/* ============================================================================
 * styles.css — AAC communication-core prototype
 * Themeable, accessibility-first. Two themes (Madagascar / Calm neutral),
 * high-contrast mode, reduced-motion mode, four target sizes.
 * Theme art is chrome only; communication tiles keep a clean high-contrast look.
 * ==========================================================================*/

:root {
  /* sizing (overridden by data-size) */
  --tile-min: 104px;
  --fs: 1;            /* font scale */
  --gap: 10px;
  --radius: 18px;
  --focus: #1b73e8;

  /* ink = the colour of pictogram lines and tile labels */
  --ink: #15302a;

  /* surfaces */
  --app-bg: #f3ecdb;
  --panel: rgba(255, 252, 244, 0.86);
  --panel-solid: #fffdf7;
  --bar-bg: #fff8ea;
  --tab-bg: #ffffff;
  --hairline: rgba(40, 30, 10, 0.12);
  --shadow: 0 2px 7px rgba(60, 45, 15, 0.13);
  --shadow-lg: 0 14px 40px rgba(40, 30, 10, 0.30);

  /* action colours — darkened so white text passes WCAG 1.4.3 (4.5:1): speak 4.94:1, express 4.77:1 */
  --speak: #228049;  --speak-ink: #ffffff;
  --neutral: #ece5d6; --neutral-ink: #3a3327;
  --express: #cc4329; --express-ink: #ffffff;

  /* modified Fitzgerald key */
  --cat-pron: #FFD23F;  /* people / pronouns - yellow  */
  --cat-verb: #86CC8C;  /* actions          - green   */
  --cat-desc: #82C6E8;  /* describing       - blue    */
  --cat-noun: #F4A259;  /* things           - orange  */
  --cat-soc:  #F3A0C0;  /* social           - pink    */
  --cat-q:    #C7A6E6;  /* questions        - purple  */
  --cat-neg:  #ED7A6B;  /* no / stop        - red     */
  --cat-misc: #DED8CA;  /* little words     - grey    */

  /* ---- design-system v2 scales (calm-premium foundation; see docs/DESIGN-SYSTEM.md) ---- */
  /* spacing — 4/8 rhythm; paddings/margins/gaps should reference these */
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
  --space-6: 24px; --space-8: 32px; --space-12: 48px;
  /* type scale (~1.2–1.25) + line-heights + weights + tracking */
  --fz-xs: 12px; --fz-sm: 14px; --fz-base: 16px; --fz-lg: 18px;
  --fz-xl: 22px; --fz-2xl: 28px; --fz-3xl: 36px;
  --lh-tight: 1.1; --lh-snug: 1.3; --lh-normal: 1.5;
  --fw-regular: 400; --fw-medium: 500; --fw-semibold: 600; --fw-bold: 800;
  --tracking-tight: -0.01em;
  /* radius scale (legacy --radius:18px kept above for existing rules) */
  --radius-sm: 12px; --radius-md: 16px; --radius-lg: 22px; --radius-pill: 999px;
  /* motion — one shared easing; reduced-motion flattens --dur-* (see below) */
  --dur-fast: 120ms; --dur-base: 200ms; --dur-slow: 400ms;
  --ease-standard: cubic-bezier(.2, 0, .2, 1);
  --ease-emphasis: cubic-bezier(.2, .8, .2, 1);
  /* iconography — single stroke weight for every pictogram */
  --icon-stroke: 3.3;
  /* elevation scale (chromatic, theme-tinted) — consolidated here (was a 2nd :root) */
  --shadow-sm: 0 1px 2px rgba(60, 45, 15, .10);
  --shadow-md: 0 3px 10px rgba(60, 45, 15, .13), 0 1px 3px rgba(60, 45, 15, .09);
  --shadow-raise: 0 9px 22px rgba(60, 45, 15, .18), 0 2px 6px rgba(60, 45, 15, .12);
}

/* ---- target sizes ---- */
[data-size="s"]  { --tile-min: 78px;  --fs: 0.9;  --gap: 8px;  }
[data-size="m"]  { --tile-min: 104px; --fs: 1.0;  --gap: 10px; }
[data-size="l"]  { --tile-min: 132px; --fs: 1.15; --gap: 12px; }
[data-size="xl"] { --tile-min: 168px; --fs: 1.35; --gap: 14px; }

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; margin: 0; }
body {
  font-family: ui-rounded, "SF Pro Rounded", "Nunito", "Segoe UI",
    system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  color: var(--ink);
  background: var(--app-bg);
  overscroll-behavior: none;
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
  touch-action: manipulation;
}
html { overscroll-behavior: none; }

