/* ═══════════════════════════════════════════════════════════════
   careiti-buttons.css — one rule for how a button holds its label

   Reported: labels sitting high, low, or off to the left, and text pressed
   against the edge. The underlying cause is that button sizing and button
   content were set in different places. Earlier work here raised every
   control to a 56px tap target with `min-height`, which grows the BOX. On a
   `display:block` button the label does not move with it — it stays on its
   own line box near the top, and the button reads as "text too high".
   Padding had the same split: several controls had generous horizontal
   padding and almost none vertical, or the reverse.

   So sizing and centring are stated together here, once. Anything that
   takes a tap target also gets told where to put its label.

   Deliberate exceptions are listed at the bottom: a few controls are
   two-line, left-aligned by design, and forcing them to centre would be a
   regression, not a fix.
   ═══════════════════════════════════════════════════════════════ */

body[data-ct="app"] button,
body[data-ct="app"] .btn,
body[data-ct="app"] a.btn,
body[data-ct="app"] .btn-primary,
body[data-ct="app"] .btn-secondary,
body[data-ct="app"] .btn-teal,
body[data-ct="app"] .btn-outline,
body[data-ct="app"] .btn-sm,
body[data-ct="app"] .cta,
body[data-ct="app"] .ans-btn,
body[data-ct="app"] .choice-btn,
body[data-ct="app"] .next-btn,
body[data-ct="app"] .result-btn,
body[data-ct="app"] .claim-btn,
body[data-ct="app"] .start-btn,
body[data-ct="app"] .nb-btn,
body[data-ct="app"] .tab-btn,
body[data-ct="app"] .tab,
body[data-ct="app"] .c-btn,
body[data-ct="app"] [role="button"],
.cgs-back, .cgm-again, .cht-next, .cht-skip, .cht-open {
  /* inline-flex, not block: this is what actually centres the label inside
     a box whose height was set by min-height rather than by its content. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  text-align: center;

  /* Never against the edge. The horizontal figure is the larger one
     because CJK labels have no side bearings — text set flush looks
     tighter than Latin does at the same measure. */
  padding-block: max(10px, .5em);
  padding-inline: max(16px, .9em);

  /* A label must not be clipped by a box sized for a shorter one. */
  overflow-wrap: break-word;
  line-height: 1.3;
}

/* Full-width buttons stay full width; inline-flex would otherwise shrink
   them to their content. */
body[data-ct="app"] .btn-primary,
body[data-ct="app"] .btn-secondary,
body[data-ct="app"] .cta,
body[data-ct="app"] .ans-btn,
body[data-ct="app"] .choice-btn,
body[data-ct="app"] .next-btn,
body[data-ct="app"] .result-btn,
body[data-ct="app"] .c-btn,
.cgm-again, .cht-next, .cht-skip {
  display: flex;
  width: 100%;
}

/* Tabs share their row equally and centre within their share, so the row
   reads as one control rather than a ragged set of left-aligned labels. */
body[data-ct="app"] .tab-bar { display: flex; }
body[data-ct="app"] .tab-bar .tab-btn,
body[data-ct="app"] .tabs .tab {
  flex: 1 1 0;
  min-width: 0;
  justify-content: center;
}

/* Icon-only controls are square and centred; without this they inherit the
   generous horizontal padding above and become lozenges. */
body[data-ct="app"] .icon-btn,
body[data-ct="app"] .c-iconbtn,
body[data-ct="app"] .qr-icon-btn,
body[data-ct="app"] .font-toggle-btn,
body[data-ct="app"] .contrast-toggle-btn,
body[data-ct="app"] .notif-close,
.ca11y-handle {
  padding-inline: 0;
  padding-block: 0;
  aspect-ratio: 1 / 1;
  /* A floor at every width, not only on tablets. Removing the padding above
     let these collapse to their glyph — measured 11x19px on a phone, far
     under any usable target and well under the 44px minimum. The tablet
     layer raises this further; it must not be the only thing holding it up. */
  min-width: 44px;
  min-height: 44px;
}

/* ── Deliberate exceptions ──────────────────────────────────────
   These are two-line controls: a title with an explanation underneath.
   Centring them would centre the explanation too, which reads as a poster
   rather than a choice, and left-aligned running text is easier to read.
   They are listed rather than left to chance so a later sweep does not
   "fix" them. */
.cgm-tab {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: left;
}

/* The accessibility bar's buttons are icon + label in a row, aligned left
   so the labels line up with each other down the panel. */
body[data-ct="app"] .ca11y-btn {
  justify-content: flex-start;
  text-align: left;
}

@media (min-width: 700px) {
  body[data-ct="app"] button,
  body[data-ct="app"] .btn,
  body[data-ct="app"] .cta,
  body[data-ct="app"] .ans-btn,
  body[data-ct="app"] .choice-btn {
    padding-inline: max(20px, 1em);
  }
}

