/* ═══════════════════════════════════════════════════════════════
   careiti-a11y.css — senior accessibility layer (pairs with careiti-a11y.js)
   Loaded on every game page. Deliberately scoped so it works on pages that
   are NOT .c-scope (careiti-ui.css only scales large-font inside .c-scope).
   ═══════════════════════════════════════════════════════════════ */

/* ── Large font ───────────────────────────────────────────────
   Scales the root so em/rem-based layouts grow with it; explicit body rule
   covers pages that pin body font-size in px. */
html.large-font { font-size: 118%; }
body.large-font { font-size: 118%; }
body.large-font .ca11y-bar { font-size: 12px; }   /* keep the bar itself compact */

/* ── High contrast ────────────────────────────────────────────
   b4d-theme-toggle.js already stamps data-contrast on <html>; these rules make
   it meaningful on pages that never styled it. */
html[data-contrast="high"] body { background: #000 !important; color: #fff !important; }
html[data-contrast="high"] a { color: #7DE8DC !important; }
html[data-contrast="high"] button:not(.ca11y-btn),
html[data-contrast="high"] .btn { border: 2px solid #fff !important; }
html[data-contrast="high"] * { text-shadow: none !important; }
html[data-contrast="high"] .ca11y-bar { background: #000; border-color: #fff; }
html[data-contrast="high"] .ca11y-btn { color: #fff; }

/* ── Accessibility bar ────────────────────────────────────────
   Bottom-right, above any fixed nav; 44px minimum tap target. */
.ca11y-bar {
  position: fixed;
  bottom: calc(max(12px, env(safe-area-inset-bottom)) + 96px);
  /* Above the cookie consent banner (99999). The accessibility control is
     the last thing that should ever be covered: a low-vision reader cannot
     dismiss a banner they cannot read, and the button that makes it
     readable was sitting underneath it. */
  z-index: 100000;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 6px;
  border-radius: 18px;
  background: rgba(255, 255, 255, .94);
  border: 1px solid rgba(28, 25, 23, .10);
  box-shadow: 0 6px 22px rgba(28, 25, 23, .16);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-family: "PingFang HK", "Hiragino Sans GB", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 12px;
}

/* ── Collapsed by default, on EVERY screen ──────────────────────────
   The phone used to get a permanently-open stack of three buttons: 89x290px
   of fixed overlay, 7.8% of the screen, sitting on top of the cards it was
   floating above. A control that helps you read must not cover what you are
   reading. So the phone gets the same treatment as the tablet — one small
   tab hugging the edge, which opens into the panel on tap. */
.ca11y-handle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44px 係全站 tap target 底線，而呢粒係開大字／高對比／朗讀嘅掣 ——
     即係最需要撳得中嗰粒。40px 唔夠，而且對手震嘅長者尤其唔夠。
     （收埋狀態嘅整體外框仍然係 52px，見 .ca11y-bar 唔開嗰個 rule。） */
  width: 44px; height: 44px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--c-teal-dark, #0B6E64);
  border-radius: 12px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ca11y-handle svg { width: 21px; height: 21px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* Collapsed: only the tab. It sits half-tucked against the edge and is
   slightly translucent, so it reads as chrome rather than content — then
   comes fully forward on touch/hover/focus. */
.ca11y-bar:not([data-ca11y-open="1"]) { padding: 3px; opacity: .82; }
.ca11y-bar:not([data-ca11y-open="1"]) .ca11y-btn,
.ca11y-bar:not([data-ca11y-open="1"]) .ca11y-admin { display: none; }
.ca11y-bar:hover, .ca11y-bar:focus-within { opacity: 1; }

/* Side docking. Default right; the panel can move itself to the left for
   left-handed use or when it sits over something important. */
.ca11y-bar[data-ca11y-side="right"] {
  right: max(0px, env(safe-area-inset-right));
  left: auto;
  border-radius: 16px 0 0 16px;
}
.ca11y-bar[data-ca11y-side="left"] {
  left: max(0px, env(safe-area-inset-left));
  right: auto;
  border-radius: 0 16px 16px 0;
}

/* Housekeeping row inside the open panel: switch side, or dismiss. */
.ca11y-admin {
  display: flex; gap: 4px; justify-content: center;
  margin-top: 2px; padding-top: 5px;
  border-top: 1px solid rgba(28, 25, 23, .10);
}
.ca11y-mini {
  width: 34px; height: 34px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; border-radius: 9px;
  color: #57534E; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.ca11y-mini:hover { background: rgba(28, 25, 23, .06); color: #1C1917; }
.ca11y-mini svg { width: 16px; height: 16px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* Dismissed by the user. `hidden` alone loses to the .ca11y-bar display
   rule, which is exactly the trap recorded in the silent-frontend-bug
   notes, so state it with the weight it needs. */
.ca11y-bar[hidden] { display: none !important; }

.ca11y-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  min-width: 52px;
  min-height: 48px;
  padding: 4px 6px;
  border: none;
  border-radius: 13px;
  background: transparent;
  color: #57534E;
  font: inherit;
  line-height: 1.15;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .16s, color .16s;
}
.ca11y-btn:hover { background: rgba(13, 148, 136, .08); }
.ca11y-btn:focus-visible { outline: 3px solid #0D9488; outline-offset: 2px; }
.ca11y-btn[aria-pressed="true"] { background: #0B6E64; color: #fff; }
.ca11y-btn.speaking { background: #F59E0B; color: #fff; }

.ca11y-btn svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ca11y-btn span { font-size: 10px; font-weight: 600; letter-spacing: .2px; white-space: nowrap; }

/* Dark theme pages */
html[data-theme="dark"] .ca11y-bar { background: rgba(28, 25, 23, .92); border-color: rgba(255, 255, 255, .14); }
html[data-theme="dark"] .ca11y-btn { color: #E7E5E4; }

/* Small screens: collapse to icons so the bar never covers gameplay */
@media (max-width: 380px) {
  .ca11y-btn span { display: none; }
  .ca11y-btn { min-width: 48px; min-height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  .ca11y-btn { transition: none; }
}

@media print { .ca11y-bar { display: none !important; } }

/* ── 大字模式 levels ────────────────────────────────────────────
   One step was not enough on a tablet. The tablet layer already enlarges
   everything, so a single 1.18x on top of it still left the biggest type
   short for a low-vision reader. Level 2 (特大) adds a second step.
   .large-font stays on at every level so existing rules keep working. */
html[data-font="1"] { font-size: 118%; }
body[data-font="1"] { font-size: 118%; }
html[data-font="2"] { font-size: 138%; }
body[data-font="2"] { font-size: 138%; }
/* 第三級（超大）。院舍要求「可以再大」——第二級對深度弱視嘅院友仍然唔夠。
   到咗呢級，內容闊度已經唔夠擺兩欄，所以下面 .ca11y-xl 會迫返單欄，
   否則字大咗但每行剩返三四個字，反而更難讀。 */
html[data-font="3"] { font-size: 164%; }
body[data-font="3"] { font-size: 164%; }
/* The bar itself must not grow with the text it controls, or at 特大 it
   eats the screen it is meant to make readable. */
body.large-font .ca11y-bar { font-size: 12px; }

/* 超大：任何多欄格線迫返單欄。字放大而欄唔放闊，等於每行得三四個字，
   斷行位亂到讀唔到 —— 放大反而幫倒忙。 */
html[data-font="3"] .level-grid,
body[data-font="3"] .level-grid,
html[data-font="3"] .stats-row,
body[data-font="3"] .stats-row {
  grid-template-columns: 1fr !important;
  flex-direction: column !important;
}

/* Current level, shown on the button so the control says where it is. */
.ca11y-step {
  font-style: normal;
  font-size: 9px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: .2px;
}
.ca11y-btn[data-act="font"] .ca11y-step:empty { display: none; }
/* 三級都要睇得出而家喺邊一級 —— 掣本身唔會變色，只係個角標變字。 */
.ca11y-btn[data-act="font"].step-3 .ca11y-step { letter-spacing: 0; }

/* At 特大 a long unbreakable token (a URL, a file name, an ID) can be wider
   than a phone screen on its own, and the page starts scrolling sideways
   even though every box is correctly sized. The same string fits at 11.5px
   and does not at 19px, so this only ever shows up at the largest step —
   which is the step the readers who need it most are using. */
html[data-font="2"] p,
html[data-font="2"] li,
html[data-font="2"] td,
html[data-font="2"] dd,
html[data-font="2"] .sci-body,
body[data-font="2"] p,
body[data-font="2"] li,
body[data-font="2"] td,
body[data-font="2"] dd,
body[data-font="2"] .sci-body { overflow-wrap: anywhere; }

/* Settings switch for the floating button (我的 → 設定 → 輔助功能). */
.a11y-switch {
  flex: 0 0 auto;
  width: 52px; height: 32px;
  border: 1px solid var(--edge, #DFD3BE);
  border-radius: 999px;
  background: #E7E5E4;
  padding: 3px;
  cursor: pointer;
  transition: background .18s;
  -webkit-tap-highlight-color: transparent;
}
.a11y-switch span {
  display: block; width: 24px; height: 24px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.2);
  transition: transform .18s;
}
.a11y-switch.on { background: #0B6E64; border-color: #0B6E64; }
.a11y-switch.on span { transform: translateX(20px); }
.a11y-switch:focus-visible { outline: 3px solid #0B6E64; outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .a11y-switch, .a11y-switch span { transition: none; } }

/* While the consent banner is up, lift the tab clear of it instead of
   floating on top of it. :has() is supported everywhere this app runs; the
   z-index above keeps the control reachable even where it is not. */
body:has(#b4d-consent) .ca11y-bar {
  bottom: calc(max(12px, env(safe-area-inset-bottom)) + 96px + 210px);
}
@media (min-width: 700px) {
  body:has(#b4d-consent) .ca11y-bar { bottom: auto; }
}