/* background scene (Madagascar theme only) */
.bgscene { position: fixed; inset: 0; z-index: -2; background: var(--app-bg); }
.bgscene::after {
  content: ""; position: fixed; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(243,236,219,0.32) 0%,
    rgba(243,236,219,0.62) 48%, rgba(243,236,219,0.86) 100%);
}
[data-theme="madagascar"] .bgscene {
  background-image: url("../img/scene.webp");
  background-size: cover; background-position: center 18%;
}
[data-theme="calm"] { --app-bg: #eef1f5; --panel: #ffffff;
  --panel-solid: #ffffff; --bar-bg: #ffffff; }
[data-theme="calm"] .bgscene { background: var(--app-bg); }
[data-theme="calm"] .bgscene::after { display: none; }
/* Calm = genuinely low-stimulation: no decorative motion, gently softened colour. */
[data-theme="calm"] .express-fab { animation: none; }
[data-theme="calm"] .grid { filter: saturate(0.85); }
/* Soft (owner directive 2026-07-08) — gentle rounded pastels app-wide, designed
   to pair with the Anan Soft symbols. Surfaces/chrome only: the Fitzgerald
   category tile colours stay constant (clinical word-finding code), and --ink
   stays the default dark for WCAG-safe labels. */
[data-theme="soft"] { --app-bg: #f6eef2; --panel: rgba(255,250,252,0.90);
  --panel-solid: #fffafc; --bar-bg: #fdf3f7; --tab-bg: #ffffff;
  --neutral: #efe3ea; --neutral-ink: #4a3c46;
  --hairline: rgba(90,60,80,0.13); --radius: 22px;
  --shadow: 0 2px 8px rgba(120,80,110,0.10); --shadow-lg: 0 14px 40px rgba(120,80,110,0.22);
  --focus: #a3477e; }
[data-theme="soft"] .bgscene { background: linear-gradient(170deg, #f8eef4, #f3ecf6 55%, #eef2f7); }
[data-theme="soft"] .bgscene::after { display: none; }
[data-theme="soft"] .express-fab { animation: none; }
[data-theme="soft"] .grid { filter: saturate(0.92); }

/* global reduced-saturation (sensory-calm) — independent of theme; mild so Fitzgerald colours stay distinct */
[data-saturation="low"] .grid { filter: saturate(0.8); }
/* Madagascar: keep the board panel near-opaque so the photo can't bleed through tile gaps. */
[data-theme="madagascar"] .board-panel { background: rgba(255,252,244,0.95); }

/* ============================================================ modern themes
   Surfaces/chrome change per theme; the Fitzgerald category tile colours stay
   constant (clinical word-finding code). Light themes work with the default dark
   ink; the dark theme keeps tile pictograms/labels dark on the pastel tiles. */

/* Ocean — cool, calm blue (light) */
[data-theme="ocean"] { --app-bg: #e4f1f8; --panel: rgba(255,255,255,0.92); --panel-solid: #ffffff;
  --bar-bg: #eef7fc; --tab-bg: #ffffff; --neutral: #d8e8f1; --neutral-ink: #234659; --focus: #0e7490; }
[data-theme="ocean"] .bgscene {
  background-image: url("../img/scene-ocean.webp"), linear-gradient(165deg, #d6ebf7, #e6f4fc 52%, #f2fbfe);
  background-size: cover, cover; background-position: center 32%, center; background-repeat: no-repeat, no-repeat; }
[data-theme="ocean"] .bgscene::after { display: block;
  background: linear-gradient(180deg, rgba(230,244,251,0.30) 0%, rgba(230,244,251,0.58) 48%, rgba(230,244,251,0.85) 100%); }
[data-theme="ocean"] .board-panel { background: rgba(255,255,255,0.95); }

/* Sunset — warm peach / rose (light) */
[data-theme="sunset"] { --app-bg: #fbe6dd; --panel: rgba(255,250,247,0.92); --panel-solid: #fffaf7;
  --bar-bg: #fdeee7; --tab-bg: #fffaf7; --neutral: #f3ddd2; --neutral-ink: #5a3a2e; --focus: #c2410c; }
[data-theme="sunset"] .bgscene {
  background-image: url("../img/scene-sunset.webp"), linear-gradient(165deg, #fbdfd0, #f7e5ec 52%, #eee7f4);
  background-size: cover, cover; background-position: center 32%, center; background-repeat: no-repeat, no-repeat; }
[data-theme="sunset"] .bgscene::after { display: block;
  background: linear-gradient(180deg, rgba(251,231,221,0.30) 0%, rgba(251,231,221,0.58) 48%, rgba(251,231,221,0.85) 100%); }
[data-theme="sunset"] .board-panel { background: rgba(255,250,247,0.95); }

/* Mono — calm neutral-grey surfaces for minimal background colour (sensory-friendly).
   The Fitzgerald tile category colours are kept intact for word-finding. */
[data-theme="mono"] { --app-bg: #ECEDEF; --panel: rgba(255,255,255,0.94); --panel-solid: #ffffff;
  --bar-bg: #F4F5F6; --tab-bg: #ffffff; --neutral: #E3E5E8; --neutral-ink: #2A2D30;
  --focus: #3949AB; --ink: #1B1D1F; --hairline: rgba(20,20,25,0.14); }
[data-theme="mono"] .bgscene { background: var(--app-bg); }
[data-theme="mono"] .bgscene::after { display: none; }

/* Midnight — true dark mode. Chrome ink goes light; tiles keep pastel + DARK ink. */
[data-theme="midnight"] { --app-bg: #0e1626; --panel: rgba(28,40,58,0.82); --panel-solid: #1b2940;
  --bar-bg: #13203a; --tab-bg: #22324e; --ink: #e7eef9; --hairline: rgba(255,255,255,0.16);
  --neutral: #2a3b57; --neutral-ink: #e7eef9; --shadow: 0 2px 8px rgba(0,0,0,0.55);
  --shadow-md: 0 8px 24px rgba(0,0,0,0.5); --shadow-lg: 0 16px 44px rgba(0,0,0,0.65); --focus: #60a5fa; }
[data-theme="midnight"] .bgscene {
  background-image: url("../img/scene-midnight.webp"), radial-gradient(130% 95% at 50% -8%, #1a2b49, #101a2d 55%, #0c1422);
  background-size: cover, cover; background-position: center 30%, center; background-repeat: no-repeat, no-repeat; }
[data-theme="midnight"] .bgscene::after { display: block;
  background: linear-gradient(180deg, rgba(14,22,38,0.30) 0%, rgba(14,22,38,0.55) 50%, rgba(14,22,38,0.80) 100%); }
[data-theme="midnight"] .splash, [data-theme="midnight"] .splash-bg { background: #0e1626; }
/* pastel tiles + chips keep DARK content so the colour code stays legible on dark surfaces
   (explicit selectors, not :where, so they out-specify the base .tile/.sym rules) */
[data-theme="midnight"] .tile, [data-theme="midnight"] .msg-chip { color: #15302a; }
[data-theme="midnight"] .tile .sym svg :where(path,line,polyline,polygon,circle,rect,ellipse),
[data-theme="midnight"] .msg-chip .sym svg :where(path,line,polyline,polygon,circle,rect,ellipse) { stroke: #15302a; }
[data-theme="midnight"] .tile .sym svg .f, [data-theme="midnight"] .tile .sym svg .f-text,
[data-theme="midnight"] .msg-chip .sym svg .f, [data-theme="midnight"] .msg-chip .sym svg .f-text { fill: #15302a; }
[data-theme="midnight"] .tile.tile-word .word-tile, [data-theme="midnight"] .msg-chip-word .lbl { color: #15302a; }
/* inactive tabs: light text on the dark tab pill; active tab: brand blue (──ink is light now) */
[data-theme="midnight"] .tab.active { background: #3b82f6; color: #fff; border-color: #3b82f6; }
[data-theme="midnight"] .tab.active .sym svg :where(path,line,polyline,polygon,circle,rect,ellipse) { stroke: #fff; }
[data-theme="midnight"] .seg button.on { background: #3b82f6; color: #fff; }
[data-theme="midnight"] .tile { border-color: rgba(0,0,0,0.22); }

/* ---------- app shell ---------- */
#app { display: flex; flex-direction: column; height: 100dvh;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); }

.appbar { display: flex; align-items: center; gap: 10px; padding: 8px 14px 6px; }
/* the wordmark is the "home" button — click/hover returns to the start hub */
.brand { display: inline-flex; align-items: center; min-width: 0; border: none; background: none;
  padding: 4px 8px; margin: -4px -4px -4px -6px; border-radius: 14px; cursor: pointer;
  transition: background var(--dur-base) var(--ease-standard); -webkit-tap-highlight-color: transparent; }
.brand:hover { background: var(--neutral); }
.brand:active { transform: scale(0.97); }
.brand-wordmark { height: clamp(38px, 9vw, 62px); width: auto; aspect-ratio: 1561 / 576;
  max-width: 46vw; display: block; background: transparent; flex-shrink: 0;
  transition: transform var(--dur-base) var(--ease-emphasis); }
.brand:hover .brand-wordmark { transform: scale(1.05); }
@media (hover: none) { .brand:hover { background: none; } .brand:hover .brand-wordmark { transform: none; } }
.spacer { flex: 1; }
.iconbtn { display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-width: 48px; min-height: 48px; padding: 0 12px; border: none; border-radius: 14px;
  background: var(--panel); color: var(--ink); font-weight: 800; font-size: 15px;
  box-shadow: var(--shadow); cursor: pointer; }
.iconbtn svg { width: 22px; height: 22px; }

/* ---------- message bar ---------- */
.msgbar { display: flex; align-items: stretch; gap: 8px; margin: 4px 12px 0;
  padding: 8px; background: var(--bar-bg); border-radius: 16px; box-shadow: var(--shadow);
  border: 1px solid var(--hairline); }
.msg-scroll { flex: 1; display: flex; align-items: center; gap: 6px; overflow-x: auto;
  min-height: 66px; padding: 2px 4px; scrollbar-width: thin; }
.msg-scroll .placeholder { color: rgba(40,30,10,0.72); font-weight: 700; font-size: 15px; padding-left: 6px;
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 400px) { .msg-scroll .placeholder { font-size: 13.5px; } }
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.msg-chip { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center;
  gap: 2px; padding: 5px 6px; background: var(--cat, #fff); border-radius: 12px;
  border: 1px solid var(--hairline); min-width: 54px; }
.msg-chip .sym { width: 34px; height: 34px; }
.msg-chip .lbl { font-size: 11px; font-weight: 800; max-width: 64px; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* glyphless words (function words / repair phrases): a clean word-chip, no lettered fallback */
.msg-chip-word { justify-content: center; padding: 8px 10px; min-height: 44px; }
.msg-chip-word .lbl { font-size: 13px; max-width: 96px; white-space: normal; overflow-wrap: anywhere;
  overflow: visible; text-overflow: clip; line-height: 1.15; }

.msg-controls { display: flex; gap: 6px; align-items: stretch; }
.ctrl { display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; min-width: 60px; border: none; border-radius: 14px; font-weight: 800;
  font-size: 13px; cursor: pointer; box-shadow: var(--shadow); padding: 6px; }
.ctrl svg { width: 24px; height: 24px; }
.ctrl.back, .ctrl.clear { background: var(--neutral); color: var(--neutral-ink); }
.ctrl.speak { background: var(--speak); color: var(--speak-ink); min-width: 96px; font-size: 16px; }
.ctrl.speak svg { width: 30px; height: 30px; }
.ctrl:active { transform: scale(0.96); }
.ctrl[disabled] { opacity: 0.6; cursor: default; box-shadow: none; }

/* ---------- tabs ---------- */
.tabs { display: flex; gap: 7px; overflow-x: auto; padding: 8px 12px 4px; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tab { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px;
  min-height: 46px; padding: 6px 14px 6px 10px; border: 2px solid var(--hairline);
  border-radius: 999px; background: var(--tab-bg); color: var(--ink); font-weight: 800;
  font-size: 15px; cursor: pointer; box-shadow: var(--shadow); }
.tab .sym { width: 26px; height: 26px; }
.tab.active { background: var(--ink); color: #fff; border-color: var(--ink); }
/* pinned "All boards" launcher — sticky at the strip's left edge so tabs scroll under it */
.boards-tab { position: sticky; left: 0; z-index: 3; background: var(--focus); color: #fff;
  border-color: var(--focus); box-shadow: 6px 0 10px -6px rgba(0,0,0,.35); }
.boards-tab .sym { width: auto; font-size: 20px; color: #fff; }
.tab.active .sym svg :where(path,line,polyline,polygon,circle,rect,ellipse) { stroke: #fff; }
.tab.active .sym svg .f { fill: #fff; }

/* ---------- board ---------- */
.board { flex: 1; overflow-y: auto; padding: 10px 12px 120px;
  -webkit-overflow-scrolling: touch; }
.board-panel { background: var(--panel); border-radius: 22px; padding: 12px;
  box-shadow: var(--shadow); border: 1px solid var(--hairline); }
.grid { display: grid; grid-template-columns: repeat(var(--cols, 6), minmax(0, 1fr)); gap: var(--gap); }
.board { overflow-x: hidden; }

.tile { position: relative; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 5px; min-height: var(--tile-min); padding: 9px 5px 7px;
  border-radius: var(--radius); background: var(--cat, #fff); color: var(--ink);
  border: 1px solid rgba(0,0,0,0.07); box-shadow: var(--shadow); cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-standard), filter var(--dur-fast) var(--ease-standard); }
.tile .cat-strip { display: none; }
/* symbol is capped by the fit target (--tile-min) so tiles compress on wide screens too,
   letting the fit/zoom controller actually shrink rows to fit every breakpoint */
.tile .sym { width: min(62%, calc(var(--tile-min, 104px) * 0.62)); max-width: 86px; aspect-ratio: 1 / 1; }
/* v224 (owner bug — applied set art miscalibrated on the board). ROOT CAUSE: the
   art carried baked-in canvas padding, so object-fit rendered the symbol small +
   top-anchored while built-in vectors (drawn edge-to-edge) read right at the same
   box. Two-part fix, both leaving tile geometry byte-identical (PD6/7):
   (1) the Anan raster sets (Classic/Bold/Soft — our own assets) are TRIMMED and
       re-centred at the source to fill their frame (tests/normalize-set-art.sh),
       so they need no CSS scaling and centre correctly;
   (2) Mulberry (2,903 third-party CC-BY-SA SVGs we don't rewrite file-by-file)
       is scaled up in-place and CLIPPED to its box, cropping the SVG's internal
       margin so the drawn symbol reads at built-in size.
   Clipping must hold on EVERY tileSym wrapper the scaled art can appear in
   (board / message bar / prediction chips / vocab editor), or the scaled art
   would spill past its box. Library preview imgs have no .tile-setart class, so
   they are untouched (owner: previews were already correct). */
.tile .sym, .msg-chip .sym, .smart-chip .sym, .smart-chip .s, .vocab-item .sym,
.ex-btn .sym, .edit-tile .sym, .spell-head .sym, .wod-word .sym, .pp-cell .pp-art { overflow: hidden; }
/* belt-and-suspenders: clip ANY wrapper that directly holds scaled Mulberry
   set-art, so a render site not in the explicit list above still can't spill
   (modern browsers; the explicit list covers the rest). */
.sym:has(> .tile-setart[src*="/mulberry/"]), .pp-art:has(> .tile-setart[src*="/mulberry/"]) { overflow: hidden; }
.tile-setart[src*="/mulberry/"] { transform: scale(1.34); }
.tile .lbl { font-weight: 800; font-size: calc(15px * var(--fs)); line-height: 1.05;
  text-align: center; letter-spacing: 0.1px; }
.tile.armed { transform: scale(0.95); filter: brightness(1.06); }

/* category colours */
.tile[data-cat="pron"] { --cat: var(--cat-pron); }
.tile[data-cat="verb"] { --cat: var(--cat-verb); }
.tile[data-cat="desc"] { --cat: var(--cat-desc); }
.tile[data-cat="noun"] { --cat: var(--cat-noun); }
.tile[data-cat="soc"]  { --cat: var(--cat-soc); }
.tile[data-cat="q"]    { --cat: var(--cat-q); }
.tile[data-cat="neg"]  { --cat: var(--cat-neg); }
.tile[data-cat="misc"] { --cat: var(--cat-misc); }
.msg-chip[data-cat="pron"] { --cat: var(--cat-pron); }
.msg-chip[data-cat="verb"] { --cat: var(--cat-verb); }
.msg-chip[data-cat="desc"] { --cat: var(--cat-desc); }
.msg-chip[data-cat="noun"] { --cat: var(--cat-noun); }
.msg-chip[data-cat="soc"]  { --cat: var(--cat-soc); }
.msg-chip[data-cat="q"]    { --cat: var(--cat-q); }
.msg-chip[data-cat="neg"]  { --cat: var(--cat-neg); }
.msg-chip[data-cat="misc"] { --cat: var(--cat-misc); }

/* pictogram rendering — uniform style for ALL symbols */
.sym svg { width: 100%; height: 100%; display: block; }
.sym svg :where(path, line, polyline, polygon, circle, rect, ellipse) {
  fill: none; stroke: var(--ink); stroke-width: var(--icon-stroke);
  stroke-linecap: round; stroke-linejoin: round; }
.sym svg .f { fill: var(--ink); stroke: none; }
.sym svg .f-text { fill: var(--ink); stroke: none; font-family: inherit; }

/* ---------- body map ---------- */
.bodywrap { display: flex; gap: 14px; flex-wrap: wrap; }
.bodymap { flex: 1 1 260px; min-width: 240px; display: flex; align-items: center; justify-content: center;
  background: #fff; border-radius: 18px; padding: 10px; box-shadow: var(--shadow); }
.bodymap svg { width: 100%; max-width: 320px; height: auto; }
.bodymap .region { fill: var(--cat-noun); stroke: var(--ink); stroke-width: 2.4; cursor: pointer;
  transition: fill 0.1s ease; opacity: 0.92; }
.bodymap .region:hover, .bodymap .region.armed { fill: #ef6a4b; }
.bodymap .region:focus-visible { outline: none; fill: #ef6a4b; stroke-width: 4; }
.bodymap .outline { fill: #fff; stroke: var(--ink); stroke-width: 2.6; }
.body-states { flex: 2 1 360px; }
.body-states h3, .bodyparts-hint { font-size: 14px; font-weight: 800; margin: 2px 0 8px; opacity: 0.7; }

/* ---------- express launcher + overlay ---------- */
.express-fab { position: fixed; z-index: 45;
  right: max(14px, env(safe-area-inset-right)); bottom: max(16px, env(safe-area-inset-bottom));
  display: inline-flex; align-items: center; gap: 9px; padding: 14px 20px 14px 16px;
  min-height: 66px; border: 3px solid #fff; border-radius: 999px; cursor: pointer;
  background: var(--express); color: var(--express-ink); font-weight: 800; font-size: 18px;
  box-shadow: 0 8px 22px rgba(0,0,0,0.30); animation: fabpulse 2.6s ease-in-out infinite; }
.express-fab .sym { width: 30px; height: 30px; }
.express-fab .sym svg :where(path,line,polyline,polygon,circle,rect,ellipse) { stroke: #fff; stroke-width: 3.6; }
@keyframes fabpulse { 0%,100% { box-shadow: 0 8px 22px rgba(0,0,0,0.30); }
  50% { box-shadow: 0 8px 22px rgba(0,0,0,0.30), 0 0 0 8px rgba(239,106,75,0.25); } }

.overlay { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center;
  justify-content: center; padding: 12px; background: rgba(25,18,6,0.46);
  transition: opacity var(--dur-base) var(--ease-standard), visibility var(--dur-base) var(--ease-standard); }
/* smooth fade + subtle rise instead of an instant display:none pop */
.overlay.hidden { opacity: 0; visibility: hidden; pointer-events: none; }
.overlay > * { transition: transform var(--dur-base) var(--ease-emphasis), opacity var(--dur-base) var(--ease-standard); }
.overlay.hidden > * { transform: translateY(16px) scale(0.985); opacity: 0; }
[data-motion="reduced"] .overlay, [data-motion="reduced"] .overlay > * { transition: none; }
/* board content cross-fades gently when switching boards (less jarring than an instant swap) */
/* H5-2: was opacity 0.3→1 with NO movement — a partial-opacity blip that read as an
   instant cut when switching board categories (the most frequent "section navigation").
   Now a full fade + a subtle rise so the switch is actually perceptible, while staying
   in the fast communicator-zone tempo (--dur-base ≈ 200ms). Reduced-motion collapses it. */
@keyframes boardFade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.board.board-in .board-panel { animation: boardFade var(--dur-base) var(--ease-emphasis); }
[data-motion="reduced"] .board.board-in .board-panel { animation: none; }
/* "Show big" partner-read view — fills the screen with the message in large text */
#bigmsg-overlay { padding: 0; z-index: 70; }   /* above other overlays (e.g. opened from Type view) */
.bigmsg-sheet { align-self: stretch; width: 100%; position: relative; display: flex;
  align-items: center; justify-content: center; padding: 9vmin 6vmin; box-sizing: border-box;
  background: var(--panel-solid); }
.bigmsg-text { font-family: inherit; font-weight: 800; line-height: 1.08; text-align: center;
  color: var(--ink); word-break: break-word; max-width: 100%; background: none; border: 0;
  padding: 0; cursor: pointer; }
.bigmsg-text:focus-visible { outline: 3px solid var(--focus); outline-offset: 6px; border-radius: 8px; }
.bigmsg-hint { position: absolute; left: 0; right: 0; bottom: max(18px, env(safe-area-inset-bottom));
  text-align: center; font-size: 14px; font-weight: 700; color: var(--ink); opacity: .55; padding: 0 16px; }
.bigmsg-close { position: absolute; top: 16px; right: 16px; min-width: 52px; min-height: 52px;
  padding: 0; border-radius: 50%; border: 1px solid var(--hairline); background: var(--tab-bg);
  color: var(--ink); font-size: 26px; line-height: 1; cursor: pointer; }
.bigmsg-close:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.sheet { background: var(--panel-solid); border-radius: 26px; box-shadow: var(--shadow-lg);
  width: min(960px, 100%); max-height: calc(100dvh - 24px); overflow: auto; padding: 16px 16px 20px; }
.sheet-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.sheet-head h2 { font-size: 22px; margin: 0; flex: 1; }
.close-btn { min-width: 56px; min-height: 56px; border: none; border-radius: 16px;
  background: var(--neutral); color: var(--neutral-ink); font-weight: 800; font-size: 22px;
  cursor: pointer; box-shadow: var(--shadow); }

.ex-group-label { font-weight: 800; font-size: 15px; opacity: 0.72; margin: 6px 2px 8px; }
.ex-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 14px; }
.ex-btn { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 9px; min-height: 132px; border: 3px solid rgba(255,255,255,0.55); border-radius: 22px;
  color: #fff; font-weight: 800; font-size: 19px; text-align: center; cursor: pointer;
  padding: 12px 8px; box-shadow: var(--shadow); }
.ex-btn .sym { width: 46px; height: 46px; }
.ex-btn .sym svg :where(path,line,polyline,polygon,circle,rect,ellipse) { stroke: #fff; stroke-width: 3.4; }
.ex-btn .sym svg .f { fill: #fff; }
.ex-btn.urgent { background: #cf4631; }
.ex-btn.calm   { background: #2f828d; }
.ex-btn.respond { background: #4f5663; }
.ex-btn.yes    { background: #228049; }
.ex-btn.emergency { background: #a8201a; font-weight: 900; }
[data-contrast="high"] .ex-btn { border: 3px solid #000; }
[data-contrast="high"] .ex-said { color: #000; }
[data-contrast="high"] .ex-group-label { opacity: 1; color: #000; }
.ex-btn:active { transform: scale(0.97); }
.ex-said { text-align: center; font-size: 24px; font-weight: 800; min-height: 30px;
  margin: 2px 0 14px; color: var(--ink); }
.ex-said.show { animation: pop 0.3s ease; }
@keyframes pop { from { transform: scale(0.8); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* ---------- settings ---------- */
.set-row { display: flex; align-items: center; gap: 12px; padding: 12px 4px;
  border-bottom: 1px solid var(--hairline); flex-wrap: wrap; }
.set-row .label { flex: 1 1 180px; font-weight: 800; font-size: 16px; }
.set-row .hint { flex-basis: 100%; font-size: 13px; opacity: 0.6; font-weight: 600; }
.seg { display: inline-flex; gap: 4px; background: var(--neutral); border-radius: 12px; padding: 4px; flex-wrap: wrap; }
.seg button { min-width: 52px; min-height: 44px; border: none; border-radius: 9px; background: transparent;
  font-weight: 800; font-size: 14px; cursor: pointer; color: var(--neutral-ink); padding: 0 12px; }
.seg button.on { background: var(--ink); color: #fff; }
.toggle { position: relative; width: 64px; height: 38px; border-radius: 999px; border: none;
  background: #c9c2b3; cursor: pointer; transition: background 0.15s ease; flex: 0 0 auto; }
.toggle::after { content: ""; position: absolute; top: 4px; left: 4px; width: 30px; height: 30px;
  border-radius: 50%; background: #fff; transition: transform 0.15s ease; box-shadow: var(--shadow); }
.toggle.on { background: var(--speak); }
.toggle.on::after { transform: translateX(26px); }
.set-row select, .set-row input[type="range"] { flex: 1 1 200px; min-height: 44px; font-size: 15px;
  font-family: inherit; border-radius: 10px; border: 2px solid var(--hairline); padding: 4px 8px; background: #fff; }
.set-note { font-size: 12.5px; opacity: 0.62; line-height: 1.5; margin-top: 14px; font-weight: 600; }
.set-section { font-size: 13px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.6px;
  opacity: 0.5; margin: 18px 2px 2px; }

/* ---------- onboarding ---------- */
.onb { text-align: center; padding: 22px 18px 24px; max-width: 520px; }
.onb img.hero { width: 168px; height: 168px; object-fit: contain;
  filter: drop-shadow(0 10px 18px rgba(0,0,0,0.18)); margin-bottom: 4px; }
.onb h1 { font-size: 28px; margin: 6px 0 2px; }
.onb .wt { font-size: 13px; opacity: 0.55; font-weight: 700; margin-bottom: 12px; }
.onb p { font-size: 16px; line-height: 1.5; opacity: 0.82; margin: 0 0 18px; }
.onb .start { min-height: 64px; padding: 0 40px; border: none; border-radius: 18px;
  background: var(--speak); color: #fff; font-weight: 800; font-size: 20px; cursor: pointer;
  box-shadow: var(--shadow-lg); }
.onb .skip { display: block; margin: 14px auto 0; background: none; border: none; font-size: 14px;
  opacity: 0.6; text-decoration: underline; cursor: pointer; font-weight: 700; color: var(--ink); }

/* ---------- celebration ---------- */
.celebrate { position: fixed; inset: 0; z-index: 70; pointer-events: none;
  display: flex; align-items: center; justify-content: center; }
.celebrate.hidden { display: none; }
.celebrate img { width: 150px; height: 150px; object-fit: contain; animation: cheer 1.1s ease; }
@keyframes cheer { 0% { transform: translateY(40px) scale(0.6); opacity: 0; }
  30% { transform: translateY(0) scale(1.08); opacity: 1; }
  75% { transform: translateY(0) scale(1); opacity: 1; }
  100% { transform: translateY(-10px) scale(0.95); opacity: 0; } }
.spark { position: absolute; width: 14px; height: 14px; border-radius: 50%; opacity: 0; }
.celebrate.go .spark { animation: spark 1s ease forwards; }
@keyframes spark { 0% { transform: translate(0,0) scale(0.4); opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) scale(1); opacity: 0; } }

/* ---------- switch scanning highlight ---------- */
.scan-active { outline: 6px solid var(--focus) !important; outline-offset: -3px;
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--focus) 38%, transparent) !important; z-index: 5; }
.scan-group { outline: 5px dashed var(--focus) !important; outline-offset: -2px; }

/* ---------- high contrast ---------- */
[data-contrast="high"] { --ink: #000; --app-bg: #ffffff; --panel: #ffffff;
  --panel-solid: #ffffff; --bar-bg: #ffffff; --hairline: #000; --neutral: #eee; --neutral-ink: #000; }
[data-contrast="high"] .bgscene, [data-contrast="high"] .bgscene::after { background: #fff; }
[data-contrast="high"] .tile { background: #fff !important; border: 3px solid #000; }
[data-contrast="high"] .tile .cat-strip { display: block; position: absolute; top: 0; left: 0; right: 0;
  height: 12px; border-radius: var(--radius) var(--radius) 0 0; background: var(--cat); border-bottom: 2px solid #000; }
[data-contrast="high"] .tile .sym { margin-top: 8px; }
[data-contrast="high"] .tab { border-width: 3px; }
[data-contrast="high"] .board-panel, [data-contrast="high"] .msgbar { border: 2px solid #000; }
[data-contrast="high"] .iconbtn, [data-contrast="high"] .ctrl, [data-contrast="high"] .close-btn { border: 2px solid #000; }
[data-contrast="high"] .msg-chip { background: #fff !important; border: 2px solid #000; }
[data-contrast="high"] .msg-scroll .placeholder { color: #000; }
/* darker Speak/Express in high-contrast mode → AAA (7.7:1 / 7.4:1) on white text */
[data-contrast="high"] { --speak: #155f31; --express: #9c2f17; }

/* ---------- reduced motion ---------- */
[data-motion="reduced"] *, [data-motion="reduced"] *::before, [data-motion="reduced"] *::after {
  animation: none !important; transition: none !important; }
/* flatten motion tokens too, so any token-driven transition auto-collapses */
[data-motion="reduced"] { --dur-fast: 0.01ms; --dur-base: 0.01ms; --dur-slow: 0.01ms; }
@media (prefers-reduced-motion: reduce) {
  :root { --dur-fast: 0.01ms; --dur-base: 0.01ms; --dur-slow: 0.01ms; }
  .express-fab { animation: none; }
  * { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

/* phones */
@media (max-width: 560px) {
  .ctrl.speak { min-width: 76px; }
  .sheet { border-radius: 20px; }
}

/* ============================================================================
 * Splash / loading screen
 * ==========================================================================*/
/* ---- promotional intro film (H5+ owner request) — sits above everything, fades to splash ---- */
.intro { position: fixed; inset: 0; z-index: 2000; background: #0b0b12; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  opacity: 1; transition: opacity .5s ease; }
.intro[hidden] { display: none; }
.intro.intro-out { opacity: 0; pointer-events: none; }
.intro-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: #0b0b12; }
.intro-veil { position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to bottom, rgba(0,0,0,.28) 0%, rgba(0,0,0,0) 26%, rgba(0,0,0,0) 55%, rgba(0,0,0,.66) 100%); }
.intro-loading { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.intro-spin { width: 44px; height: 44px; border-radius: 50%; border: 4px solid rgba(255,255,255,.25);
  border-top-color: #fff; animation: introSpin .9s linear infinite; }
.intro.playing .intro-loading { opacity: 0; }
@keyframes introSpin { to { transform: rotate(360deg); } }
.intro-brand { position: absolute; left: 0; right: 0; bottom: clamp(48px, 12vh, 130px);
  display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 0 24px;
  opacity: 0; transform: translateY(14px); animation: introBrandIn .9s var(--ease-emphasis, cubic-bezier(.2,.8,.2,1)) .5s forwards; }
.intro-wordmark { width: min(60vw, 340px); height: auto; filter: drop-shadow(0 4px 18px rgba(0,0,0,.5)); }
.intro-tag { color: #fff; font-weight: 800; font-size: clamp(18px, 4.4vw, 30px); letter-spacing: .01em;
  text-shadow: 0 2px 14px rgba(0,0,0,.6); }
@keyframes introBrandIn { to { opacity: 1; transform: none; } }
.intro-skip { position: absolute; top: calc(env(safe-area-inset-top, 0px) + 16px); right: 16px; z-index: 2;
  min-height: 44px; padding: 0 18px; border: 0; border-radius: 999px; cursor: pointer;
  background: rgba(255,255,255,.92); color: #14121c; font-weight: 800; font-size: 15px;
  box-shadow: 0 4px 16px rgba(0,0,0,.3); }
.intro-sound { position: absolute; top: calc(env(safe-area-inset-top, 0px) + 16px); left: 16px; z-index: 2;
  width: 44px; height: 44px; border: 0; border-radius: 50%; cursor: pointer; font-size: 20px; line-height: 44px;
  background: rgba(255,255,255,.92); box-shadow: 0 4px 16px rgba(0,0,0,.3); }
.intro-sound.muted { animation: introSoundPulse 1.6s ease-in-out infinite; }
@keyframes introSoundPulse { 0%,100% { box-shadow: 0 4px 16px rgba(0,0,0,.3); } 50% { box-shadow: 0 4px 16px rgba(0,0,0,.3), 0 0 0 8px rgba(255,255,255,.18); } }
[data-motion="reduced"] .intro-brand, [data-motion="reduced"] .intro-spin, [data-motion="reduced"] .intro-sound { animation: none; }
[data-motion="reduced"] .intro-brand { opacity: 1; transform: none; }

.splash { position: fixed; inset: 0; z-index: 1000; overflow: hidden;
  display: flex; align-items: center; justify-content: center; background: #FBE7C6;
  transition: opacity 0.6s ease, visibility 0.6s ease; }
.splash.hide { opacity: 0; visibility: hidden; pointer-events: none; }
.splash[hidden] { display: none; }

/* base fallback behind the parallax scene (the inline SVG scene paints over this,
   so no external image is needed — fully offline with zero extra assets) */
.splash-bg { position: absolute; inset: 0;
  background: linear-gradient(180deg, #FBDDB2 0%, #F7CD8E 42%, #EBD89C 66%, #CDE4B2 100%); }

/* animated parallax scene — crisp, code-driven backdrop (replaces the ambient video) */
.splash-scene { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.scene-svg { width: 100%; height: 100%; display: block; }
.player { will-change: transform; }
.sc-sun { transform-box: fill-box; transform-origin: center; animation: scSun 7s ease-in-out infinite; }
.cloud-a { animation: scCloudA 26s ease-in-out infinite; }
.cloud-b { animation: scCloudB 32s ease-in-out infinite; }
.sc-tree { transform-box: fill-box; transform-origin: bottom center; animation: scSway 7.5s ease-in-out infinite; }
.sc-water { animation: scShimmer 6s ease-in-out infinite; }
.sc-bird { animation: scBird 24s linear infinite; }
@keyframes scSun { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.045); opacity: 0.9; } }
@keyframes scCloudA { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(36px); } }
@keyframes scCloudB { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(-30px); } }
@keyframes scSway { 0%, 100% { transform: rotate(-1.3deg); } 50% { transform: rotate(1.3deg); } }
@keyframes scShimmer { 0%, 100% { opacity: 0.24; transform: translateX(0); } 50% { opacity: 0.5; transform: translateX(16px); } }
@keyframes scBird { 0% { transform: translateX(-160px); } 100% { transform: translateX(1360px); } }
[data-theme="calm"] .splash-scene { filter: saturate(0.58) brightness(1.04); }
[data-motion="reduced"] .splash-scene .sc-sun,
[data-motion="reduced"] .splash-scene .cloud-a,
[data-motion="reduced"] .splash-scene .cloud-b,
[data-motion="reduced"] .splash-scene .sc-tree,
[data-motion="reduced"] .splash-scene .sc-water,
[data-motion="reduced"] .splash-scene .sc-bird { animation: none; }

/* update toast */
/* sits above the Express FAB (same safe-area base + 66px FAB + gap) so the tappable
   Undo/OK button is never covered on narrow screens */
.toast { position: fixed; left: 50%; bottom: calc(max(16px, env(safe-area-inset-bottom)) + 78px);
  transform: translateX(-50%); z-index: 80; display: flex; align-items: center; gap: 12px;
  background: var(--ink); color: #fff; padding: 10px 12px 10px 16px; border-radius: 14px;
  box-shadow: var(--shadow-lg); font-weight: 700; font-size: 15px; max-width: calc(100% - 24px);
  /* H5-2: was created via createElement with NO transition — appeared instantly.
     A gentle rise+fade on insert; keeps the translateX(-50%) centering in both keyframes
     so it lands exactly on the base transform (no end-jump). Reduced-motion off. */
  animation: toastIn var(--dur-base) var(--ease-emphasis); }
@keyframes toastIn { from { opacity: 0; transform: translateX(-50%) translateY(12px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
[data-motion="reduced"] .toast { animation: none; }
.toast button { min-height: 40px; padding: 0 16px; border: none; border-radius: 10px;
  background: #2f9e57; color: #fff; font-weight: 800; cursor: pointer; }

/* themed in-app dialogs (PWA-safe replacement for prompt/confirm/alert) */
.dlg-backdrop { position: fixed; inset: 0; z-index: 2000; display: flex; align-items: center;
  justify-content: center; padding: 20px; background: rgba(20, 14, 4, 0.45); backdrop-filter: blur(2px); }
.dlg { width: 100%; max-width: 380px; background: var(--panel-solid, var(--panel)); color: var(--ink);
  border: 1px solid var(--hairline); border-radius: 18px; box-shadow: var(--shadow-lg); padding: 20px;
  display: flex; flex-direction: column; gap: 12px; }
.dlg-title { margin: 0; font-size: 19px; font-weight: 800; color: var(--ink); }
.dlg-msg { margin: 0; font-size: 15px; line-height: 1.5; opacity: 0.85; }
.dlg-input { min-height: 48px; font-size: 17px; padding: 0 14px; border: 2px solid var(--hairline);
  border-radius: 12px; background: #fff; color: #15302a; }
.dlg-input:focus-visible { outline: 3px solid var(--focus); outline-offset: 1px; border-color: var(--focus); }
.dlg-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 4px; flex-wrap: wrap; }
.dlg-btn { min-height: 48px; padding: 0 18px; border: none; border-radius: 12px; font-weight: 800;
  font-size: 15px; cursor: pointer; box-shadow: var(--shadow-sm); }
.dlg-cancel { background: var(--neutral); color: var(--neutral-ink); }
.dlg-ok { background: var(--speak); color: #fff; }
.dlg-ok.dlg-danger { background: var(--express); color: #fff; }
.dlg-btn:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
[data-contrast="high"] .dlg { border: 2px solid #000; }
[data-contrast="high"] .dlg-btn { border: 2px solid #000; }

.splash-center { position: relative; z-index: 2; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: clamp(16px, 4.5vh, 44px);
  padding: 24px; text-align: center; }

.splash-wordmark { display: block; opacity: 0; animation: splashRise 0.9s ease 0.2s forwards;
  width: clamp(250px, 66vw, 520px); height: auto; aspect-ratio: 1561 / 576;
  filter: drop-shadow(0 6px 16px rgba(31, 56, 100, 0.18)); background: transparent; }
.splash-mascot { display: block; opacity: 0; animation: splashRise 0.9s ease 0.95s forwards; }
.splash-mascot img { display: block; width: clamp(150px, 30vw, 300px); height: auto;
  transform-origin: center bottom; filter: drop-shadow(0 14px 24px rgba(31, 56, 100, 0.22));
  animation: splashBob 4.5s ease-in-out 2s infinite; }

.splash-progress { position: relative; width: clamp(150px, 42vw, 250px); height: 8px;
  border-radius: 999px; background: rgba(31, 56, 100, 0.14); overflow: hidden;
  opacity: 0; animation: splashFadeIn 0.8s ease 1.5s forwards; }
.splash-progress span { position: absolute; top: 0; left: 0; height: 100%; width: 45%;
  border-radius: 999px;
  background: linear-gradient(90deg, #2E9E5B, #0E9C8A, #F4B400, #F4673E);
  animation: splashSweep 1.9s ease-in-out infinite; }

@keyframes splashRise { from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); } }
@keyframes splashFadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes splashBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
/* H4-1: was `left: -45% -> 100%` (layout-triggering); same visual sweep via transform (composited).
   Percentages are relative to the element's OWN width (45% of parent), so -45%(parent) = -100%(own)
   and 100%(parent) = (100/45)*100%(own) ~= 222%(own). */
@keyframes splashSweep { 0% { transform: translateX(-100%); } 100% { transform: translateX(222%); } }

/* Calm neutral theme: neutral backdrop, keep wordmark + mascot. */
[data-theme="calm"] .splash, [data-theme="calm"] .splash-bg { background: #eef1f5; }
[data-theme="calm"] .splash-progress span { background: linear-gradient(90deg, #8aa0b6, #b9c6d3, #8aa0b6); }

/* Reduced motion (sensory accessibility): static scene, static mascot, calm indicator. */
[data-motion="reduced"] .splash-wordmark,
[data-motion="reduced"] .splash-mascot,
[data-motion="reduced"] .splash-progress { animation: none; opacity: 1; }
[data-motion="reduced"] .splash-mascot img { animation: none; }
[data-motion="reduced"] .splash-progress span { animation: none; left: 0; width: 100%; opacity: 0.55; }
@media (prefers-reduced-motion: reduce) {
  .splash-wordmark, .splash-mascot, .splash-progress { animation: none; opacity: 1; }
  .splash-mascot img { animation: none; }
  .splash-progress span { animation: none; left: 0; width: 100%; opacity: 0.55; }
}

/* ---------- private profile avatar (local only, never branding) ---------- */
.avatar-btn { width: 48px; height: 48px; border-radius: 50%; border: 2px solid var(--hairline);
  background: var(--panel); box-shadow: var(--shadow); cursor: pointer; padding: 0; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center; color: var(--ink); flex: 0 0 auto; }
.avatar-btn img { width: 100%; height: 100%; object-fit: cover; display: none; }
.avatar-btn svg { width: 24px; height: 24px; }
.avatar-btn.has-photo img { display: block; }
.avatar-btn.has-photo svg { display: none; }
[data-contrast="high"] .avatar-btn { border: 2px solid #000; }

.avatar-preview { width: 84px; height: 84px; border-radius: 50%; object-fit: cover;
  border: 2px solid var(--hairline); background: var(--neutral); flex: 0 0 auto; }
.profile-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* communicator-profile switcher */
.profile-list { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.profile-item { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pf-pick { flex: 1 1 200px; display: flex; align-items: center; gap: 10px; min-height: 48px;
  padding: 0 14px; border: 2px solid var(--hairline); border-radius: 14px; background: var(--panel);
  color: var(--ink); font-weight: 800; font-size: 16px; cursor: pointer; text-align: left;
  box-shadow: var(--shadow-sm); }
.pf-pick:hover { background: var(--neutral); }
.pf-pick:disabled { cursor: default; }
.profile-item.active .pf-pick { border-color: var(--focus); background: rgba(27, 115, 232, 0.10); }
.pf-dot { width: 12px; height: 12px; border-radius: 50%; background: var(--hairline); flex: 0 0 auto; }
.profile-item.active .pf-dot { background: var(--focus); }
.pf-name { flex: 1 1 auto; }
.pf-cur { font-size: 11.5px; font-weight: 800; color: var(--focus); text-transform: uppercase; letter-spacing: 0.5px; }
.pf-edit, .pf-del { min-height: 44px; padding: 0 13px; border: none; border-radius: 12px;
  background: var(--panel); color: var(--ink); font-weight: 700; font-size: 14px; cursor: pointer;
  box-shadow: var(--shadow-sm); }
.pf-edit:hover { background: var(--neutral); }
.pf-del { color: #b23b3b; }
.pf-del:hover { background: #f7e4e4; }
.pf-add { margin-top: 12px; }

/* ============================================================================
 * Splash v2 — interactive, animated, HD + launch/config menu
 * ==========================================================================*/
/* floating leaves */
.splash-leaves { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 1; }
.splash-leaves span { position: absolute; bottom: -40px; width: 22px; height: 22px;
  border-radius: 0 100% 0 100%; background: linear-gradient(135deg, #6CC287, #2E9E5B);
  opacity: 0; animation: splashLeaf linear infinite; }
.splash-leaves span:nth-child(1) { left: 7%;  width: 18px; height: 18px; animation-duration: 12s; animation-delay: 0s; }
.splash-leaves span:nth-child(2) { left: 21%; width: 26px; height: 26px; animation-duration: 15s; animation-delay: 2s; }
.splash-leaves span:nth-child(3) { left: 35%; width: 14px; height: 14px; animation-duration: 10s; animation-delay: 4s; }
.splash-leaves span:nth-child(4) { left: 48%; width: 22px; height: 22px; animation-duration: 14s; animation-delay: 1s; }
.splash-leaves span:nth-child(5) { left: 62%; width: 16px; height: 16px; animation-duration: 13s; animation-delay: 5s; }
.splash-leaves span:nth-child(6) { left: 74%; width: 28px; height: 28px; animation-duration: 16s; animation-delay: 3s; }
.splash-leaves span:nth-child(7) { left: 86%; width: 18px; height: 18px; animation-duration: 11s; animation-delay: 6s; }
.splash-leaves span:nth-child(8) { left: 93%; width: 20px; height: 20px; animation-duration: 14s; animation-delay: 2.5s; }
@keyframes splashLeaf {
  0% { opacity: 0; transform: translateY(0) rotate(0deg); }
  12% { opacity: 0.7; } 88% { opacity: 0.5; }
  100% { opacity: 0; transform: translateY(-118vh) rotate(220deg); } }

/* quick toggles */
.splash-quick { position: absolute; z-index: 5; display: flex; gap: 8px;
  top: max(14px, env(safe-area-inset-top)); right: max(14px, env(safe-area-inset-right)); }
.splash-chip { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 14px;
  border: none; border-radius: 999px; background: rgba(255, 255, 255, 0.8); color: #1f3864;
  font-weight: 800; font-size: 14px; cursor: pointer; box-shadow: var(--shadow); backdrop-filter: blur(4px); }
.splash-chip svg { width: 20px; height: 20px; }
.splash-chip[aria-pressed="false"] { opacity: 0.5; }

/* interactive mascot (now a button) */
.splash-mascot { background: none; border: none; padding: 0; cursor: pointer; }
.splash-mascot img { width: clamp(160px, 32vw, 320px); }
.splash-mascot.wave img { animation: splashWave 0.9s ease; }
@keyframes splashWave { 0%, 100% { transform: rotate(0deg); } 25% { transform: rotate(-6deg); }
  50% { transform: rotate(5deg); } 75% { transform: rotate(-3deg); } }

/* determinate progress (filled over time by JS) */
.splash-progress span { left: 0; width: 0; animation: none;
  background: linear-gradient(90deg, #2E9E5B, #0E9C8A, #F4B400, #F4673E); }
@keyframes splashLoad { from { width: 0; } to { width: 100%; } }

.splash-hint { margin: 2px 0 0; font-weight: var(--fw-semibold); font-size: 15px; color: #1f3864; opacity: 0.85; }
.splash-continue { min-height: 56px; padding: 0 38px; border: none; border-radius: 16px;
  background: #2f9e57; color: #fff; font-weight: 800; font-size: 18px; cursor: pointer;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.22); opacity: 0; transform: translateY(8px);
  transition: opacity 0.4s ease, transform 0.4s ease; }
.splash-continue[hidden] { display: none; }
.splash-continue.show { opacity: 1; transform: translateY(0); animation: contPulse 2.2s ease-in-out 0.5s infinite; }
@keyframes contPulse { 0%, 100% { box-shadow: 0 8px 20px rgba(0,0,0,0.22); }
  50% { box-shadow: 0 8px 20px rgba(0,0,0,0.22), 0 0 0 8px rgba(47,158,87,0.22); } }
[data-theme="calm"] .splash-chip { background: rgba(255,255,255,0.92); }

/* ---------- launch / configuration menu ---------- */
.launch { position: fixed; inset: 0; z-index: 990; display: flex; align-items: safe center; justify-content: center;
  padding: 16px; overflow: auto; transition: opacity 0.5s ease, visibility 0.5s ease;
  background: linear-gradient(160deg, #FBE7C6 0%, #F4D6A8 55%, #AEDBBB 100%); }
.launch-grid .set-row { padding: 9px 4px; }
.launch-grid .set-row:first-child { border-top: 1px solid var(--hairline); }
[data-theme="calm"] .launch { background: linear-gradient(160deg, #eef1f5, #e3e8ee); }
.launch.hide { opacity: 0; visibility: hidden; pointer-events: none; }
.launch[hidden] { display: none; }
.launch-card { width: min(560px, 100%); max-height: calc(100dvh - 32px); overflow: auto;
  background: var(--panel-solid); border-radius: 26px; box-shadow: var(--shadow-lg);
  padding: 22px 20px 24px; animation: launchIn 0.5s ease; }
@keyframes launchIn { from { opacity: 0; transform: translateY(18px) scale(0.98); } to { opacity: 1; transform: none; } }
.launch-head { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 4px; margin-bottom: 8px; }
.launch-head img { width: 76px; height: 76px; object-fit: contain; filter: drop-shadow(0 8px 14px rgba(31,56,100,0.16)); }
.launch-head h1 { margin: 4px 0 0; font-size: 24px; }
.launch-head p { margin: 0; font-size: 15px; opacity: 0.75; }
.launch-remember { display: flex; align-items: center; gap: 10px; padding: 14px 4px 4px; font-weight: 700; font-size: 15px; }
.launch-remember input { width: 22px; height: 22px; }
.launch-start { width: 100%; min-height: 66px; margin-top: 14px; border: none; border-radius: 18px;
  background: #2f9e57; color: #fff; font-weight: 800; font-size: 21px; cursor: pointer; box-shadow: var(--shadow-lg); }
.launch-start:active { transform: scale(0.99); }

/* start hub — big destination cards (easy navigation in/out of the app) */
.launch-dest { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 8px 0 4px; }
.launch-dest-card { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-height: 90px; padding: 14px 10px; border: 2px solid var(--hairline); border-radius: 18px;
  background: var(--panel); color: var(--ink); cursor: pointer; box-shadow: var(--shadow); text-align: center;
  transition: transform .08s ease; }
.launch-dest-card:active { transform: scale(.98); }
.launch-dest-card .ld-ic { font-size: 30px; line-height: 1; }
.launch-dest-card .ld-t { font-weight: 900; font-size: 17px; }
.launch-dest-card .ld-d { font-size: 12.5px; opacity: .7; font-weight: 600; }
.launch-dest-card.primary { grid-column: 1 / -1; background: var(--speak); color: #fff; border-color: var(--speak); min-height: 86px; }
.launch-dest-card.primary .ld-d { color: #fff; opacity: .92; }
.launch-dest-card.need { background: var(--express); color: #fff; border-color: var(--express); }
.launch-dest-card.need .ld-d { color: #fff; opacity: .92; }
.launch-setup { margin-top: 14px; border-top: 1px solid var(--hairline); padding-top: 6px; }
.launch-setup summary { cursor: pointer; font-weight: 800; font-size: 16px; padding: 10px 4px; list-style: none; }
.launch-setup summary::-webkit-details-marker { display: none; }
.launch-setup[open] summary { opacity: .75; }

/* reduced motion: calm everything on the loading flow */
[data-motion="reduced"] .splash-leaves { display: none; }
[data-motion="reduced"] .splash-mascot img { animation: none; }
[data-motion="reduced"] .splash-continue.show { animation: none; opacity: 1; transform: none; }
[data-motion="reduced"] .launch-card { animation: none; }
@media (prefers-reduced-motion: reduce) {
  .splash-leaves { display: none; }
  .splash-mascot img { animation: none; }
  .splash-continue.show { animation: none; opacity: 1; transform: none; }
  .launch-card { animation: none; }
}

/* ============================================================= insights / editor / report */
.iconbtn.danger { background: var(--cat-neg); color: #fff; }
.iconbtn.primary { background: var(--ink); color: #fff; }

.stat-summary { display: flex; flex-wrap: wrap; gap: 10px; margin: 12px 0 4px; }
.stat-card { flex: 1 1 96px; background: var(--neutral); border-radius: 14px; padding: 12px 10px; text-align: center; }
.stat-card b { display: block; font-size: 25px; line-height: 1.05; color: var(--ink); }
.stat-card span { font-size: 11px; font-weight: var(--fw-semibold); opacity: .68; text-transform: uppercase; letter-spacing: .3px; }

.cc-celebrate { display: flex; flex-direction: column; gap: 6px; margin: 2px 0 12px; }
.cc-note { background: color-mix(in srgb, var(--cat-verb) 18%, var(--panel)); border-radius: 12px; padding: 10px 12px; font-size: 14px; font-weight: var(--fw-semibold); color: var(--ink); }

.edit-grid { display: flex; flex-wrap: wrap; gap: 10px; margin: 10px 0; }
.edit-tile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  min-width: 88px; min-height: 88px; padding: 8px; border-radius: 14px; border: 2px solid var(--hairline);
  background: var(--panel-solid); color: var(--ink); cursor: pointer; transition: transform var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard); }
.edit-tile .sym { width: 40px; height: 40px; }
.edit-tile .lbl { font-weight: 700; font-size: 13px; text-align: center; }
.edit-tile.picked { border-color: var(--focus); transform: scale(1.06); box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 30%, transparent); }

/* ENG-33 function-coding hand-correction editor */
.func-edit { margin: 6px 0 4px; }
.func-edit summary { cursor: pointer; font-weight: 700; color: var(--ink); padding: 4px 0; }
.func-row { display: flex; align-items: center; gap: 8px; margin: 4px 0; }
.func-word { flex: 0 0 auto; min-width: 96px; font-size: 13px; }
.func-row select { flex: 1 1 auto; }

/* ENG-4 board heatmap — real board layout, cells shaded by lifetime use (log scale) */
.heat-grid { display: grid; grid-template-columns: repeat(var(--hcols, 6), 1fr); gap: 4px; margin: 8px 0 6px; }
.heat-cell { position: relative; border: 1px solid var(--hairline); border-radius: 8px; cursor: pointer;
  min-height: 34px; padding: 3px 2px; font: inherit; font-size: 10.5px; font-weight: 700; color: var(--ink);
  background: color-mix(in srgb, var(--cat-verb) calc(var(--heat, 0) * 85%), var(--panel-solid));
  overflow: hidden; }
.heat-cell span { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; opacity: .85; }
.heat-cell.heat-zero { border-style: dashed; opacity: .66; }
.heat-cell:focus-visible { outline: 3px solid var(--focus); outline-offset: 1px; }

.gen-list { display: flex; flex-direction: column; gap: 8px; margin: 6px 0 12px; }
.gen-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; background: var(--neutral); border-radius: 12px; padding: 8px 12px; }
.gen-prompt { font-size: 14px; font-weight: 600; }
.gen-acts { display: flex; gap: 6px; flex-shrink: 0; }

.stat-list { margin: 6px 0 10px; }
.stat-row { display: grid; grid-template-columns: 104px 1fr 42px; align-items: center; gap: 10px; margin: 7px 0; }
.stat-row .k { font-weight: 800; font-size: 13.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--ink); }
.stat-row .track { height: 16px; background: rgba(0,0,0,.07); border-radius: 8px; overflow: hidden; }
/* H4-2b: animate transform: scaleX() off a full-width bar instead of the layout-triggering
   `width` (same root-cause discipline as the theme fix). The .track already clips + rounds
   (overflow:hidden; border-radius:8px), so the bar needs no radius of its own — no scaleX
   corner distortion. transform-origin:left grows the fill from the left edge. */
.stat-row .bar { height: 100%; width: 100%; transform-origin: left center; background: var(--ink); transition: transform .35s var(--ease-standard); }
.stat-row .bar[data-cat="pron"] { background: var(--cat-pron); }
.stat-row .bar[data-cat="verb"] { background: var(--cat-verb); }
.stat-row .bar[data-cat="desc"] { background: var(--cat-desc); }
.stat-row .bar[data-cat="noun"] { background: var(--cat-noun); }
.stat-row .bar[data-cat="soc"]  { background: var(--cat-soc); }
.stat-row .bar[data-cat="q"]    { background: var(--cat-q); }
.stat-row .bar[data-cat="neg"]  { background: var(--cat-neg); }
.stat-row .bar[data-cat="body"] { background: var(--cat-noun); }
.stat-row .bar[data-cat="misc"] { background: var(--cat-misc); }
.stat-row .v { text-align: right; font-weight: var(--fw-semibold); font-size: 13px; opacity: .65; }
/* H4-5 — Command Center 2.0 interactive trend line */
.trend-wrap { margin: 8px 0 2px; }
.trend-svg { width: 100%; height: auto; display: block; overflow: visible; }
.trend-line { fill: none; stroke: var(--cat-verb); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.trend-area { fill: var(--cat-verb); opacity: .13; }
.trend-dot { fill: var(--panel-solid); stroke: var(--cat-verb); stroke-width: 2; cursor: pointer; }
.trend-dot:hover { r: 4.5; }
.trend-dot.on { fill: var(--cat-verb); }
.trend-dot:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.trend-axis { display: flex; justify-content: space-between; font-size: .72rem; font-weight: 700; opacity: .7; margin-top: 3px; }
.trend-axis .trend-max { opacity: .95; }
.trend-readout { margin-top: 4px; }
.trend-drill:empty { display: none; }
.drill-words { margin-top: 4px; padding: 8px 10px; background: var(--neutral); border-radius: 10px; }
.range-seg { margin-bottom: 8px; }
/* warm, calm empty states (shared across Insights / Learn / search / vocab) */
.stat-empty { opacity: .74; font-weight: var(--fw-medium); padding: var(--space-6) var(--space-4);
  text-align: center; line-height: var(--lh-normal); color: var(--ink);
  font-size: var(--fz-base); max-width: 42ch; margin-inline: auto; }

.hours { display: flex; align-items: flex-end; gap: 3px; height: 58px; margin: 8px 0 2px; }
.hours .h { flex: 1; background: var(--cat-desc); border-radius: 3px 3px 0 0; min-height: 2px; }
.hours-axis { display: flex; justify-content: space-between; font-size: 10px; font-weight: var(--fw-medium); opacity: .55; }
.days { display: flex; align-items: flex-end; gap: 8px; height: 78px; margin: 8px 0 2px; }
.days .d { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 5px; height: 100%; }
.days .d .b { width: 100%; background: var(--cat-verb); border-radius: 6px 6px 0 0; min-height: 2px; }
.days .d span { font-size: 10.5px; font-weight: var(--fw-semibold); opacity: .6; }

/* vocabulary editor */
.vocab-item { display: grid; grid-template-columns: 36px 1fr auto; align-items: center; gap: 10px;
  padding: 8px 6px; border-bottom: 1px solid rgba(0,0,0,.06); }
.vocab-item .sym { width: 34px; height: 34px; display: grid; place-items: center; }
.vocab-item .sym svg { width: 100%; height: 100%; }
.vocab-item .meta b { font-size: 14px; color: var(--ink); }
.vocab-item .meta small { display: block; font-size: 11px; opacity: .6; font-weight: var(--fw-medium); }
.vocab-item .row-actions { display: flex; gap: 6px; }
.field { display: block; margin: 10px 0; }
.field label { display: block; font-weight: 800; font-size: 13px; margin-bottom: 4px; color: var(--ink); }
.field input[type="text"], .field select, .field textarea {
  width: 100%; padding: 11px 12px; border-radius: 12px; border: 2px solid rgba(0,0,0,.12);
  font: inherit; background: var(--panel-solid); color: var(--ink); }
.field textarea { min-height: 60px; resize: vertical; }
.lock-note { background: var(--neutral); border-radius: 12px; padding: 12px 14px; font-weight: 700;
  font-size: 13px; margin: 8px 0; }
.cat-swatch { display: inline-block; width: 14px; height: 14px; border-radius: 4px; vertical-align: middle; margin-right: 6px; }

/* clinical report (also print stylesheet) */
.report-doc { background: #fff; color: #1a1a1a; border-radius: 14px; padding: 22px; line-height: 1.5; }
.report-doc h1 { font-size: 22px; margin: 0 0 2px; }
.report-doc h2 { font-size: 15px; margin: 20px 0 6px; border-bottom: 2px solid #e2e2e2; padding-bottom: 3px; }
.report-doc .muted { color: #666; font-size: 12.5px; }
.report-doc table { width: 100%; border-collapse: collapse; font-size: 13px; margin: 6px 0; }
.report-doc th, .report-doc td { text-align: left; padding: 6px 8px; border-bottom: 1px solid #eee; }
.report-doc th { background: #f4f4f4; }
.report-grid { display: flex; flex-wrap: wrap; gap: 10px; margin: 8px 0; }
.report-grid .c { flex: 1 1 110px; border: 1px solid #e5e5e5; border-radius: 10px; padding: 10px; text-align: center; }
.report-grid .c b { display: block; font-size: 22px; }
.report-grid .c span { font-size: 11px; color: #666; text-transform: uppercase; letter-spacing: .3px; }
@media print {
  body * { visibility: hidden !important; }
  #report-overlay, #report-overlay * { visibility: visible !important; }
  #report-overlay { position: absolute; inset: 0; background: #fff; overflow: visible; display: block; padding: 0; }
  #report-overlay .sheet { box-shadow: none; max-height: none; max-width: 100%; border-radius: 0; }
  .report-noprint { display: none !important; }
  /* ENG-5 paper backup pack — takes over the print output when active */
  body.printing-pack #report-overlay, body.printing-pack #report-overlay * { visibility: hidden !important; }
  body.printing-pack #paper-pack, body.printing-pack #paper-pack * { visibility: visible !important; }
  body.printing-pack #paper-pack { position: absolute; inset: 0; background: #fff; }
  /* ENG-34 communication passport — same print-takeover pattern */
  body.printing-passport #report-overlay, body.printing-passport #report-overlay * { visibility: hidden !important; }
  body.printing-passport #passport, body.printing-passport #passport * { visibility: visible !important; }
  body.printing-passport #passport { position: absolute; inset: 0; background: #fff; }
}
/* ENG-34 passport layout (screen-hidden; structured for print) */
#passport { display: none; }
body.printing-passport #passport { display: block; padding: 8mm; }
.pass-head { display: flex; align-items: center; gap: 6mm; padding: 0 0 5mm; border-bottom: 2px solid #222; }
.pass-photo { width: 30mm; height: 30mm; object-fit: cover; border-radius: 4mm; border: 1px solid #ccc; }
.pass-name { font-size: 26pt; margin: 0; color: #000; }
.pass-sub { font-size: 13pt; color: #555; }
.pass-facts { font-size: 12pt; color: #000; margin: 5mm 0; line-height: 1.5; }
.pass-sec { margin: 4mm 0; page-break-inside: avoid; }
.pass-sec h2 { font-size: 14pt; margin: 0 0 1.5mm; color: #1a5e3a; }
.pass-body { font-size: 12pt; color: #000; line-height: 1.5; }
.pass-empty { color: #999; font-style: italic; }
.pass-foot { margin-top: 6mm; padding-top: 3mm; border-top: 1px solid #ccc; font-size: 9pt; color: #666; }
/* ENG-5 pack layout (screen-hidden; structured for print) */
#paper-pack { display: none; }
body.printing-pack #paper-pack { display: block; }
.pp-board { page-break-after: always; padding: 6mm 4mm; }
.pp-title { font-size: 18pt; margin: 0 0 4mm; color: #000; }
.pp-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 2.5mm; }
.pp-cell { border: 1.2px solid #444; border-radius: 3mm; padding: 2mm 1mm; text-align: center;
  page-break-inside: avoid; background: #fff; }
.pp-cell .pp-art { display: block; height: 15mm; }
.pp-cell .pp-art img, .pp-cell .pp-art svg { max-height: 15mm; max-width: 90%; }
.pp-cell .pp-art .sym-emoji { font-size: 11mm; line-height: 15mm; }
.pp-cell .pp-lbl { display: block; font-weight: 800; font-size: 10pt; color: #000; }
.pp-foot { margin-top: 4mm; font-size: 8pt; color: #555; }

/* ENG-8 command palette — keyboard-first jump-to-anything (Cmd/Ctrl+K) */
.cmd-backdrop { position: fixed; inset: 0; z-index: 1100; background: rgba(20,16,10,.42);
  display: flex; align-items: flex-start; justify-content: center; padding: 12vh 16px 16px;
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
.cmd-box { width: min(560px, 100%); max-height: 66vh; display: flex; flex-direction: column;
  background: var(--panel-solid, #fff); border: 1px solid var(--hairline); border-radius: 16px;
  box-shadow: 0 24px 64px rgba(30,20,10,.34); overflow: hidden; }
.cmd-input { border: 0; border-bottom: 1px solid var(--hairline); background: transparent; color: var(--ink);
  font: inherit; font-size: 17px; padding: 16px 18px; outline: none; }
.cmd-input:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
.cmd-list { overflow-y: auto; padding: 6px; }
.cmd-item { display: flex; align-items: baseline; gap: 10px; padding: 9px 12px; border-radius: 10px; cursor: pointer; }
.cmd-item.sel { background: color-mix(in srgb, var(--accent, #2f9e57) 16%, transparent); }
.cmd-kind { flex: 0 0 auto; font-size: 10px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  opacity: .6; min-width: 42px; }
.cmd-t { flex: 1 1 auto; font-weight: 700; color: var(--ink); }
.cmd-s { flex: 0 0 auto; font-size: 12px; opacity: .6; }
.cmd-empty { padding: 18px; text-align: center; opacity: .7; }
.cmd-foot { border-top: 1px solid var(--hairline); padding: 8px 14px; font-size: 11px; opacity: .6; }
.tile.cmd-flash { animation: cmdFlash 1.4s ease-out; }
@keyframes cmdFlash { 0%,100% { box-shadow: none; } 20%,60% { box-shadow: 0 0 0 4px var(--focus, #2f9e57); } }
[data-motion="reduced"] .cmd-backdrop { backdrop-filter: none; -webkit-backdrop-filter: none; }
[data-motion="reduced"] .tile.cmd-flash { animation: none; outline: 3px solid var(--focus, #2f9e57); }

/* ENG-23 goal progress state chip */
.goal-row .goal-state { margin-left: auto; font-size: 11px; padding: 3px 10px; text-transform: capitalize; }

/* v217 immersive library — set pages, symbol view, compare strip */
.lib-back { margin-right: auto; }
.lib-sheet .sheet-head h2 { text-transform: none; }
.lib-tile-btn { font: inherit; color: var(--ink); background: var(--panel-solid); border: 1px solid var(--hairline);
  border-radius: 12px; padding: 8px 4px 6px; cursor: pointer; position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 4px; }
.lib-tile-btn:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.lib-tile-btn .lib-art { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; }
.lib-tile-btn .lib-art img, .lib-tile-btn .lib-art svg { max-width: 100%; max-height: 100%; }
.lib-badge { position: absolute; top: 4px; right: 4px; font-size: 9px; font-weight: 800; letter-spacing: .03em;
  background: color-mix(in srgb, var(--focus, #2f9e57) 14%, var(--panel-solid)); color: var(--ink);
  border-radius: 99px; padding: 1px 6px; }
.lib-count { font-weight: 600; }
.lib-boardprev-strip { display: flex; gap: 8px; margin: 6px 0 10px; flex-wrap: wrap; }
.lib-detail { display: flex; align-items: center; justify-content: center; min-height: 170px;
  background: var(--panel-solid); border: 1px solid var(--hairline); border-radius: 16px; margin: 6px 0; }
.lib-detail img, .lib-detail .sym { width: 150px; height: 150px; }
.lib-detail .sym svg { width: 100%; height: 100%; }
.lib-detail-badge { text-align: center; }
.lib-compare { display: flex; gap: 10px; flex-wrap: wrap; margin: 8px 0; }
.lib-compare .lib-tile-btn { width: 92px; }
.lib-view-in { animation: popIn var(--dur-fast, .16s) var(--ease-emphasis, ease-out); }
[data-motion="reduced"] .lib-view-in { animation: none; }

/* morphology popover */
.morph-pop { position: fixed; z-index: 90; display: flex; gap: 6px; padding: 8px;
  background: var(--panel-solid); border-radius: 14px; box-shadow: var(--shadow-lg);
  border: 2px solid var(--ink);
  /* H5-2: was created via createElement with NO transition — popped in instantly.
     A quick scale+fade on insert (communicator-fast tempo) so grammar forms feel like
     they open, not snap. Animation plays on element insertion; reduced-motion off. */
  animation: popIn var(--dur-fast) var(--ease-emphasis); transform-origin: top center; }
@keyframes popIn { from { opacity: 0; transform: scale(0.92); } to { opacity: 1; transform: none; } }
[data-motion="reduced"] .morph-pop { animation: none; }
.morph-opt { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 62px;
  padding: 9px 10px; border: none; border-radius: 10px; background: var(--neutral); color: var(--ink);
  font: inherit; cursor: pointer; }
.morph-opt b { font-size: 16px; }
.morph-opt small { font-size: 10px; opacity: .65; font-weight: var(--fw-medium); }
.morph-opt:hover, .morph-opt:focus { background: var(--cat-verb); outline: none; }
.tile.placeholder { background: transparent; border: 2px dashed rgba(0,0,0,.08); box-shadow: none;
  pointer-events: none; }
.sym-emoji { font-size: 2.1em; line-height: 1; }
/* emoji tiles scale with the S/M/L/XL size control (was fixed 2.1em → too small on fringe boards) */
.tile .sym-emoji { font-size: clamp(22px, calc(var(--tile-min, 104px) * 0.5), 72px); line-height: 1;
  display: grid; place-items: center; width: 100%; height: min(62%, calc(var(--tile-min, 104px) * 0.62)); }

/* built-in show/hide list */
details.builtins { margin: 6px 0; border: 1px solid rgba(0,0,0,.1); border-radius: 12px; padding: 4px 10px; }
details.builtins summary { font-weight: 800; cursor: pointer; padding: 6px 2px; color: var(--ink); }
.hide-row { display: flex; align-items: center; gap: 10px; padding: 6px 4px; font-weight: 700; font-size: 14px; }
.hide-row input { width: 20px; height: 20px; }

.report-notes { width: 100%; min-height: 90px; border: 1px solid #ccc; border-radius: 8px; padding: 10px;
  font: inherit; resize: vertical; }

/* ===== emergency card (gated: EMERGENCY_ENABLED) — FIXED high-contrast, theme-independent.
   Above every surface incl. the splash (z-1000) and dialogs (z-2000): an emergency must win. */
#emergency-overlay { z-index: 3000; background: rgba(8, 10, 12, .78); }
.emergency-sheet { background: #10151a; color: #fff; width: min(720px, 96vw); max-height: 94dvh; overflow: auto;
  border-radius: 22px; padding: 18px 18px 22px; border: 3px solid #fff; }
.em-title { font-size: 26px; font-weight: 900; letter-spacing: .5px; display: flex; justify-content: space-between; align-items: center; }
.em-title .close-btn { color: #fff; border-color: #fff; }
.em-said { min-height: 30px; font-size: 19px; font-weight: 800; color: #ffd60a; }
.em-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 12px 0; }
.em-btn { min-height: 76px; border-radius: 18px; border: 3px solid #fff; font: inherit; font-weight: 900; font-size: 22px;
  cursor: pointer; background: #ffd60a; color: #10151a; }
.em-btn.danger { background: #ff453a; color: #fff; }
.em-btn.yes { background: #30d158; color: #05310f; }
.em-btn.no { background: #ff453a; color: #fff; }
.em-btn:active, .em-pain button:active { transform: scale(.97); }
.em-lab { font-size: 14px; font-weight: 800; text-transform: uppercase; letter-spacing: .6px; opacity: .9; margin-top: 8px; }
.em-pain { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; margin: 10px 0; }
.em-pain button { min-height: 64px; font-size: 26px; font-weight: 900; border-radius: 14px; border: 3px solid #fff;
  background: #1c2430; color: #fff; cursor: pointer; }
.em-med { background: #fff; color: #10151a; border-radius: 14px; padding: 14px; margin-top: 12px; font-weight: 700; font-size: 15.5px; }
.em-med h3 { font-size: 14px; text-transform: uppercase; letter-spacing: .5px; margin: 0 0 6px; }
.em-med .row { margin: 4px 0; line-height: 1.45; }
.em-med .k { opacity: .6; font-size: 12px; text-transform: uppercase; letter-spacing: .4px; }
.em-close { min-height: 56px; width: 100%; margin-top: 14px; border-radius: 14px; font: inherit; font-weight: 900; font-size: 19px;
  background: #fff; color: #10151a; border: none; cursor: pointer; }
.em-fields { display: flex; flex-direction: column; gap: 8px; }
.sos-pill { position: absolute; top: max(12px, env(safe-area-inset-top)); left: max(12px, env(safe-area-inset-left));
  z-index: 8; min-height: 44px; min-width: 64px; padding: 10px 16px; border-radius: 999px; background: #d1332a; color: #fff;
  font: inherit; font-weight: 900; letter-spacing: .8px; border: 2px solid #fff; cursor: pointer; box-shadow: var(--shadow-md); }
@media (prefers-reduced-motion: reduce) { .em-btn:active, .em-pain button:active { transform: none; } }

/* second language (bilingual) — dual-label tiles + the appbar language chip */
.tile .lbl2 { display: block; font-size: .68em; font-weight: 700; opacity: .62; line-height: 1.15; }
.lang2-chip .l2t { font-weight: 800; font-size: 13px; }
.lang2-chip.on { background: var(--focus); color: #fff; }
[data-locked="on"] #lang2-chip { display: inline-flex; }  /* switching languages IS communication — never locked */

/* smart suggestion bar */
.smartbar { display: flex; gap: 8px; overflow-x: auto; padding: 8px 4px 4px; -webkit-overflow-scrolling: touch;
  min-height: 52px; }  /* reserved: chips appearing/refreshing never move the board below (motor-plan stability) */
.smartbar.predict-off { display: none; min-height: 0; }
.smart-chip.pin-chip { border-color: var(--cat-soc); }
.smart-chip.routine-chip { border-color: var(--focus); }  /* time-aware board suggestion (tap = open, hold = dismiss) */

/* H2-1 motor access: extra tile spacing for hand stability (gated: H2_ACCESS_ENABLED) */
[data-pad="s"] .grid { gap: calc(clamp(6px, 1.6vw, var(--gap)) * 1.5); }
[data-pad="m"] .grid { gap: calc(clamp(6px, 1.6vw, var(--gap)) * 2.2); }
[data-pad="l"] .grid { gap: calc(clamp(6px, 1.6vw, var(--gap)) * 3); }

/* H2-2 keyguard: exact physical grid (mm × calibrated px/mm); zoom off while active */
[data-kg="on"] .grid { grid-template-columns: repeat(var(--cols), var(--kg-tile)) !important;
  gap: var(--kg-gap) !important; justify-content: center; }
[data-kg="on"] .grid .tile { width: var(--kg-tile) !important; height: var(--kg-tile) !important;
  min-width: 0 !important; min-height: 0 !important; }
[data-kg="on"] .zoom-bar { display: none; }
.kg-cal-bar { height: 26px; background: var(--focus); color: #fff; border-radius: 6px;
  display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 800; margin: 6px 0; }

/* H2-7 practice mode (gated): unmistakable practice frame + gentle feedback */
.practice-frame { border: 3px dashed var(--focus); border-radius: 18px; padding: 12px; position: relative; margin-top: 8px; }
.practice-ribbon { display: inline-block; background: var(--focus); color: #fff; font-size: 11px; font-weight: 900;
  letter-spacing: .6px; padding: 4px 12px; border-radius: 999px; margin-bottom: 8px; }
.practice-grid .tile { cursor: pointer; }
@keyframes practiceNope { 0%,100% { transform: translateX(0); } 30% { transform: translateX(-4px); } 60% { transform: translateX(4px); } }
.tile.practice-nope { animation: practiceNope .45s ease; }
[data-motion="reduced"] .tile.practice-nope { animation: none; opacity: .7; }
.learn-streak { font-weight: 800; font-size: 15px; margin: 6px 0; }
.wod-card { display: flex; align-items: center; gap: 12px; background: var(--panel-solid); border: 1px solid var(--hairline);
  border-radius: 16px; padding: 12px 14px; margin: 8px 0; box-shadow: var(--shadow-md); }
.wod-lab { font-size: 11px; font-weight: 900; text-transform: uppercase; letter-spacing: .5px; opacity: .6; }
.wod-word { display: flex; align-items: center; gap: 8px; font-size: 18px; }
.wod-word .sym svg { width: 1.6em; height: 1.6em; }

/* H2-5 partner window (gated): mirrored upside-down read-only message strip */
/* Partner window mirror strip — docked IN-FLOW just under the header, inside the
   content/board area (fix 2026-07-07: was position:fixed;top:0 above the logo).
   Only the MESSAGE flips 180° (for a partner across a flat tablet); a small
   right-way-up label tells the carer it's a deliberate mirror, not a glitch. */
#partner-strip { flex: 0 0 auto; pointer-events: none;
  display: flex; align-items: center; gap: 10px;
  background: var(--panel-solid); color: var(--ink);
  border: 1px solid var(--hairline); border-radius: 12px; box-shadow: var(--shadow-sm);
  min-height: 44px; margin: 6px 10px 2px; padding: 6px 14px; overflow: hidden; }
#partner-strip .ps-label { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 700; letter-spacing: .01em;
  color: var(--neutral-ink, #6f6690); opacity: .78; white-space: nowrap; }
#partner-strip .ps-label svg { width: 15px; height: 15px; flex: 0 0 auto; }
#partner-strip .ps-text { flex: 1 1 auto; min-width: 0; transform: rotate(180deg);
  text-align: center; font-size: clamp(18px, 3.2vw, 26px); font-weight: 800;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 480px) { #partner-strip .ps-label-txt { display: none; } }  /* icon-only on phones */

/* H2-4 word-by-word highlight while speaking (gated) */
.msg-chip.speaking-now { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 12px; }
[data-motion="reduced"] .msg-chip.speaking-now { outline-width: 4px; }

/* H2-3 symbol search results in the vocabulary editor (gated) */
.sym-results { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 4px; }
.sym-pick { display: flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 10px;
  border: 2px solid rgba(0,0,0,.14); background: var(--panel-solid); color: var(--ink); font: inherit;
  font-weight: 700; font-size: 13.5px; cursor: pointer; }
.sym-pick.on { border-color: var(--focus); box-shadow: 0 0 0 2px var(--focus); }
.sym-pick .sym img { width: 1.6em; height: 1.6em; display: block; object-fit: contain; }
.pack-badge { font-size: 10px; font-weight: 900; text-transform: uppercase; letter-spacing: .4px;
  background: #ece5d6; color: #3a3327; border-radius: 999px; padding: 2px 7px; }
.sym-pick .sym svg { width: 1.4em; height: 1.4em; display: block; }

/* H2-2 dwell-to-select: filling ring while a hovered button arms */
@keyframes dwellFill { from { box-shadow: 0 0 0 2px var(--focus); } to { box-shadow: 0 0 0 8px var(--focus); } }
.dwell-arm { animation: dwellFill var(--dwell-ms, 1000ms) linear forwards; position: relative; z-index: 3; }
[data-motion="reduced"] .dwell-arm { animation: none; box-shadow: 0 0 0 5px var(--focus); }
.smart-chip.pin-chip .s { font-size: 1em; }
.smart-chip { flex: 0 0 auto; display: flex; align-items: center; gap: 7px; padding: 8px 14px;
  border-radius: 999px; border: 2px solid var(--cat, rgba(0,0,0,.12)); background: var(--panel-solid);
  color: var(--ink); font: inherit; font-weight: 800; font-size: 15px; cursor: pointer; }
.smart-chip .s { font-size: 1.3em; }
.smart-chip:active { transform: scale(.96); }
.smart-chip[data-kind="recent"] { border-style: dashed; }
.smartbar-lab { flex: 0 0 auto; align-self: center; font-size: 11px; font-weight: var(--fw-semibold); opacity: .5;
  text-transform: uppercase; letter-spacing: .4px; padding-right: 2px; }
@media (prefers-reduced-motion: reduce) { .stat-row .bar { transition: none; } .smart-chip:active { transform: none; } }
.smart-chip .s svg { width: 1.3em; height: 1.3em; display: block; }
.smart-chip .s .sym-emoji { font-size: 1em; }

/* ===================================================== typing view (Type to talk) */
.type-sheet { display: flex; flex-direction: column; }
.type-text { width: 100%; min-height: 84px; max-height: 30vh; resize: none; border: 2px solid rgba(0,0,0,.14);
  border-radius: 14px; padding: 14px 16px; font: inherit; font-size: clamp(20px, 3.4vw, 28px); line-height: 1.35;
  color: var(--ink); background: var(--panel-solid); }
.type-text:focus { outline: 3px solid var(--cat-desc); outline-offset: 1px; }
.type-preds { display: flex; gap: 8px; overflow-x: auto; padding: 10px 0 2px; min-height: 30px; }
.pred-chip { flex: 0 0 auto; padding: 8px 16px; border-radius: 999px; border: 2px solid var(--cat-desc);
  background: var(--panel-solid); color: var(--ink); font: inherit; font-weight: 800; font-size: 16px; cursor: pointer; }
.pred-chip:active { transform: scale(.96); }
.type-actions { display: flex; gap: 8px; margin: 8px 0 10px; }
.type-act { flex: 1; padding: 13px 8px; border: none; border-radius: 13px; background: var(--neutral);
  color: var(--ink); font: inherit; font-weight: 800; font-size: 16px; cursor: pointer; }
.type-act.speak { background: var(--ink); color: #fff; }
.type-act:active { transform: scale(.98); }
.kbd { display: flex; flex-direction: column; gap: 7px; }
.kbd-row { display: flex; gap: 6px; justify-content: center; }
.key { flex: 1 1 0; min-width: 0; height: clamp(44px, 8.5vw, 60px); border: none; border-radius: 11px;
  background: var(--panel-solid); box-shadow: 0 2px 0 rgba(0,0,0,.14); color: var(--ink);
  font: inherit; font-weight: 800; font-size: clamp(17px, 3.4vw, 23px); cursor: pointer; text-transform: lowercase; }
.key:active { transform: translateY(1px); box-shadow: 0 1px 0 rgba(0,0,0,.14); background: var(--neutral); }
.key.wide { flex: 1.6 1 0; }
.key.space { flex: 5 1 0; text-transform: lowercase; font-size: 15px; color: var(--neutral-ink); }
.key.del { background: var(--cat-neg); color: #fff; box-shadow: 0 2px 0 rgba(0,0,0,.2); }
.key.punct { flex: .8 1 0; color: var(--neutral-ink); }
[data-contrast="high"] .key { border: 2px solid var(--ink); }
@media (prefers-reduced-motion: reduce) { .key:active, .pred-chip:active, .type-act:active { transform: none; } }

/* ===================================================== learn module */
.learn-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-top: 12px; }
.learn-card { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; text-align: left;
  padding: 18px; border: none; border-radius: 18px; background: var(--panel-solid); box-shadow: var(--shadow-md);
  color: var(--ink); font: inherit; cursor: pointer; }
.learn-card:active { transform: scale(.985); }
.learn-card .lc-ic { font-size: 34px; line-height: 1; }
.learn-card .lc-t { font-weight: 900; font-size: 18px; }
.learn-card .lc-d { font-size: 13.5px; opacity: .7; font-weight: 600; }
@media (max-width: 460px) { .learn-grid { grid-template-columns: 1fr; } }
/* all-boards overview grid */
.boards-grid { grid-template-columns: repeat(3, 1fr); }
.boards-card { align-items: center; text-align: center; gap: 8px; min-height: 96px; justify-content: center; }
.boards-card .lc-ic { font-size: 32px; }
.boards-card .lc-ic svg { width: 38px; height: 38px; }
.boards-card .lc-ic .sym-emoji { font-size: 34px; }
.boards-card.current { border-color: var(--focus); background: rgba(27, 115, 232, 0.10); }
@media (max-width: 460px) { .boards-grid { grid-template-columns: repeat(2, 1fr); } }

/* speaking indicator — the Speak button gently pulses while a message is being spoken,
   so the output is visible (noisy rooms, hearing difficulty, partner confirmation) */
@keyframes speakPulse { 0%,100% { box-shadow: 0 0 0 0 rgba(34,128,73,0); } 50% { box-shadow: 0 0 0 7px rgba(34,128,73,0.30); } }
html.is-speaking .ctrl.speak { animation: speakPulse 1s ease-in-out infinite; }
[data-motion="reduced"].is-speaking .ctrl.speak { animation: none; box-shadow: 0 0 0 4px rgba(34,128,73,0.35); }
@media (prefers-reduced-motion: reduce) { html.is-speaking .ctrl.speak { animation: none; box-shadow: 0 0 0 4px rgba(34,128,73,0.35); } }

/* boards overview — search across every word (theme-aware tokens) */
.boards-search { margin: 0 0 12px; }
.boards-search input { width: 100%; box-sizing: border-box; min-height: 48px; padding: 12px 16px;
  font: inherit; font-size: 17px; border: 2px solid var(--hairline); border-radius: 12px;
  background: var(--tab-bg); color: var(--ink); }
.boards-search input:focus-visible { outline: none; border-color: var(--focus); }
.boards-results { display: grid; gap: 8px; max-height: 58vh; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.board-result { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; min-height: 52px; padding: 10px 16px; text-align: left; cursor: pointer;
  border: 1px solid var(--hairline); border-radius: 12px; background: var(--tab-bg); color: var(--ink); }
.board-result:hover, .board-result:focus-visible { border-color: var(--focus); background: var(--neutral); }
.board-result .br-w { font-weight: 800; font-size: 17px; }
.board-result .br-b { font-size: 13px; font-weight: var(--fw-semibold); opacity: .7; }
/* search jump: flash the matched tile so the word is easy to spot on arrival */
@keyframes tileFound { 0% { box-shadow: 0 0 0 0 var(--focus); } 22% { box-shadow: 0 0 0 6px var(--focus); } 100% { box-shadow: 0 0 0 0 rgba(0,0,0,0); } }
.tile.tile-found { animation: tileFound 1.5s ease-out; position: relative; z-index: 2; }
/* reduced motion: a static ring instead of a pulse (still removed after ~1.6s by JS) */
[data-motion="reduced"] .tile.tile-found { animation: none; box-shadow: 0 0 0 4px var(--focus); }
/* modeling mode: gentle tab pulse marking step 1 of the motor path (tab → tile) */
@keyframes modelPulse { 0%, 100% { box-shadow: 0 0 0 0 var(--focus); } 50% { box-shadow: 0 0 0 6px var(--focus); } }
.tab.model-pulse { animation: modelPulse 0.5s ease-in-out 2; position: relative; z-index: 4; }
[data-motion="reduced"] .tab.model-pulse { animation: none; box-shadow: 0 0 0 4px var(--focus); }
@media (prefers-reduced-motion: reduce) { .tile.tile-found { animation: none; box-shadow: 0 0 0 4px var(--focus); } }

/* ===================================================== learn activities */
.learn-sheet .sheet-head { position: relative; }
.back-btn { background: var(--neutral); border: none; border-radius: 999px; padding: 7px 14px; font: inherit;
  font-weight: 800; color: var(--ink); cursor: pointer; margin-right: auto; }
.learn-body { margin-top: 6px; }
.learn-prompt { font-size: clamp(20px, 4vw, 26px); text-align: center; margin: 10px 0 6px; color: var(--ink); }
.learn-replay { display: block; margin: 4px auto 12px; background: var(--ink); color: #fff; border: none;
  border-radius: 999px; padding: 11px 22px; font: inherit; font-weight: 800; font-size: 16px; cursor: pointer; }
.learn-choices { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.learn-choice { min-height: clamp(110px, 24vw, 150px); }
.learn-choice.correct { outline: 4px solid var(--cat-verb); animation: learnPop .35s ease; }
.nudge { animation: wob .45s ease; }
@keyframes learnPop { 0% { transform: scale(1); } 50% { transform: scale(1.06); } 100% { transform: scale(1); } }
@keyframes wob { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }
.spell-head { display: flex; align-items: center; gap: 16px; justify-content: center; margin: 6px 0 4px; }
.spell-head .sym.big { width: clamp(72px, 18vw, 110px); height: clamp(72px, 18vw, 110px); display: grid; place-items: center; }
.spell-head .sym.big svg { width: 100%; height: 100%; }
.spell-word { display: flex; gap: 8px; }
.slot { width: clamp(34px, 9vw, 48px); height: clamp(44px, 11vw, 60px); border-bottom: 4px solid var(--ink);
  display: grid; place-items: center; font-size: clamp(24px, 6vw, 34px); font-weight: 900; color: var(--ink); text-transform: lowercase; }
.slot.filled { border-bottom-color: var(--cat-verb); }
.letter-tray { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 16px; }
.letter-tile { width: clamp(48px, 12vw, 64px); height: clamp(48px, 12vw, 64px); border: none; border-radius: 14px;
  background: var(--panel-solid); box-shadow: 0 3px 0 rgba(0,0,0,.16); color: var(--ink); font: inherit;
  font-weight: 900; font-size: clamp(22px, 5.5vw, 30px); cursor: pointer; text-transform: lowercase; }
.letter-tile.used { background: var(--cat-verb); color: #fff; box-shadow: none; }
.letter-card { text-align: center; padding: 18px 0 6px; }
.big-letter { font-size: clamp(80px, 26vw, 150px); font-weight: 900; line-height: 1; color: var(--ink); letter-spacing: .04em; }
.letter-ex { font-size: clamp(18px, 4vw, 24px); font-weight: 800; opacity: .75; margin-top: 6px; }
.letter-nav { display: flex; gap: 10px; margin-top: 16px; }
.learn-cheer { position: fixed; left: 50%; top: 38%; transform: translate(-50%,-50%); font-size: 96px;
  pointer-events: none; z-index: 95; animation: learnCheer 1.1s ease forwards; }
@keyframes learnCheer { 0% { transform: translate(-50%,-50%) scale(.3); opacity: 0; } 30% { opacity: 1; transform: translate(-50%,-50%) scale(1.1); } 100% { transform: translate(-50%,-70%) scale(1); opacity: 0; } }
@media (max-width: 460px) { .learn-choices { grid-template-columns: repeat(2, 1fr); } }
@media (prefers-reduced-motion: reduce) { .learn-choice.correct, .nudge, .learn-cheer { animation: none; } }

.read-word { text-align: center; font-size: clamp(40px, 11vw, 72px); font-weight: 900; color: var(--ink);
  margin: 14px 0 6px; letter-spacing: .02em; text-transform: lowercase; }

/* errorless learning: gentle "model the answer" cue (never a shake/penalty) */
.learn-choice.chosen { opacity: .9; }
.model { animation: modelpulse 1s ease; outline: 4px solid var(--cat-desc); outline-offset: 2px; border-radius: var(--radius); }
@keyframes modelpulse { 0%,100% { outline-color: transparent; } 40% { outline-color: var(--cat-desc); } }
.letter-tile.model { outline: 4px solid var(--cat-verb); }
/* #13 high-contrast: give toggles a colour-independent border + knob cue */
[data-contrast="high"] .toggle { border: 2px solid #000; background: #fff; }
[data-contrast="high"] .toggle.on { background: #000; }
[data-contrast="high"] .toggle::after { border: 1px solid #000; }
@media (prefers-reduced-motion: reduce) { .model { animation: none; } }

/* #21 typed text chips look distinct from symbol chips */
.msg-chip-typed { background: var(--neutral); }
.msg-chip-typed .sym { font-size: 1.15em; }
.msg-chip-typed .lbl { white-space: normal; }
/* #12 clearer grammar (long-press to inflect) affordance */
.tile.has-morph .lbl::after { content: "›"; position: absolute; right: 6px; bottom: 3px; font-size: 18px; opacity: .5; font-weight: 900; color: var(--ink); }
/* #8 body-map keyboard focus parity (outline in addition to fill) */
.bodymap .region:focus-visible { outline: 4px solid var(--cat-desc); outline-offset: 2px; }
/* #23 keep the express FAB from covering the last row on small phones */
@media (max-width: 560px) { .board { padding-bottom: 96px; } }

/* ================================================ v16 UI polish (micro-interactions, depth, focus)
   (elevation tokens --shadow-sm/-md/-raise are now consolidated into the main :root above) */
/* header: button feedback + declutter to icon-only on small phones (labels kept for SR) */
.iconbtn{ transition: background var(--dur-base) var(--ease-standard), box-shadow var(--dur-base) var(--ease-standard), transform var(--dur-fast) var(--ease-standard); }
.iconbtn:hover{ background: var(--neutral); }
.iconbtn:active{ transform: translateY(1px); box-shadow: var(--shadow-sm); }
@media (max-width:560px){ .iconbtn span{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); } .iconbtn{ padding:0 10px; } }
/* unified elevation scale */
.tab, .ctrl, .iconbtn{ box-shadow: var(--shadow-sm); }
.tab.active{ box-shadow: var(--shadow-md); }
.msg-chip{ box-shadow: var(--shadow-sm); }
.board-panel{ box-shadow: var(--shadow-md); }
/* tiles: layered depth + tactile press; hover changes shadow only (never transform — avoids fighting .armed) */
.tile{ box-shadow: var(--shadow-md), inset 0 1px 0 rgba(255,255,255,.45); }
.tile:active{ transform: scale(.95); filter: brightness(1.06); }
@media (hover:hover) and (pointer:fine){
  .tile{ transition: box-shadow var(--dur-base) var(--ease-standard), filter var(--dur-fast) var(--ease-standard), transform var(--dur-fast) var(--ease-standard); }
  .tile:hover{ box-shadow: var(--shadow-raise), inset 0 1px 0 rgba(255,255,255,.5); filter: brightness(1.02); }
  .tab:hover{ box-shadow: var(--shadow-md); }
  .ctrl:hover:not([disabled]){ filter: brightness(1.04); }
  .smart-chip:hover, .pred-chip:hover, .learn-card:hover{ box-shadow: var(--shadow-raise); }
}
/* refined, high-visibility focus ring (token-friendly) */
:focus-visible { outline: 4px solid var(--focus); outline-offset: 3px; }
[data-contrast="high"] :focus-visible{ outline-color:#000; }
/* honour reduced motion: no lifts/scales/brightness shifts */
@media (prefers-reduced-motion: reduce){
  .tile, .tab, .iconbtn, .ctrl, .msg-chip, .smart-chip, .pred-chip, .learn-card{ transition: none !important; }
  .tile:hover, .tile:active, .iconbtn:active{ transform: none !important; filter: none !important; }
}

/* easy-read font toggle (Atkinson Hyperlegible) — opt-in via Settings */
[data-font="hyperlegible"] body,
[data-font="hyperlegible"] button,
[data-font="hyperlegible"] input,
[data-font="hyperlegible"] textarea,
[data-font="hyperlegible"] select {
  font-family: "Atkinson Hyperlegible", ui-rounded, "SF Pro Rounded", "Nunito", system-ui, -apple-system, Arial, sans-serif;
}

/* photo word tiles + editor media previews */
.tile-photo { width: 100%; height: 100%; object-fit: cover; border-radius: 12px; display: block; }
.msg-chip .tile-photo, .smart-chip .tile-photo { border-radius: 8px; }
.media-prev { width: 88px; height: 88px; object-fit: cover; border-radius: 14px; display: block;
  margin-bottom: 8px; border: 2px solid var(--hairline); }

/* Theme Studio — curated accent-colour swatches (slice 1) */
.accent-swatches { display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: flex-end; }
.accent-sw { width: 44px; height: 44px; min-width: 44px; border-radius: 50%;
  border: 2px solid var(--hairline); cursor: pointer; padding: 0; box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease-standard); }
.accent-sw:active { transform: scale(0.94); }
.accent-sw.accent-theme { background: var(--neutral); color: var(--neutral-ink); font-weight: var(--fw-bold); font-size: 15px; }
.accent-sw.on { outline: 3px solid var(--ink); outline-offset: 2px; }
/* when a custom accent is chosen, tint the selected nav tab + segments too (curated swatches
   keep white-text contrast ≥4.5:1). Default look + high-contrast mode are unaffected. */
[data-accent="custom"] .tab.active { background: var(--focus); border-color: var(--focus); }
[data-accent="custom"] .seg button.on { background: var(--focus); }

/* first-run coach-marks (non-modal tips card) */
.coach-card { position: fixed; z-index: 80; top: 80px; left: 50%; transform: translateX(-50%);
  width: min(440px, 92vw); background: var(--panel-solid); border: 2px solid var(--ink);
  border-radius: 18px; box-shadow: var(--shadow-lg); padding: 16px 18px; animation: coachIn .25s ease; }
.coach-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.coach-head strong { font-size: 17px; color: var(--ink); }
.coach-x { background: var(--neutral); border: none; border-radius: 999px; width: 36px; height: 36px;
  font-size: 16px; font-weight: 800; color: var(--ink); cursor: pointer; }
.coach-tips { list-style: none; margin: 6px 0 14px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.coach-tips li { display: flex; gap: 10px; align-items: flex-start; font-size: 14.5px; line-height: 1.4; color: var(--ink); }
.coach-tips li span:first-child { font-size: 20px; line-height: 1; flex: 0 0 auto; }
.coach-got { width: 100%; padding: 13px; border: none; border-radius: 12px; background: var(--ink);
  color: #fff; font: inherit; font-weight: 800; font-size: 16px; cursor: pointer; }
@keyframes coachIn { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .coach-card { animation: none; } }
[data-contrast="high"] .coach-card { border-color: #000; }

/* text-only learn choices (Which group? / Yes or No) */
.group-choice { justify-content: center; }
.group-choice .lbl { font-size: clamp(20px, 4.5vw, 30px); white-space: normal; }
.learn-choices.yesno { grid-template-columns: 1fr 1fr; max-width: 460px; margin: 0 auto; }
.learn-choices.yesno .learn-choice { min-height: clamp(96px, 22vw, 140px); }

/* interactive sentence-bar chips (tap = re-speak word, long-press = delete word) */
.msg-chip { font: inherit; color: var(--ink); -webkit-appearance: none; appearance: none; cursor: pointer; text-align: center; }
.msg-chip:active { transform: scale(.95); }
@media (prefers-reduced-motion: reduce) { .msg-chip:active { transform: none; } }

/* recent-sentence chips in the suggestion bar (message history reuse) */
.recent-sentence { max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-style: dotted; font-weight: 700; }

/* tab-bar horizontal-scroll affordance: edge fades signal the 13 boards continue off-screen.
   Self-adjusting — when tabs fit, the fade sits over empty bg and is invisible. */
.tabs-wrap { position: relative; }
.tabs-wrap::before, .tabs-wrap::after { content: ""; position: absolute; top: 0; bottom: 4px;
  width: 26px; pointer-events: none; z-index: 2; }
.tabs-wrap::before { left: 0; background: linear-gradient(to right, var(--app-bg), transparent); }
.tabs-wrap::after  { right: 0; background: linear-gradient(to left, var(--app-bg), transparent); }

/* colour swatches (Colours board) — real hue reads on any theme, legible in high-contrast */
.swatch { width: 100%; height: 100%; border-radius: 50%; border: 3px solid var(--ink); box-sizing: border-box; display: block; }
.msg-chip .swatch { border-width: 2px; }
.smart-chip .swatch { width: 1.3em; height: 1.3em; border-radius: 50%; border: 2px solid var(--ink); display: inline-block; }
/* smartbar horizontal-scroll cue (predictions / recent sentences continue off-edge) */
.smartbar { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent); }

/* ================================================ v94 — responsive spacing, safe-area, fit & zoom
   Portrait / small screens: clamp all chrome so the board gets maximum room and nothing overlaps.
   The active board's tile size is driven at runtime by the fit/zoom controller (app.js), which
   sets --tile-min / --fs / --gap inline on <html>, overriding the caregiver size preset. */
#app { overflow: hidden; }
.appbar { gap: clamp(6px, 2vw, 10px); padding: clamp(4px, 1.3vh, 8px) clamp(10px, 3vw, 14px) clamp(3px, 1vh, 6px); }
.msgbar { gap: clamp(6px, 1.6vw, 8px); margin: clamp(3px, .8vh, 4px) clamp(8px, 3vw, 12px) 0; padding: clamp(5px, 1.4vw, 8px); }
.msg-scroll { min-height: clamp(46px, 8vh, 66px); }
.tabs { gap: clamp(5px, 1.4vw, 7px); padding: clamp(5px, 1.2vh, 8px) clamp(8px, 3vw, 12px) 4px; }
.smartbar { gap: clamp(6px, 1.4vw, 8px); padding: clamp(4px, 1vh, 8px) 4px 4px; }
.board { padding: clamp(6px, 1.3vh, 10px) clamp(8px, 3vw, 12px)
  calc(clamp(88px, 15vw, 108px) + env(safe-area-inset-bottom)); }
.board-panel { padding: clamp(8px, 2vw, 12px); }
.grid { gap: clamp(6px, 1.6vw, var(--gap)); }

/* zoom / fit-to-screen control — bottom-left, mirrors the "I need" FAB; always reachable */
.zoom-bar { position: fixed; z-index: 44;
  left: max(10px, env(safe-area-inset-left)); bottom: max(14px, env(safe-area-inset-bottom));
  display: inline-flex; align-items: center; gap: 1px; padding: 4px;
  background: var(--panel-solid); border-radius: 999px; box-shadow: var(--shadow-md);
  border: 1px solid var(--hairline); }
.zoom-btn { width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--ink); border-radius: 999px; cursor: pointer;
  font-weight: 800; transition: background var(--dur-base) var(--ease-standard), transform var(--dur-fast) var(--ease-standard); }
.zoom-btn svg { width: 22px; height: 22px; pointer-events: none; }
.zoom-btn:active { transform: scale(.9); }
.zoom-btn[disabled] { opacity: .38; cursor: default; }
.zoom-btn.fit-on { background: var(--focus); color: #fff; }
.zoom-lvl { min-width: 34px; text-align: center; font-size: 11px; font-weight: 800; color: var(--ink);
  font-variant-numeric: tabular-nums; padding: 0 2px; }
[data-locked="on"] .zoom-bar { display: none; }  /* locked view stays ultra-simple */
@media (hover: hover) and (pointer: fine) { .zoom-btn:hover:not([disabled]) { background: var(--neutral); } }

/* very small phones: trim header + FAB so nothing overflows or overlaps */
@media (max-width: 380px) {
  .appbar { gap: 5px; }
  .iconbtn { min-width: 42px; padding: 0 8px; }
  .brand-wordmark { height: clamp(38px, 11vw, 50px); max-width: 46vw; }
  .express-fab { min-height: 52px; padding: 9px 15px 9px 13px; font-size: 15px; }
  .express-fab .sym { width: 22px; height: 22px; }
  .zoom-btn { width: 40px; height: 40px; }
}

/* ============================================================ responsiveness: landscape phones
   Short-viewport landscape (phones, ~<=560px tall) was dominated by chrome, leaving ~1 board row.
   Compress the header/message bar/tabs and cap tile height so several rows are usable.
   Targets phones only (tablets/desktop are taller than 560px → unaffected). */
@media (orientation: landscape) and (max-height: 560px) {
  .appbar { padding: 2px 12px 1px; gap: 6px; }
  .brand-wordmark { height: clamp(22px, 7vh, 34px); max-width: 26vw; }
  .iconbtn { min-height: 34px; min-width: 34px; padding: 0 8px; }
  .iconbtn svg { width: 18px; height: 18px; }
  .msgbar { margin: 2px 10px 0; padding: 3px; gap: 5px; }
  .msg-scroll { min-height: 36px; }
  .msg-chip .sym { width: 24px; height: 24px; }
  .ctrl { min-width: 44px; padding: 3px; font-size: 10px; gap: 1px; }
  .ctrl svg { width: 18px; height: 18px; }
  .ctrl.speak { min-width: 62px; font-size: 12px; }
  .ctrl.speak svg { width: 22px; height: 22px; }
  .smartbar { display: none; }            /* reclaim ~30px for another board row in short landscape */
  .tabs { padding: 3px 12px 2px; }
  .tab { min-height: 32px; font-size: 13px; padding: 3px 11px 3px 8px; }
  .tab .sym { width: 20px; height: 20px; }
  .board { padding: 4px 10px calc(72px + env(safe-area-inset-bottom)); }
  .board-panel { padding: 7px; }
  .tile { min-height: min(var(--tile-min), 30vh); padding: 5px 4px 4px; gap: 3px; }
  .express-fab { min-height: 46px; padding: 7px 13px 7px 11px; font-size: 14px; }
  .express-fab svg, .express-fab .sym { width: 20px; height: 20px; }
  .zoom-bar { padding: 3px; }
  .zoom-btn { width: 36px; height: 36px; }
}

/* responsiveness: typing keyboard must FIT in landscape (was scrolling keys below the fold) */
@media (orientation: landscape) and (max-height: 560px) {
  .sheet { max-height: 94vh; }
  .type-text { min-height: 40px; max-height: 17vh; font-size: clamp(16px, 2.4vw, 20px); }
  .type-preds { min-height: 24px; padding: 4px 0 2px; }
  .pred-chip { padding: 5px 12px; font-size: 14px; }
  .type-actions { margin: 5px 0 6px; }
  .type-act { padding: 8px; font-size: 14px; }
  .kbd { gap: 4px; }
  .kbd-row { gap: 4px; }
  .key { height: clamp(28px, 6.4vh, 38px); font-size: clamp(15px, 3vw, 19px); box-shadow: 0 1px 0 rgba(0,0,0,.14); }
}

/* responsiveness: centre the app on ultra-wide screens so tiles aren't stretched */
@media (min-width: 1400px) {
  .msgbar, .smartbar, .tabs-wrap, .board-panel { max-width: 1280px; margin-left: auto; margin-right: auto; }
}

/* word tiles: abstract/function words with no symbol render the whole word boldly + centred
   (distinct & legible, vs an ambiguous repeated initial). Scales with the size control. */
.tile-word { justify-content: center; }
.tile-word .word-tile { font-weight: 900; font-size: calc(22px * var(--fs)); line-height: 1.08;
  text-align: center; color: var(--ink); padding: 0 3px; letter-spacing: .2px; overflow-wrap: anywhere; hyphens: auto; }
.tile-word.placeholder { display: flex; }

/* communication lock / keyguard: hide caregiver controls; board + message bar + FAB stay active */
[data-locked="on"] .appbar .iconbtn,
[data-locked="on"] .avatar-btn { display: none; }
/* logo stays visible as branding when locked, but isn't a lock-escape route */
[data-locked="on"] .brand { pointer-events: none; }
#lock-badge { position: fixed; top: calc(env(safe-area-inset-top) + 8px); right: 12px; z-index: 70;
  display: inline-flex; align-items: center; gap: 6px; padding: 8px 13px; border: 2px solid var(--ink);
  border-radius: 999px; background: var(--panel-solid); color: var(--ink); font: inherit; font-weight: 800;
  font-size: 13px; cursor: pointer; box-shadow: var(--shadow-md); }
#lock-badge .lk-ic { font-size: 16px; }
#lock-badge.holding { background: var(--cat-verb); transform: scale(.97); }
#lock-badge[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { #lock-badge.holding { transform: none; } }

/* v101 — account & E2E sync UI */
.sync-ui { gap: 6px; }
.sync-field { width: 100%; padding: 12px 14px; border: 2px solid var(--hairline); border-radius: 14px;
  font-size: 16px; font-family: inherit; background: var(--panel-solid); color: var(--ink); }
.sync-field:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.sync-ok { color: var(--speak); font-weight: 800; }
.iconbtn.primary { background: var(--speak); color: #fff; }
.iconbtn.danger { background: var(--express); color: #fff; }

/* v103 — plans & pricing */
.plans-sheet { max-width: 860px; }
.plan-status { font-weight: 800; margin: 2px 0 10px; }
.plans-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 12px; }
.plan-card { position: relative; background: var(--panel-solid); border: 2px solid var(--hairline);
  border-radius: 18px; padding: 44px 16px 16px; display: flex; flex-direction: column; gap: 8px;
  box-shadow: var(--shadow-sm); }
.plan-card h3 { margin: 0; font-size: 17px; }
.plan-badge { position: absolute; top: 12px; left: 16px; background: var(--neutral); color: var(--neutral-ink);
  font-size: 11px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase;
  padding: 4px 10px; border-radius: 999px; }
.plan-card:nth-child(2) { border-color: var(--speak); }
.plan-card:nth-child(2) .plan-badge { background: var(--speak); color: #fff; }
.plan-price { font-size: 26px; font-weight: 900; color: var(--ink); }
.plan-price span { font-size: 13px; font-weight: 700; opacity: .65; }
.plan-card ul { margin: 0; padding: 0 0 0 18px; font-size: 13.5px; font-weight: 600; opacity: .85;
  display: flex; flex-direction: column; gap: 4px; flex: 1; }
.plan-choose { margin-top: 6px; justify-content: center; }
.plan-current { outline: 3px solid var(--focus); }
.plan-clin { border-color: var(--cat-q); background: linear-gradient(160deg, var(--panel-solid), #f6f0fb); }
.plan-clin .plan-badge { background: var(--cat-q); color: #3a2657; }
@media (max-width: 640px) { .plans-grid { grid-template-columns: 1fr; } .plan-card { padding-top: 40px; } }

/* v104 — account role picker */
.role-pick { gap: 8px; }
.role-pick .iconbtn { flex: 1; justify-content: center; border: 2px solid var(--hairline); }
.role-pick .iconbtn.primary { border-color: var(--speak); }

/* H4-4 — role entry doors (dark, H4_DOORS_ENABLED). Two prominent cards before the sign-in form. */
.role-doors-hint { font-weight: 700; margin: 2px 0 2px; }
.role-doors { display: flex; flex-direction: column; gap: 10px; margin-bottom: 6px; }
@media (min-width: 460px) { .role-doors { flex-direction: row; } }
.role-door { flex: 1; display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  text-align: left; padding: 14px 16px; border: 2px solid var(--hairline); border-radius: 16px;
  background: var(--panel-solid); color: var(--ink); cursor: pointer; min-height: 64px;
  transition: transform var(--dur-fast) var(--ease-standard), border-color var(--dur-base) var(--ease-standard), box-shadow var(--dur-base) var(--ease-standard); }
.role-door:hover { box-shadow: var(--shadow); }
.role-door:active { transform: scale(.985); }
.role-door.chosen { border-color: var(--speak); box-shadow: inset 0 0 0 1px var(--speak); }
.role-door .rd-title { font-weight: 800; font-size: 1rem; }
.role-door .rd-sub { font-size: .8rem; opacity: .7; font-weight: 600; }
[data-motion="reduced"] .role-door { transition: none; }

/* v105 — clinical portal */
.clin-sheet { max-width: 760px; }
.clin-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
@media (max-width: 640px) { .clin-grid { grid-template-columns: 1fr; } }
.goal-list { display: flex; flex-direction: column; gap: 6px; margin: 4px 0; }
.goal-row { display: flex; align-items: center; gap: 10px; padding: 9px 12px; background: var(--panel-solid);
  border: 1px solid var(--hairline); border-radius: 12px; font-weight: 700; font-size: 14.5px; cursor: pointer; }
.goal-row input { width: 20px; height: 20px; flex: 0 0 auto; }
.pron-row { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 12px; background: var(--panel-solid); border: 1px solid var(--hairline);
  border-radius: 12px; font-size: 14.5px; }
.pron-add { align-items: stretch; }
.pron-add .sync-field { flex: 1; min-width: 0; }
.clin-tpl { min-height: 90px; }
.report-goals { margin: 6px 0 10px; padding-left: 22px; }
.report-goals li { margin: 3px 0; }

/* v106 — owner CRM */
.crm-sheet { max-width: 820px; }
.crm-cards { margin-bottom: 4px; }
.crm-tablewrap { max-height: 300px; overflow-y: auto; border: 1px solid var(--hairline); border-radius: 12px; }
.crm-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.crm-table th, .crm-table td { padding: 8px 10px; text-align: left; border-bottom: 1px solid var(--hairline); }
.crm-table th { position: sticky; top: 0; background: var(--bar-bg); font-size: 11.5px;
  text-transform: uppercase; letter-spacing: .05em; }

/* v107 — pre-app account entry + upsells */
/* commerce overlays must sit ABOVE the launch menu (z-990) so sign-in/CRM/pricing work pre-app */
/* H4-6: cc-overlay joins this list now that "Your dashboard" is reachable directly from the
   launch-menu account row (same pre-app category as Account/Clinical/CRM) — without this it
   renders correctly in the DOM but sits BEHIND the launch menu (z-60 default vs launch's z-990). */
#account-overlay, #pricing-overlay, #clinical-overlay, #crm-overlay, #cc-overlay { z-index: 1050; }
.launch-account { margin: 12px 0 2px; padding: 12px; background: var(--panel-solid);
  border: 1px solid var(--hairline); border-radius: 16px; display: flex; flex-direction: column; gap: 8px; }
.la-line { font-weight: 800; font-size: 14px; color: var(--speak); }
.la-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.la-actions .iconbtn { flex: 1 1 auto; justify-content: center; font-size: 14px; min-height: 44px; }
.la-hint { font-size: 12.5px; font-weight: 700; opacity: .65; }
.iconbtn.warm { background: var(--express); color: #fff; }
.upsell-banner { display: flex; flex-direction: column; gap: 3px; text-align: left; width: 100%;
  margin: 2px 0 12px; padding: 13px 16px; border: 2px solid var(--speak); border-radius: 14px;
  background: #eaf7ee; color: var(--ink); cursor: pointer; font-family: inherit;
  transition: transform var(--dur-fast) var(--ease-standard), box-shadow var(--dur-base) var(--ease-standard); }
.upsell-banner b { font-size: 15.5px; font-weight: 900; }
.upsell-banner span { font-size: 13px; font-weight: 600; opacity: .78; }
.upsell-banner:hover { box-shadow: var(--shadow-md); }
.upsell-banner:active { transform: scale(.985); }

/* v108 — splash sign-in pill signed-in state */
.splash-chip-on { color: var(--speak); }

/* ================================================= v111 — motion system (Batch 1)
   Two speed zones: COMMUNICATOR (<=150ms, state not decoration — tiles already use
   --dur-fast 120ms, untouched) and CAREGIVER/ENTRY (300–400ms, coordinated).
   All motion below uses these tokens; reduced-motion collapses everything. */
:root { --motion-fast: 150ms; --motion-standard: 300ms; --motion-entrance: 400ms; }

/* splash → launch: choreographed handoff (bg persists via .bgscene; centre exits gracefully) */
.splash { transition: opacity var(--motion-entrance) var(--ease-standard), visibility var(--motion-entrance) var(--ease-standard); }
.splash.hide .splash-center { opacity: 0; transform: translateY(14px);
  transition: opacity var(--motion-standard) var(--ease-standard), transform var(--motion-standard) var(--ease-standard); }
.launch { transition: opacity var(--motion-entrance) var(--ease-standard), visibility var(--motion-entrance) var(--ease-standard); }
/* launch cards stagger in (entrance only) */
@keyframes launchCardIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
.launch:not(.hide):not([hidden]) .launch-dest-card { animation: launchCardIn var(--motion-entrance) var(--ease-emphasis) both; }
.launch:not(.hide):not([hidden]) .launch-dest-card:nth-child(2) { animation-delay: 40ms; }
.launch:not(.hide):not([hidden]) .launch-dest-card:nth-child(3) { animation-delay: 80ms; }
.launch:not(.hide):not([hidden]) .launch-dest-card:nth-child(4) { animation-delay: 120ms; }
.launch:not(.hide):not([hidden]) .launch-dest-card:nth-child(5) { animation-delay: 160ms; }

/* caregiver overlays: coordinated scale+fade at standard tempo (was 200ms) */
.overlay { transition: opacity var(--motion-standard) var(--ease-standard), visibility var(--motion-standard) var(--ease-standard); }
.overlay > * { transition: transform var(--motion-standard) var(--ease-emphasis), opacity var(--motion-standard) var(--ease-standard); }

/* theme switch: brief coordinated cross-fade instead of instant repaint (attr removed after).
   H4-2 (v168): recolor flows through the ROOT custom properties, not a transition on 125
   individual elements. The old approach forced a ~6.3ms synchronous style-recalc across every
   tile/chrome element at apply time (measured, native; ~4-6x that at 6x-throttle → dropped
   frames). Here the theme colour tokens are @property-registered as <color> so a single
   transition on <html> interpolates them; every element reading var(--token) repaints with the
   interpolated value — one transitioning element instead of 125. Browsers without @property
   (Safari <16.4) simply cut instantly (graceful, == reduced-motion). */
@property --app-bg     { syntax: '<color>'; inherits: true; initial-value: #f3ecdb; }
@property --panel      { syntax: '<color>'; inherits: true; initial-value: rgba(255,252,244,0.86); }
@property --panel-solid{ syntax: '<color>'; inherits: true; initial-value: #fffdf7; }
@property --bar-bg     { syntax: '<color>'; inherits: true; initial-value: #fff8ea; }
@property --tab-bg     { syntax: '<color>'; inherits: true; initial-value: #ffffff; }
@property --ink        { syntax: '<color>'; inherits: true; initial-value: #15302a; }
@property --hairline   { syntax: '<color>'; inherits: true; initial-value: rgba(40,30,10,0.12); }
@property --neutral    { syntax: '<color>'; inherits: true; initial-value: #ece5d6; }
@property --neutral-ink{ syntax: '<color>'; inherits: true; initial-value: #3a3327; }
@property --focus      { syntax: '<color>'; inherits: true; initial-value: #1b73e8; }
html[data-theme-fading] {
  transition: --app-bg 250ms var(--ease-standard), --panel 250ms var(--ease-standard),
    --panel-solid 250ms var(--ease-standard), --bar-bg 250ms var(--ease-standard),
    --tab-bg 250ms var(--ease-standard), --ink 250ms var(--ease-standard),
    --hairline 250ms var(--ease-standard), --neutral 250ms var(--ease-standard),
    --neutral-ink 250ms var(--ease-standard), --focus 250ms var(--ease-standard); }

/* reduced-motion collapses ALL of the above to instant cuts */
[data-motion="reduced"] .splash, [data-motion="reduced"] .splash.hide .splash-center,
[data-motion="reduced"] .launch, [data-motion="reduced"] .launch .launch-dest-card,
html[data-motion="reduced"][data-theme-fading] {
  transition: none !important; animation: none !important; }

/* v112 — feedback channel */
.fb-sheet { max-width: 520px; }
.fb-cats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin: 10px 0; }
.fb-cats .iconbtn { justify-content: center; border: 2px solid var(--hairline); }
.fb-cats .iconbtn.primary { border-color: var(--speak); }
.fb-send { width: 100%; justify-content: center; margin-top: 10px; }
#feedback-overlay { z-index: 1055; }  /* above launch + account so it works from any caregiver surface */
@media (max-width: 480px) { .fb-cats { grid-template-columns: repeat(2, 1fr); } }

/* v113 — micro-interactions */
.board { overscroll-behavior: none; }        /* no rubber-band pull past the board */
html.is-speaking .ctrl.speak { animation: speakPulse 1.1s var(--ease-standard) infinite; }
@keyframes speakPulse { 0%,100% { box-shadow: var(--shadow-sm); } 50% { box-shadow: 0 0 0 6px rgba(34,128,73,.25); } }
[data-motion="reduced"] html.is-speaking .ctrl.speak, html[data-motion="reduced"].is-speaking .ctrl.speak { animation: none; }

/* v115 — edge states */
#offline-chip { position: fixed; top: max(8px, env(safe-area-inset-top)); left: 50%; transform: translateX(-50%);
  z-index: 48; display: flex; align-items: center; gap: 10px; padding: 8px 10px 8px 16px;
  background: var(--panel-solid); border: 1px solid var(--hairline); border-radius: 999px;
  box-shadow: var(--shadow-md); font-size: 13.5px; font-weight: 700; color: var(--ink);
  transition: opacity var(--motion-standard) var(--ease-standard); }
#offline-chip button { border: none; background: var(--neutral); color: var(--neutral-ink);
  border-radius: 50%; width: 28px; height: 28px; cursor: pointer; font-weight: 800; }
.plan-lapsed { color: var(--express); font-weight: 700; }
.evict-note { border-color: var(--cat-noun); }

/* v116 — backlog sweep */
[data-theme="midnight"] .msg-scroll .placeholder { color: rgba(236,240,244,0.82); }  /* was dark-on-dark 1.01:1 */
.launch[data-shown] .launch-dest-card { animation: none; }  /* entrance stagger runs once per page-load */

/* H3.5 symbol-set chooser: set artwork fills the tile symbol slot exactly */
.tile-setart { width: 100%; height: 100%; object-fit: contain; display: block; }

/* H3.5 symbols & looks chooser */
.symset-row { align-items: center; gap: 10px; }
.symset-prev { display: flex; gap: 6px; margin: 6px 0; }
.symset-mini { width: 52px; height: 52px; display: inline-flex; align-items: center; justify-content: center; background: #fff; border: 1px solid rgba(0,0,0,.12); border-radius: 10px; padding: 5px; }
.symset-mini img, .symset-mini svg { width: 100%; height: 100%; object-fit: contain; }
.symset-launch { margin-top: 6px; }

/* H3.5 in-app library store */
.symset-cat { flex-direction: column; align-items: flex-start; }
.symset-chip { display: inline-block; font-size: .66rem; font-weight: 800; letter-spacing: .04em; color: var(--warm, #e8734a); background: rgba(232,115,74,.12); border-radius: 99px; padding: 1px 8px; vertical-align: middle; }
.symset-chip.live { color: #2f7d4f; background: rgba(47,158,87,.14); }

/* v147: the chooser must stack ABOVE the launch screen (z 990) like commerce overlays (v107 lesson) */
#symset-overlay { z-index: 1050; }
/* v147: big, prominent launch pill for Symbols & looks */
.symset-launch .iconbtn { width: 100%; font-size: 1.08rem; font-weight: 700; padding: 15px 18px; border-radius: 14px; }
/* v147: tall chooser sheet must not clip above the fold (safe center + internal scroll) */
#symset-overlay { align-items: safe center; }
#symset-overlay .sheet { max-height: calc(100dvh - 40px); overflow-y: auto; }

/* H3.5 v148 — SYMBOL LIBRARY: its own full-screen interface */
.library { position: fixed; inset: 0; z-index: 1050; background: var(--bg, #faf7f2); display: flex; flex-direction: column;
  /* H4-2b: token-driven open/close (caregiver zone) replacing the instant display:none cut —
     mirrors the .overlay hidden pattern (proven safe with switch-scan + focus) so the Library
     fades + rises in and out instead of popping. */
  transition: opacity var(--motion-standard) var(--ease-standard),
    visibility var(--motion-standard) var(--ease-standard),
    transform var(--motion-standard) var(--ease-emphasis); }
.library.hidden { opacity: 0; visibility: hidden; pointer-events: none; transform: translateY(10px) scale(0.992); }
[data-motion="reduced"] .library { transition: none; }
.lib-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px 8px; }
.lib-head h2 { font-size: 1.3rem; margin: 0; }
.lib-tabs { display: flex; gap: 6px; padding: 4px 16px 10px; overflow-x: auto; flex: none; }
.lib-tab { flex: none; font: inherit; font-size: .88rem; font-weight: 700; padding: 9px 14px; border-radius: 99px; border: 1.5px solid rgba(0,0,0,.14); background: #fff; cursor: pointer; min-height: 44px; }
.lib-tab.on { background: var(--warm, #e8734a); border-color: var(--warm, #e8734a); color: #fff; }
.lib-body { flex: 1; overflow-y: auto; padding: 4px 16px calc(24px + env(safe-area-inset-bottom)); }
.lib-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); gap: 12px 8px; margin-top: 12px; }
.lib-tile { text-align: center; }
.lib-art { display: flex; align-items: center; justify-content: center; width: 68px; height: 68px; margin: 0 auto; background: #fff; border: 1.5px solid rgba(0,0,0,.12); border-radius: 12px; padding: 6px; }
.lib-art img, .lib-art .sym, .lib-art .sym svg { width: 100%; height: 100%; object-fit: contain; }
.lib-lbl { display: block; font-size: .7rem; font-weight: 700; margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lib-search { width: 100%; font: inherit; font-size: 1rem; padding: 12px 14px; margin-top: 10px; border-radius: 12px; border: 1.5px solid rgba(0,0,0,.18); }

/* P0 v163 — GLOBAL, component-independent cap on symbol-set artwork (.tile-setart).
   tileSym() feeds FIVE components (board tile, smart bar, message bar, vocab list,
   learn/word-of-day); only the board's .tile .sym was ever sized, so the smart-bar
   chip rendered the raster at its intrinsic 512px and overlaid the live UI. The
   absolute max here caps the image in EVERY context — sized wrapper or not — so no
   set-art image can EVER exceed a tile's worth of space again. This is the structural
   safety net that must hold regardless of which component invokes the shared path. */
.tile-setart {
  display: block; object-fit: contain;
  width: 100%; height: 100%;
  max-width: 96px; max-height: 96px;   /* absolute backstop: bigger than any legit symbol (board .sym maxes 86px), far smaller than the UI */
}
/* size the symbol wrapper in the non-board components that render tileSym */
.smart-chip .s, .smart-chip .sym { width: 34px; height: 34px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center; overflow: hidden; }
.smart-chip .s .tile-setart, .smart-chip .sym .tile-setart { max-width: 34px; max-height: 34px; }
.msg-chip .sym { overflow: hidden; }
.msg-chip .sym .tile-setart { max-width: 34px; max-height: 34px; }
.vocab-item .sym { width: 40px; height: 40px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center; overflow: hidden; }
.vocab-item .sym .tile-setart { max-width: 40px; max-height: 40px; }
.symset-mini img { max-width: 100%; max-height: 100%; object-fit: contain; }
.lib-art img { max-width: 100%; max-height: 100%; object-fit: contain; }
/* failed/removed set-art degrades to the plain word label (onerror) */
.tile.setart-failed .word-tile, .tile.setart-failed .lbl { font-weight: 800; }
/* library picker: a failed image (broken link, offline, missing asset) degrades to a
   clean placeholder — never the browser's raw broken-image icon (onerror in _libGridFromFiles) */
.lib-art.lib-art-broken { background: rgba(0,0,0,.04); }
.lib-art.lib-art-broken::after { content: '\1F4F7'; opacity: .35; font-size: 1.4rem; }

/* ENG-40 · E6 classroom v1 — fast profile switcher (caregiver surface; the
   header button is .iconbtn so [data-locked] hides it under comm-lock) */
#classroom-overlay{position:fixed;inset:0;z-index:1000;background:rgba(30,24,10,.45);display:grid;place-items:center;padding:18px}
.class-sheet{background:var(--panel-solid);border-radius:var(--radius);box-shadow:var(--shadow-lg);max-width:520px;width:100%;max-height:82vh;overflow:auto;padding:18px 18px 22px}
.class-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.class-head h2{margin:0;font-size:20px;color:var(--ink)}
.class-sub{margin:6px 0 14px;color:var(--ink);opacity:.75;font-size:14px}
.class-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
.class-card{display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px 10px;min-height:96px;border:2px solid var(--hairline);border-radius:14px;background:#fff;cursor:pointer;font:inherit}
.class-card.active{border-color:var(--speak);box-shadow:0 0 0 2px rgba(34,128,73,.18)}
.class-card .class-init{width:44px;height:44px;border-radius:50%;background:var(--cat-desc);display:grid;place-items:center;font-weight:800;font-size:20px;color:var(--ink)}
.class-card .class-name{font-weight:800;color:var(--ink);text-align:center}
.class-card .class-name em{font-style:normal;font-weight:700;font-size:11px;color:var(--speak);display:block}
.class-card .class-meta{font-size:12px;color:var(--ink);opacity:.6}
#classroom-overlay .close-btn{min-width:44px;min-height:44px;border-radius:12px;border:1px solid var(--hairline);background:#fff;font-size:18px;cursor:pointer}

/* ENG-45 · Learn Anan — only the first-run gateway button lives in the eager
 * sheet (the quick-tips card is eager). The whole tour spotlight/bubble stylesheet
 * ships inside js/tour.js and is injected when the lazy course loads, so it costs
 * the communicator path nothing (G8). */
.coach-learn{display:block;width:100%;margin:2px 0 8px;padding:12px 14px;border-radius:12px;border:1px solid #228049;
  background:#eaf6ee;color:#175f36;font-weight:800;font-size:15px;cursor:pointer;min-height:44px}