/* ── Legacy floating a11y toggles ───────────────────────────────
   .font-toggle-btn and .contrast-toggle-btn are fixed at the top-right with
   z-index 200 and duplicate what the accessibility tab already offers —
   大字模式 and 高對比. Two sets of the same control is confusing on its
   own, and these also sat on top of the memory game's 棄關 button
   (measured 29x43px of overlap), so the game could not be quit.
   The accessibility tab is on every page now, so these come off. They are
   hidden rather than deleted: other surfaces outside data-ct="app" may
   still render them. */
body[data-ct="app"] .font-toggle-btn,
body[data-ct="app"] .contrast-toggle-btn { display: none !important; }

/* An icon inside a control is decoration, never the click target. Without
   this a tap can land on the <svg> and, where the handler is bound to the
   button rather than delegated, do nothing — the tutorial's ✕ failed
   exactly this way on its last step while working on the others. */
button svg, .btn svg, a.btn svg, .cht-x svg, .cgs-back svg,
.ca11y-btn svg, .ca11y-handle svg, .cic { pointer-events: none; }

/* ── A control has to be visible before it can be read ──────────
   The text-contrast audit passed every one of these while they were
   invisible: it only ever asked whether a LABEL could be read, never
   whether the CONTROL could be seen. WCAG 1.4.11 covers the second, and
   56 controls failed it on the live site — transparent fills outlined with
   --rule, which is 1.31:1 on paper.

   Rule from here: anything pressable is either a ≥3:1 fill or carries a
   ≥3:1 border. --rule stays decorative; --edge is the one controls use. */
/* Default: EVERY pressable thing carries the control border. Enumerating
   which classes need it was the wrong shape — it left 登出, .share-btn,
   .sci-lang and the tutorial's own ✕ invisible, because a list can only
   cover the controls you thought of. Filled controls override the colour
   below; nothing has to be remembered. */
body[data-ct="app"] button,
body[data-ct="app"] .btn,
body[data-ct="app"] a.btn,
body[data-ct="app"] .cta,
body[data-ct="app"] .tab,
body[data-ct="app"] .tabbtn,
body[data-ct="app"] .tab-btn,
body[data-ct="app"] [role="button"],
body[data-ct="app"] input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
body[data-ct="app"] select,
body[data-ct="app"] textarea,
.cgs-back, .cht-open, .cht-skip, .cht-x, .cgm-again, .ca11y-btn {
  border: 1px solid var(--edge, #8E7C5E);
}

/* Controls that carry a strong fill of their own state their border against
   that fill instead — an outline in --edge around a dark teal button would
   read as a seam. */
body[data-ct="app"] .btn-primary,
body[data-ct="app"] .btn-teal,
body[data-ct="app"] .next-btn,
body[data-ct="app"] .result-btn,
body[data-ct="app"] .c-btn,
body[data-ct="app"] .claim-btn,
body[data-ct="app"] .start-btn,
body[data-ct="app"] .nb-btn,
body[data-ct="app"] button.primary,
.cgm-again, .cht-next {
  border-color: var(--teal-deep, #095A52);
}

/* Form fields also need to read as a field, not as a gap in the page —
   white on warm white is 1.02:1. */
body[data-ct="app"] input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
body[data-ct="app"] select,
body[data-ct="app"] textarea {
  background: var(--print, #FFFDF8);
}

/* The cookie banner's secondary choice was a transparent box on print. */
body[data-ct="app"] #b4d-consent .b4d-btn-nec {
  border: 1px solid var(--edge, #8E7C5E);
}

/* The accessibility tab handle had no fill and no border at all — the one
   control this audience is most likely to need was the least visible thing
   on the page. */
.ca11y-handle {
  border: 1px solid var(--edge, #8E7C5E) !important;
  background: var(--print, #FFFDF8);
}

/* Selected states keep their fill, so they must not also take the border
   treatment above and end up outlined against their own colour. */
body[data-ct="app"] .tab.active,
body[data-ct="app"] .tabbtn.active,
body[data-ct="app"] .tab-btn.active,
body[data-ct="app"] .icon-btn.on,
body[data-ct="app"] .cgm-tab[aria-pressed="true"] {
  border-color: var(--teal-deep, #095A52);
}

/* Icon-only controls were exempted from the border block above so they
   could stay square, which left them with no fill and no outline at all —
   the least visible controls on the page were the ones with no label to
   fall back on. */
body[data-ct="app"] .icon-btn,
body[data-ct="app"] .c-iconbtn,
body[data-ct="app"] .qr-icon-btn,
body[data-ct="app"] .notif-close,
body[data-ct="app"] .sci-lang,
body[data-ct="app"] .sci-langbtn-std,
.ca11y-handle, .cht-x {
  border: 1px solid var(--edge, #8E7C5E) !important;
  background: var(--print, #FFFDF8);
}
