
  @import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=Syne:wght@600;700;800&family=Baloo+2:wght@500;600;700;800&display=swap');

  /* Charmcraft pass: retunes the same tokens the "cutesy" pass did, since
     that's still the highest-leverage lever in this file — --cover alone
     is read 100+ times. Colors are Charmcraft's own OKLCH design tokens
     (src/styles.css), converted to sRGB hex so they drop into variables
     this file already reads everywhere, rather than adopting Charmcraft's
     own variable names (--background/--primary/etc.), which would mean
     renaming every one of those 100+ call sites for no functional gain.
     Font swaps Baloo 2 (headline use) for Syne — Charmcraft's actual
     display face — while keeping Plus Jakarta Sans for body copy, since
     Charmcraft uses that exact pairing too; --font-display keeps a Baloo 2
     fallback behind Syne for any glyph Syne doesn't cover.
     Charmcraft's own dark-mode tokens are a generic shadcn dark theme that
     drops the jade/coral identity entirely (its primary goes to near-white
     gray) — not something to port literally. Below instead keeps the same
     jade/coral/gold hue family, just re-lit for a dark background, the
     same judgment call the original cutesy dark mode made. */
  :root{
    --on-cover:#ffffff;
    --ink:#062822;
    --paper:#fff9e7;
    --paper-dark:#f8ebc4;
    --card:#ffffff;
    --card-bg:#f5f0e2;
    --cover:#1d9178;
    --cover-light:#3aa88f;
    --cover-deep:#006b57;
    --primary-tint:#bef1e6;
    --stamp:#f27e6d;
    --stamp-light:#f6a08f;
    --stamp-tint:#fde8e4;
    --gold:#eec14e;
    --gold-tint:#fbf0d3;
    --ok:#1d9178;
    --ok-bg:#bef1e6;
    --bad:#e7000b;
    --bad-bg:#fbdcdc;
    --warn:#f27e6d;
    --warn-bg:#fde8e4;
    --line:#e3dac1;
    --muted:#516d66;
    --muted-soft:#8a9d97;
    --on-accent:#062822;
    /* v224: ink for text sitting on the --ok-bg / --bad-bg / --warn-bg / --stamp-tint tints
       (the plain --ok / --bad colours are backgrounds and borders; as text on their tints
       they measured 3.4–3.7:1). Light values are ≥5:1 on every tint; dark reuses the
       dark-mode accents, which already pass. */
    --ok-ink:#0b6b62;
    --bad-ink:#9f1239;
    --warn-ink:#92400e;
    --stamp-ink:#be123c;
    --font:'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-display:'Syne', 'Baloo 2', 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --radius-sm:12px;
    --radius:16px;
    --radius-lg:22px;
    --shadow-sm:0 2px 6px rgba(6,40,34,0.08);
    --shadow:0 14px 30px rgba(6,40,34,0.10);
    --shadow-lg:0 26px 60px rgba(6,40,34,0.16);
  }
  body.dark-mode{
    --on-cover:#062822; /* dark text on the bright mint accent: white was ~1.9:1 */
    --ink:#eaf6f1;
    --paper:#0a1815;
    --paper-dark:#0d1f1a;
    --card:#122b25;
    --card-bg:#17352d;
    --cover:#3ddc9a;
    --cover-light:#6ee6b8;
    --cover-deep:#00997a;
    --primary-tint:#1a3a32;
    --stamp:#ff9a86;
    --stamp-light:#ffb3a3;
    --stamp-tint:#3a231e;
    --gold:#ffd873;
    --gold-tint:#3a3018;
    --ok:#3ddc9a;
    --ok-bg:#123a2c;
    --bad:#ff6b6b;
    --bad-bg:#3a1414;
    --warn:#ff9a86;
    --warn-bg:#3a231e;
    --line:#234942;
    --muted:#9fc2b8;
    --muted-soft:#5f8078;
    --on-accent:#062822;
    --ok-ink:#3ddc9a;
    --bad-ink:#ff6b6b;
    --warn-ink:#ff9a86;
    --stamp-ink:#ff9a86;
    --shadow-sm:0 1px 3px rgba(0,0,0,0.35);
    --shadow:0 12px 28px rgba(0,0,0,0.4);
    --shadow-lg:0 24px 56px rgba(0,0,0,0.55);
  }
  body.dark-mode{ background-image:
      radial-gradient(600px circle at 8% -5%, rgba(61,220,154,0.14), transparent 55%),
      radial-gradient(600px circle at 100% 10%, rgba(255,154,134,0.10), transparent 50%);
  }
  body.dark-mode img{ opacity:0.92; }

  /* Charmcraft signature: chunky "3D" buttons — a solid drop-shadow one
     shade deeper than --cover, that collapses when pressed. This file has
     dozens of independent button rules built up over many sessions rather
     than one shared .btn class, so rewriting each individually isn't
     practical here. The [style*="var(--cover)"] selector below matches
     every button that sets its own background inline to var(--cover) —
     which covers most of the app's real calls-to-action — without having
     to touch each of those inline styles. Class-based cover buttons are
     covered by the second selector list. */
  button[style*="var(--cover)"], input[type="submit"][style*="var(--cover)"],
  .tab-btn.active, .lib-tab.active, .lib-chip.active, .corr-btn.on, .speak-btn.on,
  .deck-card .dc-vote.on{
    box-shadow: 0 4px 0 var(--cover-deep);
    transition: transform .08s ease, box-shadow .08s ease;
  }
  button[style*="var(--cover)"]:active, input[type="submit"][style*="var(--cover)"]:active,
  .tab-btn.active:active, .lib-tab.active:active, .lib-chip.active:active,
  .corr-btn.on:active, .speak-btn.on:active, .deck-card .dc-vote.on:active{
    transform: translateY(3px);
    box-shadow: 0 1px 0 var(--cover-deep);
  }
  #themeOverlay{
    position:fixed; inset:0; background:rgba(0,0,0,0.45); z-index:9700;
    display:flex; align-items:center; justify-content:center; padding:16px;
  }
  #themeSheet{
    background:var(--card); border-radius:20px; padding:20px 18px 18px;
    max-width:360px; width:100%; font-family:var(--font);
    /* Adding the 7th "Cutesy" swatch to both grids pushed total content
       past one screen's height on smaller phones — the sheet never had a
       max-height/scroll of its own, so anything past the fold (including
       the Done button) was simply unreachable rather than requiring a
       scroll. max-height matches the 16px overlay padding on each side. */
    max-height:calc(100vh - 32px);
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
  }
  #themeSheet .ts-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:10px; }
  #themeSheet .ts-title{ font-size:19px; font-weight:800; color:var(--ink); }
  .ts-x{ border:none; background:var(--card-bg); color:var(--muted); width:32px; height:32px; border-radius:50%; font-size:14px; cursor:pointer; }
  .ts-label{ font-size:11.5px; font-weight:800; letter-spacing:.04em; text-transform:uppercase; color:var(--muted); margin:14px 0 7px; }
  /* Preview */
  /* Theme pairs */
  #themePairGrid{ display:grid; grid-template-columns:repeat(5,1fr); gap:8px 4px; }
  .ts-pair{ border:none; background:none; cursor:pointer; display:flex; flex-direction:column; align-items:center; gap:4px; padding:4px 0; font-family:var(--font); -webkit-tap-highlight-color:transparent; }
  .ts-pair-dots{ position:relative; width:44px; height:44px; border-radius:50%; overflow:hidden; box-shadow:0 2px 6px rgba(0,0,0,.18); outline:3px solid transparent; outline-offset:2px; transition:transform .12s, outline-color .12s; }
  .ts-pair-dots i{ position:absolute; inset:0; }
  .ts-pair-dots i:last-child{ clip-path:polygon(100% 0, 100% 100%, 0 100%); }
  .ts-pair:active .ts-pair-dots{ transform:scale(.92); }
  .ts-pair.active .ts-pair-dots{ outline-color:var(--ink); }
  .ts-pair span{ font-size:10px; font-weight:700; color:var(--muted); }
  .ts-pair.active span{ color:var(--ink); }
  /* Segmented controls */
  .ts-seg{ display:flex; background:var(--card-bg); border-radius:12px; padding:3px; gap:3px; }
  .ts-seg button{ flex:1; border:none; background:none; border-radius:9px; padding:8px 4px; font:700 12px var(--font); color:var(--muted); cursor:pointer; display:flex; align-items:center; justify-content:center; gap:6px; }
  .ts-seg button.on{ background:var(--card); color:var(--ink); box-shadow:var(--shadow-sm); }
  .ts-dot{ width:12px; height:12px; border-radius:50%; display:inline-block; box-shadow:inset 0 0 0 1px rgba(0,0,0,.15); }
  /* Custom drawer */
  #tsCustom{ margin-top:14px; border-top:1px solid var(--line); padding-top:10px; }
  #tsCustom summary{ cursor:pointer; font-weight:800; font-size:13px; color:var(--ink); list-style:none; padding:4px 0; }
  #tsCustom summary::-webkit-details-marker{ display:none; }
  #tsCustom summary::after{ content:'›'; float:right; transition:transform .15s; font-size:18px; line-height:1; color:var(--muted); }
  #tsCustom[open] summary::after{ transform:rotate(90deg); }
  #tsCustom .ts-target{ margin:8px 0 12px; }
  .ts-hue{
    -webkit-appearance:none; appearance:none; width:100%; height:14px; border-radius:999px; outline:none; cursor:pointer; margin:2px 0 12px;
    background:linear-gradient(to right, hsl(0,85%,55%), hsl(60,85%,55%), hsl(120,85%,55%), hsl(180,85%,55%), hsl(240,85%,55%), hsl(300,85%,55%), hsl(360,85%,55%));
  }
  .ts-hue::-webkit-slider-thumb{ -webkit-appearance:none; appearance:none; width:26px; height:26px; border-radius:50%; background:var(--ts-thumb, #fff); border:3px solid #fff; box-shadow:0 0 0 1px rgba(0,0,0,.25), 0 2px 6px rgba(0,0,0,.3); cursor:pointer; }
  .ts-hue::-moz-range-thumb{ width:22px; height:22px; border-radius:50%; background:var(--ts-thumb, #fff); border:3px solid #fff; box-shadow:0 0 0 1px rgba(0,0,0,.25), 0 2px 6px rgba(0,0,0,.3); cursor:pointer; }
  .ts-hex-row{ display:flex; align-items:center; gap:8px; }
  .ts-hex{ display:flex; align-items:center; background:var(--card-bg); border:1.5px solid var(--line); border-radius:10px; padding:0 8px; height:36px; width:112px; }
  .ts-hex span{ color:var(--muted); font-weight:800; }
  .ts-hex input{ border:none; background:none; outline:none; width:100%; font:700 13px ui-monospace, SFMono-Regular, Menlo, monospace; color:var(--ink); text-transform:uppercase; padding:0 0 0 2px; }
  .ts-hex.bad{ border-color:var(--bad); }
  .ts-picker{ width:36px; height:36px; border-radius:10px; overflow:hidden; border:1.5px solid var(--line); flex:none; cursor:pointer; position:relative; background:conic-gradient(red, yellow, lime, cyan, blue, magenta, red); }
  .ts-picker input{ position:absolute; inset:0; opacity:0; width:100%; height:100%; cursor:pointer; }
  .ts-contrast{ font-size:11px; font-weight:700; color:var(--muted); flex:1; text-align:right; }
  .ts-foot{ display:flex; gap:8px; margin-top:16px; align-items:center; }
  .ts-reset{ border:none; background:none; color:var(--muted); font:700 12.5px var(--font); cursor:pointer; padding:10px 6px; white-space:nowrap; }
  #themeSheet #themeSheetClose{ flex:1; margin:0; }
  .dark-toggle{
    /* Now flows inline in the compact floating cluster instead of being
       absolutely pinned inside a full-width banner — that positioning
       doesn't apply once the whole bar is just a small pill.
       relative (not static) so its 44px ::after tap area centres on the button
       instead of the header row — it used to sit on top of the EN/VI switch. */
    position:relative; z-index:2;
    width:28px; height:28px; border-radius:50%;
    background:transparent; border:none; cursor:pointer;
    font-size:14px; display:flex; align-items:center; justify-content:center;
    color:var(--ink); flex-shrink:0;
  }
  .dark-toggle:active{ background:var(--paper-dark); }
  .account-toggle{
    height:28px; width:28px; padding:0; border-radius:50%;
    background:transparent; border:none; cursor:pointer;
    font-size:14px; font-weight:700; font-family:var(--font);
    display:flex; align-items:center; justify-content:center;
    color:var(--ink); flex-shrink:0; overflow:hidden;
  }
  /* Icon-only in the compact floating cluster — JS sets these labels to a
     bare emoji (see updateAccountUI / the direction-toggle handler), and the
     full text lives in each button's title="" for a hover tooltip instead. */
  .account-toggle span, #directionToggleLabel{ line-height:1; }
  .account-toggle:active{ background:var(--paper-dark); }
  .account-toggle.signed-in #accountToggleLabel{ width:100%; height:100%; display:flex; align-items:center; justify-content:center; }
  .account-toggle .acct-pic{ width:100%; height:100%; object-fit:cover; border-radius:50%; display:block; box-shadow:0 0 0 2px var(--cover); }
  .account-toggle .acct-initial{ width:100%; height:100%; border-radius:50%; display:flex; align-items:center; justify-content:center;
    background:var(--cover); color:#fff; font-weight:800; font-size:0.95em; }
  #teacherModeToggle.active{ background:#f97316; color:#fff; }
  #teacherModeBanner{
    position:sticky; top:0; z-index:60; background:#f97316; color:#fff;
    font-family:var(--font); font-weight:700; font-size:12px;
    padding:7px 12px; text-align:center; display:flex; align-items:center;
    justify-content:center; gap:10px; flex-wrap:wrap;
  }
  #teacherModeBannerOff{
    background:rgba(255,255,255,0.25); border:none; color:#fff; border-radius:999px;
    padding:3px 10px; font-weight:700; font-size:11px; cursor:pointer; font-family:var(--font);
  }
  #teacherStudentPicker{
    border-radius:999px; border:none; background:rgba(255,255,255,0.25); color:#fff;
    font-family:var(--font); font-size:11px; font-weight:700; padding:3px 6px;
  }
  #teacherInviteBtn{
    background:rgba(255,255,255,0.25); border:none; color:#fff; border-radius:999px;
    padding:3px 10px; font-weight:700; font-size:11px; cursor:pointer; font-family:var(--font);
  }
  .teacher-pin-btn{
    background:#c2410c; color:#fff; border:none; border-radius:8px;
    padding:6px 12px; font-weight:700; font-size:12px; cursor:pointer; font-family:var(--font);
    margin-top:6px;
  }
  .teacher-pin-btn:disabled{ opacity:0.5; cursor:not-allowed; }
  .tf-package-row{
    border:1px solid var(--line); border-radius:10px; padding:10px;
    margin-bottom:8px; background:var(--paper);
  }
  .tf-package-row .tf-package-grid{
    display:flex; flex-wrap:wrap; gap:6px; margin-bottom:6px;
  }
  .tf-package-row input{
    flex:1 1 100px; min-width:0;
  }
  .tf-package-remove{
    background:none; border:none; color:var(--bad); font-weight:700;
    cursor:pointer; font-family:var(--font); font-size:12px; padding:2px 6px;
  }
  .package-card{
    border:1px solid var(--line); border-radius:12px; padding:12px;
    margin-bottom:8px; background:var(--paper);
  }
  .package-card .package-name{ font-weight:800; font-size:14px; color:var(--ink); }
  .package-card .package-price{ font-weight:800; font-size:16px; color:var(--cover); margin-top:2px; }
  .package-card .package-meta{ font-size:11px; color:var(--muted); margin-top:2px; }
  .package-card .package-desc{ font-size:12.5px; color:var(--muted); margin-top:4px; }
  .package-card .package-book-btn{
    margin-top:8px; width:100%; border:none; border-radius:999px; padding:8px 10px;
    background:var(--cover); color:var(--on-cover); font-weight:700; font-size:12.5px;
    cursor:pointer; font-family:var(--font);
  }
  .teacher-panel{
    display:none; margin:10px 0; padding:10px 12px; border-radius:12px;
    background:rgba(249,115,22,0.10); border:1px solid rgba(249,115,22,0.35);
    font-family:var(--font);
  }
  .teacher-panel.show{ display:block; }
  .teacher-panel-label{
    font-size:10px; font-weight:800; text-transform:uppercase; letter-spacing:0.04em;
    color:#c2410c; margin-bottom:6px;
  }
  .teacher-answer-key{ font-size:14px; font-weight:700; color:#7c2d12; word-break:break-word; }
  .teacher-syllable-row{ display:flex; flex-wrap:wrap; gap:6px; margin-top:8px; }
  .teacher-syllable-chip{
    background:#fff; border:1px solid rgba(249,115,22,0.5); border-radius:8px;
    padding:4px 8px; font-size:12px; cursor:pointer; font-family:var(--font);
  }
  .teacher-syllable-chip:active{ background:rgba(249,115,22,0.2); }
  .teacher-inline-row{ display:flex; gap:6px; margin-top:6px; flex-wrap:wrap; }
  .teacher-inline-row input[type="text"]{
    flex:1; min-width:140px; padding:6px 8px; border-radius:8px;
    border:1px solid rgba(249,115,22,0.4); font-family:var(--font); font-size:13px;
  }
  .teacher-inline-row select{
    padding:6px 8px; border-radius:8px; border:1px solid rgba(249,115,22,0.4);
    font-family:var(--font); font-size:12px;
  }
  .teacher-inline-row button{
    background:#f97316; color:#fff; border:none; border-radius:8px;
    padding:6px 12px; font-weight:700; font-size:12px; cursor:pointer; font-family:var(--font);
  }
  .match-card .teacher-pair-badge{
    position:absolute; top:2px; left:4px; font-size:10px; font-weight:800;
    color:#c2410c; background:rgba(255,255,255,0.85); border-radius:6px; padding:0 4px;
  }
  *{box-sizing:border-box; -webkit-tap-highlight-color:transparent;}
  /* A long press on a button used to start native text selection instead of
     firing the button — the selection handles appeared, the tap was eaten, and
     press-and-hold gestures (pinning a tab, removing a card) failed roughly
     half the time. Selection is switched off on anything you're meant to press.
     Content stays selectable on purpose: learners copy Vietnamese words out to
     Zalo and Translate, so words, sentences, passages, bios and chat messages
     are deliberately not in this list. */
  button, a, label, [role="button"], summary,
  .more-item, .cat-chip, .opt, .skip-btn, .check-btn, .speak-btn, .accent-btn,
  .dialect-btn, .study-deck-btn, .tab-btn, .bn-btn, .pr-pill, .pr-back-btn,
  .ev-btn, .star-btn, .teacher-contact-btn, .teacher-modal-close, .pr-create-card,
  .nav-row, .cats, .icon-legend, .tone-legend, .diff-badge, .region-badge,
  .prog-stat, .call-util-btn, .live-act, .layout-btn, .fav-icon-btn,
  .msg-tab, .il-x, .more-pin, .more-check{
    -webkit-user-select:none;
    -moz-user-select:none;
    user-select:none;
    -webkit-touch-callout:none;
  }
  /* Inputs must stay selectable even when a rule above catches their wrapper —
     otherwise you can't place a cursor or fix a typo mid-word. */
  input, textarea, select, [contenteditable="true"]{
    -webkit-user-select:text;
    user-select:text;
    -webkit-touch-callout:default;
  }
  body{
    margin:0;
    background:var(--paper);
    background-image:
      radial-gradient(600px circle at 8% -5%, rgba(29,145,120,0.10), transparent 55%),
      radial-gradient(600px circle at 100% 10%, rgba(242,126,109,0.08), transparent 50%);
    background-attachment:fixed;
    font-family: var(--font);
    color:var(--ink);
    min-height:100vh;
    display:flex;
    justify-content:center;
    padding:18px 12px 40px;
    -webkit-font-smoothing:antialiased;
  }
  .book{
    width:100%;
    max-width:480px;
    position:relative;
  }
  /* ---------- Desktop / wide-browser layout ----------
     Everything above is tuned for a phone-width column, which is right for
     reading and flashcards but leaves a browser window mostly empty. From
     here up we give the shell more room and let a few specific grids (the
     public-room cards, the "more" menu) use the extra width — the rest of
     the app keeps its phone-width column on purpose, since long lines of
     text and cramped flashcards are worse than unused side margin. */
  @media (min-width:760px){
    body{ padding:32px 24px 40px; }
    .book{ max-width:640px; }
  }
  @media (min-width:1080px){
    .book{ max-width:760px; }
    .pr-room-grid{ grid-template-columns:1fr 1fr 1fr; }
    .more-grid{ grid-template-columns:repeat(4,1fr); }
  }
  /* Big computer screens: the phone-sized column looked tiny (people were
     zooming the browser to 150% to read it). Scale the main page and the
     bottom bar up on wide mouse-driven screens only — phones and tablets are
     untouched. Pop-ups and calls live outside .book and keep normal size;
     the full-screen typing tutor switches the scale off. */
  @media (min-width:1600px) and (hover:hover) and (pointer:fine){ .book, #bottomNav{ zoom:1.05; } }
  @media (min-width:1900px) and (hover:hover) and (pointer:fine){ .book, #bottomNav{ zoom:1.12; } }
  @media (min-width:2300px) and (hover:hover) and (pointer:fine){ .book, #bottomNav{ zoom:1.26; } }
  body.in-type-tutor .book{ zoom:1 !important; }
  /* A 1:1 video call filling an ultra-wide monitor edge-to-edge looks
     stretched and makes faces huge; cap the stage so it reads like a call,
     not a billboard, and letterbox the rest. Group calls with several tiles
     already fill sensibly, so this only kicks in for the solo layout. */
  @media (min-width:900px){
    .live-tiles.solo{ max-width:640px; max-height:76vh; margin:0 auto; }
  }
  /* The study sheet was built to float over the small 1:1 solo-call PIP
     video without resizing it (see setStudyOpenLayout) — fine there, but in
     a group room with two tiles stacked to fill the whole screen, that same
     floating sheet was landing squarely on top of the second person and
     hiding them completely instead of the video making room. Shrink the
     stage so the tiles reflow above the sheet instead of under it. */
  /* Docked (mobile) study panel still sits full-width across the bottom of
     the screen and needs the stage to make room, same as before. On desktop
     the docked panel is already a small 400px corner box (see .study-panel
     media query above), so this only matters below that breakpoint — and
     the video's own floating/resizable state (see .live-stage.floating)
     takes over there instead of coupling to the study panel's state. */
  @media (max-width:759px){
    body.in-live-room.study-open:not(.in-solo-call) .live-stage{ max-height:48vh; }
  }
  /* No longer a banner — just a bare row of small icon buttons, right-
     aligned, no card/border/shadow of its own, so it reads as a handful of
     controls rather than a stacked header above whatever the current tab's
     own top content is (the Start Here greeting banner, etc). */
  .cover-title{
    text-align:right;
    color:var(--ink);
    background:transparent;
    border:none;
    padding:0;
    margin:0 0 6px;
    box-shadow:none;
    position:relative;
    overflow:visible;
    display:flex;
    flex-wrap:nowrap;
    align-items:center;
    justify-content:flex-end;
    gap:2px;
  }
  .cover-title::after{ display:none; }
  .cover-title .title-block{ display:none; }
  .cover-title h1{
    font-family:var(--font-display);
    font-size:24px;
    margin:0 0 2px;
    font-weight:700;
    letter-spacing:-0.01em;
    position:relative;
    white-space:nowrap;
  }
  .cover-title .tagline{
    font-family:var(--font);
    font-size:12px;
    font-weight:800;
    letter-spacing:.08em;
    text-transform:uppercase;
    color:rgba(255,255,255,0.95);
    position:relative;
    margin-bottom:3px;
  }
  .cover-title .sub{
    font-family:var(--font);
    font-size:11.5px;
    font-weight:500;
    color:rgba(255,255,255,0.85);
    opacity:1;
    position:relative;
  }
  .cover-title .header-actions{
    position:relative;
    display:flex;
    align-items:center;
    flex-wrap:nowrap;
    gap:2px;
  }
  .page{
    background:var(--card);
    border-radius:var(--radius-lg);
    box-shadow:var(--shadow);
    padding:20px 18px 24px;
    position:relative;
    overflow:hidden;
  }
  .content{
    position:relative;
  }
  nav.tabs{
    display:flex;
    flex-wrap:wrap;
    gap:6px;
    margin-bottom:16px;
  }
  nav.tabs button{
    flex:1 1 auto;
    font-family:var(--font);
    font-size:11px;
    font-weight:700;
    letter-spacing:0.1px;
    padding:8px 10px;
    border-radius:999px;
    border:none;
    background:var(--paper-dark);
    color:var(--muted);
    cursor:pointer;
    white-space:nowrap;
    text-align:center;
    transition:background .15s ease, color .15s ease, transform .1s ease;
  }
  nav.tabs button.active{
    background:var(--cover);
    color:var(--on-cover);
    box-shadow:var(--shadow-sm);
  }
  nav.tabs button:active{ animation:btnPop .28s ease-out; }
  h2.section-title{
    font-family:var(--font-display);
    font-size:22px;
    margin:0 0 4px;
    font-weight:700;
    letter-spacing:0;
    color:var(--ink);
  }
  /* Collapsible settings/browse sections — keeps dense config rows out of
     the way by default so the actual flashcard is reachable without
     scrolling, per the "no page should need forever-scrolling" pass.
     Plain <details>/<summary>, no JS needed, so nothing about how the
     content inside behaves had to change. */
  #learnSettingsDetails, #learnBrowseDetails{
    margin:10px 0 12px; border:1px solid var(--line); border-radius:var(--radius);
    background:var(--card); overflow:hidden;
  }
  #learnSettingsSummary, #learnBrowseSummary{
    list-style:none; cursor:pointer; padding:11px 14px; font-family:var(--font);
    font-size:12.5px; font-weight:700; color:var(--ink); display:flex;
    align-items:center; justify-content:space-between;
  }
  #learnSettingsSummary::-webkit-details-marker, #learnBrowseSummary::-webkit-details-marker{ display:none; }
  #learnSettingsSummary::after, #learnBrowseSummary::after{
    content:'›'; font-size:16px; color:var(--muted); transform:rotate(90deg); transition:transform .15s ease;
  }
  details[open] > #learnSettingsSummary::after, details[open] > #learnBrowseSummary::after{ transform:rotate(-90deg); }
  #learnSettingsBody, #learnBrowseSettingsBody{ padding:0 14px 14px; }
  /* Same collapsible pattern, reused for Progress's Weekly Rhythm / Badges /
     Activity sections — those are worth checking but not what most visits
     to this tab are for, so they're tucked behind a tap instead of forcing
     a long scroll past them to reach... well, past them, since they're the
     last three sections anyway; this mainly just shrinks the page's resting
     height so it doesn't look like a wall of stats on first open. */
  .progress-collapsible{
    margin:14px 0 0; border:1px solid var(--line); border-radius:var(--radius);
    background:var(--card); overflow:hidden;
  }
  .progress-collapsible summary{
    list-style:none; cursor:pointer; padding:11px 14px; font-family:var(--font);
    font-size:13px; font-weight:700; color:var(--ink); display:flex;
    align-items:center; justify-content:space-between;
  }
  .progress-collapsible summary::-webkit-details-marker{ display:none; }
  .progress-collapsible summary::after{
    content:'›'; font-size:16px; color:var(--muted); transform:rotate(90deg); transition:transform .15s ease;
  }
  .progress-collapsible[open] summary::after{ transform:rotate(-90deg); }
  .progress-collapsible-body{ padding:2px 14px 14px; }
  /* Chunky-shadow treatment for the four SRS grading buttons — same
     press-down signature as the rest of the app's primary actions, each
     shadowed in a deeper shade of its own semantic color rather than one
     shared color, since they're deliberately color-coded (red/orange/
     green/teal) and a single shadow tone would flatten that distinction. */
  #againBtn.srs-btn{ box-shadow:0 4px 0 #a30008; }
  #hardBtn.srs-btn{ box-shadow:0 4px 0 #c05a3d; }
  #goodBtn.srs-btn{ box-shadow:0 4px 0 var(--cover-deep); }
  #easyBtn.srs-btn{ box-shadow:0 4px 0 var(--cover-deep); }
  .srs-btn{ border-radius:var(--radius); font-weight:800; padding:12px 8px; transition:transform .08s ease, box-shadow .08s ease; }
  .srs-btn:active{ transform:translateY(3px); animation:none !important; }
  #againBtn.srs-btn:active{ box-shadow:0 1px 0 #a30008; }
  #hardBtn.srs-btn:active{ box-shadow:0 1px 0 #c05a3d; }
  #goodBtn.srs-btn:active{ box-shadow:0 1px 0 var(--cover-deep); }
  #easyBtn.srs-btn:active{ box-shadow:0 1px 0 var(--cover-deep); }
  .section-note{
    font-family:var(--font);
    font-size:13px;
    font-weight:500;
    line-height:1.45;
    color:var(--muted);
    margin-bottom:16px;
  }

  /* word counter badge */
  .stamp{
    float:right;
    display:flex;
    align-items:baseline;
    gap:4px;
    margin:0 0 10px 12px;
    background:var(--paper-dark);
    color:var(--cover);
    padding:7px 13px;
    border-radius:999px;
    font-family:var(--font);
  }
  .stamp .num{ font-size:14px; font-weight:800; line-height:1;}
  .stamp .lbl{ font-size:10px; font-weight:700; letter-spacing:0.4px; text-transform:uppercase; color:var(--muted);}

  /* categories */
  .cats{
    display:flex;
    flex-wrap:wrap;
    gap:7px;
    margin-bottom:14px;
  }
  .cat-chip.cat-more{ font-style:italic; opacity:.8; }
  .cat-chip{
    font-family:var(--font);
    font-size:12px;
    font-weight:700;
    padding:6px 12px;
    min-height:36px; /* v224: chips were 29px tall everywhere */
    display:inline-flex; align-items:center;
    border-radius:999px;
    background:var(--paper-dark);
    border:none;
    cursor:pointer;
    color:var(--ink);
    transition:background .15s, color .15s;
  }
  .cat-chip.active{
    background:var(--cover);
    border-color:var(--cover);
    color:var(--on-cover);
  }
  .cat-chip.locked{
    opacity:0.4;
    cursor:not-allowed;
  }
  .cat-chip.forced{
    border-style:dashed;
    border-color:var(--gold);
  }

  /* flashcard */
  .card-wrap{
    perspective:1000px;
    margin:6px 0 8px;
  }
  .card{
    min-height:150px;
    border:none;
    border-radius:var(--radius-lg);
    background:var(--card);
    display:flex;
    align-items:center;
    justify-content:center;
    flex-direction:column;
    text-align:center;
    padding:18px 46px 18px 46px;
    cursor:pointer;
    box-shadow:var(--shadow);
    position:relative;
    transition:transform .12s ease;
  }
  .card:active{ transform:scale(0.98); }
  /* Speak/mic/record buttons all sit in one fixed side rail (right) instead
     of stacking in the card's normal flow or splitting across both edges —
     keeps every action reachable from the same spot. */
  .card .card-side{
    position:absolute;
    top:50%;
    transform:translateY(-50%);
    display:flex;
    flex-direction:column;
    gap:8px;
    z-index:2;
  }
  .card .card-side.right{ right:10px; }
  /* Deliberately separated from the plain gray speak/mic/record rail and
     given the accent color instead of the muted default — this is the one
     button on the card meant to be noticed at a glance, not blended in with
     the utility icons. Sits at the same vertical center, opposite side. */
  .card-edit-btn{
    position:absolute;
    top:50%; left:10px;
    transform:translateY(-50%);
    z-index:2;
    background:var(--cover);
    color:var(--on-cover);
    width:34px; height:34px;
    font-size:15px;
  }
  .card-edit-btn:active{ background:var(--gold); color:var(--on-accent); }
  .card .vn{
    font-size:calc(28px * var(--flash-scale, 1));
    font-weight:800;
    letter-spacing:-0.01em;
    color:var(--ink);
  }
  /* Tone color coding — one color per tone mark, applied to the flashcard word.
     ngang (no mark, flat tone) is left as the default ink color. */
  .tone-huyen{ color:#2563eb; }  /* huyền — grave, low-falling */
  .tone-sac{ color:#ea580c; }    /* sắc — acute, high-rising (v265: was #f97316 — 2.8:1 on white, so the contrast guard
                                    repainted it a darker orange a second after the card showed) */
  .tone-hoi{ color:#16a34a; }    /* hỏi — hook above, dipping-rising */
  .tone-nga{ color:#9333ea; }    /* ngã — tilde, broken-rising */
  .tone-nang{ color:#b91c1c; }   /* nặng — dot below, low-heavy */
  /* v265: dark mode gets its own tone colors (the light ones were too dark there and got repainted after a moment) */
  body.dark-mode .tone-huyen{ color:#60a5fa; } body.dark-mode .tone-sac{ color:#fb923c; } body.dark-mode .tone-hoi{ color:#4ade80; }
  body.dark-mode .tone-nga{ color:#c084fc; } body.dark-mode .tone-nang{ color:#f87171; }
  .rd-word{ cursor:pointer; border-radius:4px; padding:0 1px; text-decoration:underline; text-decoration-style:dotted; text-decoration-color:var(--muted-soft); text-underline-offset:3px; }
  .rd-word:active{ background:var(--primary-tint); }
  .icon-legend{
    display:flex;
    flex-wrap:wrap;
    gap:4px 10px;
    align-items:center;
    justify-content:center;
    font-family:var(--font);
    font-size:10.5px;
    color:var(--muted);
    margin-top:6px;
  }
  .icon-legend b{ font-weight:400; font-size:12px; margin-right:2px; }
  .icon-legend .il-x{
    border:none; background:none; color:var(--muted); cursor:pointer;
    font-size:11px; padding:0 2px; line-height:1;
  }
  .tone-legend{
    display:flex;
    flex-wrap:wrap;
    gap:6px 10px;
    justify-content:center;
    font-family:var(--font);
    font-size:10.5px;
    color:var(--muted);
    margin-top:6px;
  }
  .tone-legend span{ display:inline-flex; align-items:center; gap:3px; }
  .tone-legend .dot{ width:7px; height:7px; border-radius:50%; display:inline-block; }
  .card .en{
    font-size:calc(14.5px * var(--flash-scale, 1));
    font-weight:500;
    font-family:var(--font);
    color:var(--muted);
    margin-top:8px;
  }
  .card .hint{
    font-family:var(--font);
    font-size:12px;
    font-weight:700;
    color:var(--muted);
    margin-top:14px;
    text-transform:uppercase;
    letter-spacing:1px;
  }
  .card .cat-tag{
    position:absolute;
    top:14px; left:16px;
    font-family:var(--font);
    font-size:11px;
    font-weight:700;
    letter-spacing:0.6px;
    text-transform:uppercase;
    color:var(--stamp-ink, var(--stamp));
    background:var(--stamp-tint);
    padding:3px 9px;
    border-radius:999px;
  }
  .nav-row{
    display:flex;
    justify-content:space-between;
    align-items:center;
    font-family:var(--font);
    gap:8px;
  }
  .nav-row button{
    background:var(--paper-dark);
    color:var(--ink);
    border:none;
    padding:10px 18px;
    min-height:40px;
    border-radius:999px;
    font-size:13px;
    font-weight:700;
    cursor:pointer;
    transition:background .15s, transform .1s;
  }
  .nav-row button:active{ transform:scale(0.96); }
  .nav-row .count{
    font-size:12px;
    font-weight:600;
    color:var(--muted);
  }

  /* Flashcards: slim arrow buttons around a short "2 / 20" counter, and a quiet
     2×2 tools row — the old full-width pills were the biggest things on screen. */
  .fc-nav{ display:grid; grid-template-columns:48px 1fr 48px; align-items:center; gap:10px; }
  .fc-nav button{ width:48px; height:44px; padding:0; font-size:20px; line-height:1; border-radius:14px; background:var(--paper-dark); }
  .fc-nav .count{ text-align:center; display:flex; flex-direction:column; gap:2px; min-width:0; }
  .fc-nav .count b{ font-size:15px; font-weight:800; color:var(--ink); }
  .fc-nav .count small{ font-size:11px; font-weight:600; color:var(--muted); line-height:1.25; }
  .fc-tools{ display:grid; grid-template-columns:repeat(4,1fr); gap:8px; margin-top:8px; }
  .fc-tools button{ min-height:40px; padding:8px 6px; font-size:12.5px; border:1.5px solid var(--line); background:transparent; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; border-radius:12px; }
  @media (max-width:520px){ .fc-tools{ grid-template-columns:repeat(2,1fr); } }

  /* quiz */
  .quiz-q{
    font-size:21px;
    font-weight:800;
    color:var(--ink);
    margin-bottom:16px;
    min-height:52px;
    letter-spacing:-0.01em;
  }
  .opt{
    display:block;
    width:100%;
    text-align:left;
    font-family:var(--font);
    font-size:14.5px;
    font-weight:600;
    padding:13px 16px;
    margin-bottom:9px;
    border-radius:var(--radius-sm);
    border:2px solid var(--line);
    background:var(--card);
    cursor:pointer;
    color:var(--ink);
    transition:border-color .12s, background .12s;
  }
  .opt.correct{ background:var(--ok-bg); border-color:var(--ok); color:var(--ok-ink, var(--ok)); font-weight:800;}
  .opt.wrong{ background:var(--bad-bg); border-color:var(--bad); color:var(--bad-ink, var(--bad));}
  .opt:disabled{ cursor:default; }
  .quiz-score{
    font-family:var(--font);
    font-size:12.5px;
    font-weight:600;
    color:var(--muted);
    margin-bottom:10px;
  }

  /* sentence builder */
  .target-en{
    font-family:var(--font);
    font-size:12px;
    font-weight:700;
    color:var(--muted);
    margin-bottom:8px;
    text-transform:uppercase;
    letter-spacing:0.5px;
  }
  .build-zone{
    min-height:58px;
    border:2px dashed var(--line);
    background:var(--paper-dark);
    border-radius:var(--radius-sm);
    display:flex;
    flex-wrap:wrap;
    gap:8px;
    align-items:flex-start;
    padding:10px 12px;
    margin-bottom:16px;
  }
  .word-chip{
    font-family:var(--font);
    font-size:15px;
    font-weight:700;
    padding:9px 14px;
    background:var(--cover);
    color:var(--on-cover);
    border-radius:var(--radius-sm);
    cursor:pointer;
    border:none;
    box-shadow:var(--shadow-sm);
  }
  .bank{
    display:flex;
    flex-wrap:wrap;
    gap:8px;
    margin-bottom:18px;
  }
  .bank .word-chip{
    background:var(--card);
    color:var(--ink);
    border:2px solid var(--line);
    box-shadow:none;
  }
  .check-btn{
    font-family:var(--font);
    background:var(--cover);
    color:var(--on-cover);
    border:none;
    padding:12px 22px;
    border-radius:999px;
    font-size:13.5px;
    font-weight:700;
    cursor:pointer;
    margin-right:8px;
    /* Chunky-shadow signature, app-wide — this is the shared "primary
       action" class (29 uses across every tab), so upgrading it here
       covers Quiz's Check, Save-word, and most other tabs' main CTA in
       one place instead of touching each tab individually. */
    box-shadow:0 4px 0 var(--cover-deep);
    transition:transform .08s ease, box-shadow .08s ease;
  }
  .check-btn:active{ transform:translateY(3px); box-shadow:0 1px 0 var(--cover-deep); animation:none; }
  .check-btn:disabled{
    opacity:0.4;
    cursor:default;
    box-shadow:none;
    transform:none;
  }
  .skip-btn{
    font-family:var(--font);
    background:var(--card);
    color:var(--ink);
    border:2px solid var(--line);
    padding:10px 20px;
    border-radius:999px;
    font-size:13px;
    font-weight:700;
    cursor:pointer;
  }
  .skip-btn.active{
    background:var(--cover);
    color:var(--on-cover);
    border-color:var(--cover);
  }
  .dialect-btn{
    font-family:var(--font);
    background:var(--card);
    color:var(--ink);
    border:2px solid var(--line);
    padding:8px 14px;
    border-radius:999px;
    font-size:12.5px;
    font-weight:700;
    cursor:pointer;
    flex:1;
  }
  .dialect-btn.active{
    background:var(--cover);
    color:var(--on-cover);
    border-color:var(--cover);
  }
  .feedback{
    font-family:var(--font);
    font-size:13.5px;
    font-weight:600;
    margin-top:14px;
    padding:12px 14px;
    border-radius:var(--radius-sm);
  }
  .feedback.ok{ background:var(--ok-bg); color:var(--ok-ink, var(--ok)); }
  .feedback.bad{ background:var(--bad-bg); color:var(--bad-ink, var(--bad)); }
  .why-wrong{
    font-family:var(--font);
    font-size:12.5px;
    font-weight:500;
    line-height:1.5;
    margin-top:10px;
    padding:10px 12px;
    border-radius:var(--radius-sm);
    background:var(--bad-bg);
    color:var(--bad-ink, var(--bad));
  }
  .feedback.bad .why-wrong{
    margin-top:8px;
    padding-top:8px;
    padding-left:0; padding-right:0; padding-bottom:0;
    border-radius:0;
    background:transparent;
    border-top:1px solid rgba(239,68,68,0.25);
  }
  .en-word{
    transition:background 0.2s, color 0.2s;
    border-radius:4px;
    padding:0 3px;
  }
  .en-word.hit{
    background:var(--gold);
    color:var(--on-accent);
    font-weight:800;
  }
  .gloss-note{
    font-family:var(--font);
    font-size:11px;
    font-weight:500;
    font-style:italic;
    color:var(--muted-soft);
    min-height:14px;
    margin:-2px 0 4px;
  }

  .prog-stats{
    display:grid;
    grid-template-columns:1fr 1fr;
    gap:10px;
    margin-bottom:20px;
  }
  .prog-stats > .prog-stat:nth-child(odd):last-child{ grid-column:1 / -1; } /* v224: no orphan tile */
  .prog-stat{
    background:var(--paper-dark);
    border:none;
    border-radius:var(--radius);
    padding:16px 8px;
    text-align:center;
  }
  .prog-num{
    font-family:var(--font-display);
    font-size:27px;
    font-weight:700;
    color:var(--cover);
  }
  .prog-lbl{
    font-family:var(--font);
    font-size:10.5px;
    font-weight:700;
    color:var(--muted);
    text-transform:uppercase;
    letter-spacing:0.5px;
    margin-top:3px;
  }
  h3.review-title{
    font-size:15.5px;
    color:var(--ink);
    font-weight:700;
    margin:0 0 4px;
  }
  .review-list{
    display:flex;
    flex-wrap:wrap;
    gap:7px;
  }
  .review-chip{
    font-family:var(--font);
    font-size:12px;
    font-weight:600;
    padding:6px 11px;
    background:var(--bad-bg);
    color:var(--bad-ink, var(--bad));
    border-radius:999px;
  }
  .leech-chip{
    font-family:var(--font);
    font-size:12px;
    font-weight:600;
    padding:6px 11px;
    background:var(--warn-bg);
    color:var(--warn-ink, var(--warn));
    border-radius:999px;
    cursor:default;
  }
  .heatmap-grid{
    display:grid;
    grid-template-columns:repeat(14,1fr);
    gap:4px;
    margin-top:8px;
    max-width:460px; /* v224: on wide screens the cells grew to 77px */
  }
  .heatmap-cell{
    aspect-ratio:1/1;
    border-radius:4px;
    background:var(--paper-dark);
    max-width:28px;
  }
  .heatmap-cell[data-level="1"]{ background:#c3ecd2; }
  .heatmap-cell[data-level="2"]{ background:#7ed19b; }
  .heatmap-cell[data-level="3"]{ background:#31b464; }
  .heatmap-cell[data-level="4"]{ background:var(--ok); }
  .review-empty{
    font-family:var(--font);
    font-size:12.5px;
    font-weight:500;
    color:var(--muted);
  }

  .grammar-card{
    background:var(--card);
    border:none;
    border-radius:var(--radius);
    padding:18px 18px 16px;
    margin-bottom:6px;
    box-shadow:var(--shadow-sm);
  }
  .grammar-title{
    font-size:18px;
    font-weight:800;
    color:var(--ink);
    margin-bottom:6px;
  }
  .grammar-template{
    font-family:var(--font);
    font-size:13px;
    font-weight:700;
    color:var(--cover);
    background:var(--primary-tint);
    display:inline-block;
    padding:5px 11px;
    border-radius:8px;
    margin-bottom:9px;
    letter-spacing:0.2px;
  }
  .grammar-note{
    font-family:var(--font);
    font-size:12.5px;
    font-weight:500;
    color:var(--muted);
    line-height:1.6;
    margin-bottom:10px;
  }
  .grammar-examples{
    display:flex;
    flex-direction:column;
    gap:7px;
  }
  .grammar-ex{
    font-family:var(--font);
    font-size:12.5px;
    background:var(--paper-dark);
    border:none;
    border-radius:10px;
    padding:9px 12px;
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:8px;
  }
  .grammar-ex .vn{
    font-family:var(--font);
    font-weight:700;
    font-size:15px;
    color:var(--ink);
    display:block;
  }
  .grammar-ex .en{
    color:var(--muted);
    font-size:11.5px;
    font-weight:500;
  }

  footer{
    text-align:center;
    color:var(--muted);
    font-family:var(--font);
    font-size:12.5px;
    font-weight:600;
    margin-top:18px;
  }
  footer a{ display:inline-block; padding:12px 6px; } /* v224: 44px tall links (were 14px) */

  /* speaker buttons */
  .speak-btn{
    display:inline-flex;
    align-items:center;
    justify-content:center;
    width:36px; height:36px;
    border-radius:50%;
    border:none;
    background:var(--paper-dark);
    color:var(--cover);
    font-size:14px;
    cursor:pointer;
    flex-shrink:0;
  }
  .speak-btn:active{ background:var(--gold); color:var(--on-accent); animation:btnPop .28s ease-out; }
  .skip-btn:active{ animation:btnPop .28s ease-out; }
  .speak-btn.active{ background:var(--bad); color:#fff; animation:pulse 1s infinite; }
  .speak-btn.on{ background:var(--cover); color:var(--on-cover); }
  @keyframes pulse{ 0%,100%{opacity:1;} 50%{opacity:0.55;} }
  /* Cutesy pass: a springy little "pop" on tap instead of the flat
     scale-down every button had before — overshoots past 1.0 on release
     so it reads as bouncy rather than just "pressed", the way a chunky
     rounded pill button on a playful app usually feels. Kept to a single
     shared keyframe so every button (check/skip/speak/tab) picks it up
     for free via the transition timing function change below, rather than
     each needing its own animation wired up. */
  @keyframes btnPop{ 0%{transform:scale(0.94);} 60%{transform:scale(1.05);} 100%{transform:scale(1);} }
  /* The turtle mascot ties into the app's existing "🐢 Turtle mode" —
     reusing that idea rather than inventing an unrelated character. One
     slow bob on the one screen it lives on (Start Here's landing choice)
     is the "spend your boldness in one place" motion; it doesn't repeat
     on every screen. */
  @keyframes mascotBob{ 0%,100%{transform:translateY(0);} 50%{transform:translateY(-6px);} }
  .sh-mascot{ display:block; margin:4px auto 8px; animation:mascotBob 2.6s ease-in-out infinite; }
  /* One more use of the same "answers a person's action" motion rule:
     this only fires once, right when a quiz round is scored as a pass —
     it's confirming something that just happened, not decorating the
     screen on load. */
  @keyframes celebratePop{ 0%{transform:scale(0.85); opacity:0;} 60%{transform:scale(1.04); opacity:1;} 100%{transform:scale(1);} }
  .rd-wrap-pass{ animation:celebratePop .4s ease-out; }
  .card .speak-btn{
    margin-top:0;
  }
  .font-size-ctrl{ display:flex; gap:4px; }
  .font-size-ctrl button{
    border:1px solid var(--paper-dark); background:var(--paper); color:var(--ink);
    border-radius:8px; width:40px; height:36px; font-weight:800; font-size:13px;
    font-family:var(--font); cursor:pointer;
  }
  .font-size-ctrl button:active{ background:var(--paper-dark); }
  /* reading passages */
  .reading-line{
    display:flex;
    align-items:center;
    gap:10px;
    padding:12px 0;
    border-bottom:1px solid var(--paper-dark);
  }
  .reading-line:last-child{ border-bottom:none; }
  .reading-vn{ font-size:17px; color:var(--cover-deep); line-height:1.5; } /* v224: the story text is the page's content — teal-600 was 3.7:1 */
  body.dark-mode .reading-vn{ color:var(--cover); }
  .reading-en{ font-size:13px; color:var(--stamp); opacity:0.75; margin-top:2px; }
  .reading-line > div{ flex:1; }
  .reading-speak{ flex-shrink:0; }
  .chip-row{
    display:flex;
    align-items:center;
    gap:5px;
  }
  .chip-row .word-chip{ margin:0; }
  .chip-speak{
    border:none;
    background:transparent;
    font-size:14px;
    cursor:pointer;
    padding:0;
    min-width:32px; min-height:32px; /* v224: was 24px next to a 45px word chip */
    display:inline-flex; align-items:center; justify-content:center; border-radius:10px;
    color:var(--stamp);
  }
  .tts-note{
    font-family:var(--font);
    font-size:10.5px;
    font-weight:500;
    color:var(--muted-soft);
    margin-top:4px;
  }

  /* mode toggle */
  .mode-toggle{
    display:flex;
    gap:7px;
    margin-bottom:14px;
  }
  .mode-toggle button{
    flex:1;
    font-family:var(--font);
    font-size:12px;
    font-weight:700;
    padding:9px 4px;
    min-height:40px;
    border-radius:999px;
    border:none;
    background:var(--paper-dark);
    color:var(--muted);
    cursor:pointer;
  }
  .mode-toggle button.active{
    background:var(--cover);
    color:var(--on-cover);
  }

  /* typed answer */
  .dict-ac-box{
    /* Must sit above every modal overlay (the deck editor is .teacher-modal-
       overlay at 9750, other sheets go up to 9999). At 9600 the suggestions
       were rendering fine but hidden behind the deck editor's backdrop. */
    position:fixed; z-index:10050; margin-top:0;
    background:var(--card); border:1.5px solid var(--paper-dark); border-radius:12px;
    max-height:220px; overflow-y:auto; box-shadow:0 6px 18px rgba(0,0,0,0.18);
  }
  .dict-ac-item{
    padding:8px 12px; cursor:pointer; font-family:var(--font);
    display:flex; flex-direction:column; gap:1px;
  }
  .dict-ac-item strong{ font-size:14px; color:var(--cover); }
  .dict-ac-item span{ font-size:11.5px; color:var(--muted); }
  .dict-ac-item:hover, .dict-ac-item.active{ background:var(--primary-tint); }
  .type-input{
    width:100%;
    font-family:var(--font);
    font-weight:600;
    font-size:17px;
    padding:12px 14px;
    border:2px solid var(--line);
    border-radius:var(--radius-sm);
    background:var(--card);
    -webkit-appearance:none;
    appearance:none;
    color:var(--ink);
    margin-bottom:10px;
    transition:border-color .12s;
  }
  .type-input:focus{ outline:none; border-color:var(--cover); }
  .feedback.close{ background:var(--warn-bg); color:var(--warn); }

  /* difficulty / stats badges */
  .quiz-meta{
    display:flex;
    flex-wrap:wrap;
    gap:10px;
    font-family:var(--font);
    font-size:11.5px;
    font-weight:600;
    color:var(--muted);
    margin-bottom:8px;
  }
  .match-card{
    position:relative;
    min-height:72px;
    border:2px solid var(--line);
    border-radius:var(--radius-sm);
    background:var(--card);
    display:flex;
    align-items:center;
    justify-content:center;
    text-align:center;
    padding:6px 4px;
    font-family:var(--font);
    font-weight:600;
    font-size:12.5px;
    line-height:1.25;
    cursor:pointer;
    color:var(--ink);
    transition:border-color .12s, background .12s;
  }
  .match-card.vn-side{ font-family:var(--font); font-weight:700; font-size:14.5px; color:var(--ink); }
  .match-card.selected{ border-color:var(--gold); box-shadow:0 0 0 2px var(--gold) inset; }
  .match-card.matched{ opacity:0.6; cursor:default; background:var(--ok-bg); border-color:var(--ok); color:var(--ok-ink, var(--ok)); } /* v224: matched pairs stay readable */
  .match-card.shake{ border-color:var(--bad); background:var(--bad-bg); }

  /* Home banner (Start Here landing) and the "Island journey" path are now
     built with real Tailwind classes transcribed straight from Charmcraft's
     own source (src/routes/index.tsx) instead of hand-rolled CSS approximations
     — see the <script>tailwind.config</script> block in <head> for the exact
     color values, and renderShPath()/homeBannerHtml() in the script below for
     the markup itself. */

  /* ---------- START HERE ---------- */
  /* "Island journey" path look: a mint container with a dashed line down the
     middle and alternating left/right stop cards, matching the reference
     screens. Restyles the existing .sh-stop markup renderShPath() already
     produces — no JS changes needed, since the classes were already there. */
  #shStopList{
    position:relative; padding:18px 6px; border-radius:28px;
    background:var(--primary-tint); overflow:hidden;
  }
  #shStopList::before{
    content:''; position:absolute; top:26px; bottom:26px; left:50%;
    width:0; border-left:6px dashed color-mix(in srgb, var(--cover) 45%, var(--line));
    transform:translateX(-50%); z-index:0;
  }
  .sh-stop{
    position:relative; z-index:1; display:flex; align-items:center; gap:10px;
    width:82%; text-align:left; border:1.5px solid var(--line); background:var(--card);
    border-radius:18px; padding:10px 14px; margin-bottom:16px; cursor:pointer;
    font-family:var(--font); color:var(--ink); box-shadow:var(--shadow-sm);
    transition:transform .12s ease;
  }
  .sh-stop:active{ transform:scale(0.98); }
  .sh-stop:nth-child(odd){ margin-right:auto; }
  .sh-stop:nth-child(even){ margin-left:auto; }
  .sh-stop-done{ border-color:var(--cover); }
  .sh-stop-icon{
    font-size:20px; flex-shrink:0; width:44px; height:44px; text-align:center;
    display:flex; align-items:center; justify-content:center; border-radius:50%;
    background:var(--gold); color:var(--on-accent); font-family:var(--font-display); font-weight:800;
  }
  .sh-stop-done .sh-stop-icon{ background:var(--cover); color:var(--on-cover); }
  .sh-stop-text{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
  .sh-stop-title{ font-weight:800; font-size:14px; }
  .sh-stop-desc{ font-size:11.5px; color:var(--muted); line-height:1.35; }
  .sh-stop-arrow{ font-size:20px; color:var(--muted); flex-shrink:0; }
  .sh-stop-done .sh-stop-arrow{ font-size:0; }
  .sh-stop-done .sh-stop-arrow::after{ content:'★'; font-size:17px; color:var(--gold); }
  .sh-tone-row{
    display:flex; align-items:center; gap:10px; padding:9px 0;
    border-bottom:1px solid var(--paper-dark); font-family:var(--font);
  }
  .sh-tone-row:last-of-type{ border-bottom:none; }
  .sh-tone-row .section-note{ flex:1; }
  .sh-tone-mark{ font-size:26px; font-weight:800; width:34px; flex-shrink:0; color:var(--ink); }
  .sh-tone-row b{ font-size:14px; width:52px; flex-shrink:0; color:var(--ink); }
  .sh-region-wrap{ overflow-x:auto; -webkit-overflow-scrolling:touch; margin:4px 0; }
  .sh-topic-table th, .sh-region-table th{ text-align:left; font-size:11px; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); padding:4px 8px; }
  .sh-region-table td{ padding:4px 6px; }
  .sh-region-word{ border:none; background:var(--paper-dark,#f1ead6); color:var(--ink); border-radius:12px; padding:5px 9px; font:700 13px var(--font); cursor:pointer; line-height:1.25; }
  @media (max-width:480px){ .sh-region-table td{ padding:3px 3px; } .sh-region-table td.sh-ct-en{ font-size:12px; } .sh-region-word{ padding:4px 7px; font-size:12.5px; } }
  .sh-region-word:hover{ background:var(--cover,#1d9178); color:#fff; }
  .sh-mini-speak{
    flex-shrink:0; width:32px; height:32px; padding:0; border-radius:50%;
    font-size:14px; display:flex; align-items:center; justify-content:center;
  }
  .sh-video-link{
    display:block; text-decoration:none; text-align:center;
    margin:0 0 14px; font-size:12px; line-height:1.4;
  }
  .sh-vowel-table, .sh-cons-table{
    width:100%; border-collapse:collapse; font-family:var(--font); font-size:13px; margin-top:8px;
  }
  .sh-vowel-table td, .sh-cons-table td{
    border:1px solid var(--paper-dark); padding:7px 8px; text-align:center; color:var(--ink);
  }
  .sh-vowel-cell{
    cursor:pointer; font-weight:700; color:var(--cover) !important;
    background:var(--primary-tint);
  }
  .sh-vowel-cell:active{ opacity:.7; }
  .sh-combo-fam{ margin-bottom:14px; }
  .sh-combo-fam-label{
    font-family:var(--font); font-weight:800; font-size:12px; color:var(--muted);
    text-transform:uppercase; letter-spacing:.04em; margin-bottom:6px;
  }
  .sh-combo-grid{ display:flex; flex-wrap:wrap; gap:6px; }
  .sh-combo-cell{
    border:none; border-radius:8px; padding:7px 10px; font-family:var(--font);
    font-size:13px;
  }
  .sh-cons-table td:last-child{ border:none; padding:4px; }
  .sh-ct-ex{ text-align:left !important; font-size:12.5px; }
  .sh-vt-label{
    text-align:left !important; font-weight:800; font-size:11px; background:var(--primary-tint);
    color:var(--cover); white-space:nowrap;
  }
  .sh-ct-vn{ font-weight:800; width:34%; background:var(--primary-tint); color:var(--cover); }
  .sh-ct-en{ text-align:left !important; font-size:12.5px; color:var(--muted); }
  .sh-quiz-box{
    margin-top:18px; padding:14px; border-radius:14px;
    background:var(--primary-tint); font-family:var(--font);
  }
  .sh-quiz-head{ font-weight:800; font-size:13px; color:var(--cover); margin-bottom:8px; }
  .sh-quiz-play{ font-size:14px; padding:10px; margin:0; }
  .sh-quiz-slow{ font-size:16px; padding:10px 14px; margin:0; }
  .sh-quiz-opts{ display:grid; grid-template-columns:1fr 1fr; gap:8px; }
  .sh-quiz-opt{
    border:1.5px solid var(--paper-dark); background:var(--card); color:var(--ink);
    border-radius:10px; padding:10px 6px; font-family:var(--font); font-weight:700;
    font-size:12.5px; cursor:pointer;
  }
  .sh-quiz-opt:disabled{ opacity:.7; }
  .sh-quiz-correct{ background:var(--ok-bg) !important; border-color:var(--ok) !important; color:var(--ok) !important; }
  .sh-quiz-wrong{ background:var(--bad-bg) !important; border-color:var(--bad) !important; color:var(--bad) !important; }
  .sh-quiz-fb{ text-align:center; font-weight:700; font-size:12.5px; margin-top:8px; min-height:16px; color:var(--ink); }
  /* Round-complete screen — the AirLearn-style "stats + confetti" moment
     applied to the one place in this app that already has a natural
     fixed-length boundary (a 5-question quick-check), rather than forced
     onto the main Quiz/Cloze/Build tabs, which are deliberately endless
     practice loops with no "finished" point to celebrate. */
  .rd-wrap{ text-align:center; padding:4px 0 6px; }
  .rd-mascot{ position:relative; display:inline-block; margin-bottom:2px; }
  .rd-wrap-pass .rd-mascot svg{ animation:mascotBob 1.1s ease-in-out 2; }
  .rd-confetti{
    position:absolute; font-size:18px; opacity:0;
    animation:rdConfettiPop .9s ease-out forwards;
  }
  .rd-c1{ top:-6px; left:-10px; animation-delay:.05s; }
  .rd-c2{ top:-14px; right:-6px; animation-delay:.15s; }
  .rd-c3{ bottom:2px; right:-12px; animation-delay:.25s; }
  @keyframes rdConfettiPop{
    0%{ opacity:0; transform:translateY(4px) scale(0.6) rotate(0deg); }
    40%{ opacity:1; }
    100%{ opacity:0; transform:translateY(-22px) scale(1.1) rotate(20deg); }
  }
  .rd-headline{
    font-family:var(--font-display);
    font-size:22px;
    font-weight:700;
    color:var(--ink);
    margin:4px 0 2px;
  }
  .rd-stats{ display:flex; gap:8px; margin:14px 0 4px; }
  .rd-stat{ flex:1; border-radius:var(--radius-sm); padding:10px 4px; }
  .rd-stat-num{ font-family:var(--font-display); font-size:19px; font-weight:700; }
  .rd-stat-lbl{ font-size:9.5px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; margin-top:1px; }
  .rd-stat-gold{ background:var(--gold-tint); }
  .rd-stat-gold .rd-stat-num{ color:var(--warn); }
  .rd-stat-ok{ background:var(--ok-bg); }
  .rd-stat-ok .rd-stat-num{ color:var(--ok); }
  .rd-stat-cover{ background:var(--primary-tint); }
  .rd-stat-cover .rd-stat-num{ color:var(--cover); }
  .badge-grid{
    display:flex;
    flex-wrap:wrap;
    gap:8px;
    margin-top:8px;
  }
  .badge-chip{
    font-family:var(--font);
    font-size:11px;
    font-weight:600;
    padding:6px 11px;
    border-radius:999px;
    background:var(--paper-dark);
    border:none;
    color:var(--muted-soft);
  }
  .badge-chip.earned{
    background:var(--gold);
    border-color:var(--gold);
    color:var(--on-accent);
  }
  .xp-bar-wrap{
    background:var(--paper-dark);
    border:none;
    border-radius:999px;
    height:14px;
    overflow:hidden;
    margin:6px 0 4px;
  }
  .xp-bar-fill{
    background:linear-gradient(90deg, var(--gold), var(--stamp));
    height:100%;
    border-radius:999px;
  }
  .streak-flame{
    font-size:22px;
  }

  .diff-badge{
    font-family:var(--font);
    font-size:10.5px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.5px;
    padding:4px 10px;
    border-radius:999px;
    background:var(--gold);
    color:var(--on-accent);
  }

  /* Context sentence on flashcard */
  .context-box {
    margin-top: 12px;
    padding: 12px 14px;
    background: var(--paper-dark);
    border-left: none;
    border-radius: var(--radius-sm);
    font-size: 14px;
    font-weight:600;
    color: var(--ink);
    display: none;
  }
  .context-box .ctx-en {
    font-family: var(--font);
    font-size: 11.5px;
    font-weight:500;
    color: var(--muted);
    margin-top: 4px;
  }

  /* Survival phrases */
  .survival-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .survival-card {
    background: var(--card);
    border: 2px solid var(--line);
    border-radius: var(--radius);
    padding: 14px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
  }
  .survival-card .vn {
    font-size: 17px;
    font-weight:700;
    color: var(--ink);
  }
  .survival-card .en {
    font-family: var(--font);
    font-size: 12px;
    font-weight:500;
    color: var(--muted);
    margin-top: 2px;
  }
  .survival-card .cat-tag {
    font-family: var(--font);
    font-size: 10.5px;
    font-weight:700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--stamp-ink, var(--stamp));
    background: var(--stamp-tint);
    padding: 3px 8px;
    border-radius: 999px;
    border: none;
    white-space: nowrap;
  }

  /* Teacher directory */
  #authPasswordToggle{
    position:absolute; right:6px; top:50%; transform:translateY(-50%);
    width:32px; height:32px; border:none; background:none; cursor:pointer;
    font-size:16px; opacity:.6; display:flex; align-items:center; justify-content:center;
  }
  #authPasswordToggle:active{ opacity:1; }
  .teacher-search{
    width:100%;
    font-family:var(--font);
    font-size:14px;
    font-weight:500;
    padding:11px 14px;
    border-radius:999px;
    border:2px solid var(--line);
    background:var(--card);
    color:var(--ink);
    margin-bottom:12px;
    outline:none;
  }
  .teacher-search:focus{ border-color:var(--cover); }
  .teacher-grid{
    display:grid;
    grid-template-columns:1fr;
    gap:12px;
  }
  .teacher-card{
    background:var(--card);
    border:2px solid var(--line);
    border-radius:var(--radius);
    padding:14px;
    display:flex;
    gap:12px;
    cursor:pointer;
    box-shadow:var(--shadow-sm);
  }
  .teacher-card:active{ transform:scale(0.98); }
  .teacher-avatar{
    width:56px; height:56px; border-radius:50%;
    flex:none; object-fit:cover;
    background:var(--paper-dark);
    display:flex; align-items:center; justify-content:center;
    font-size:20px; font-weight:800; color:var(--cover);
  }
  .teacher-info{ flex:1; min-width:0; }
  .teacher-name{ font-size:15.5px; font-weight:800; color:var(--ink); }
  .teacher-region{ font-family:var(--font); font-size:11px; font-weight:700; color:var(--stamp); text-transform:uppercase; letter-spacing:0.3px; }
  .teacher-tags{ display:flex; flex-wrap:wrap; gap:5px; margin:6px 0; }
  .teacher-tag{
    font-family:var(--font); font-size:10px; font-weight:700;
    background:var(--paper-dark); color:var(--muted);
    padding:3px 8px; border-radius:999px;
  }
  .teacher-meta{ display:flex; align-items:center; gap:8px; font-family:var(--font); font-size:12px; color:var(--muted); font-weight:600; }
  .teacher-rating{ color:var(--gold); font-weight:800; }
  .teacher-price{ color:var(--ink); font-weight:800; margin-left:auto; }
  .teacher-empty{
    font-family:var(--font); font-size:13px; color:var(--muted);
    text-align:center; padding:30px 10px;
  }
  .teacher-apply-note{
    margin-top:16px; text-align:center; font-family:var(--font);
    font-size:12px; color:var(--muted);
  }
  .teacher-apply-note a{ color:var(--cover); font-weight:700; text-decoration:none; }

  /* Connection-state banner for 1:1 calls — without this, a call that never
     negotiates just shows a black rectangle forever with no explanation. */
  .call-conn-status{
    position:absolute; left:50%; top:52px; transform:translateX(-50%);
    z-index:6; max-width:88%; text-align:center;
    background:rgba(12,12,22,0.82); color:#fff; font-family:var(--font);
    font-size:12.5px; font-weight:600; line-height:1.4;
    padding:8px 14px; border-radius:999px; backdrop-filter:blur(6px);
  }
  .call-conn-status.failed{ background:rgba(185,28,28,0.92); }
  .call-conn-status button{
    margin-left:8px; border:none; background:#fff; color:#111;
    font-family:var(--font); font-size:11.5px; font-weight:700;
    padding:5px 12px; border-radius:999px; cursor:pointer;
  }

  /* Teacher detail modal */
  .teacher-modal-overlay{
    display:none; position:fixed; inset:0; background:rgba(12,12,22,0.6);
    /* Above the fullscreen video shell (8800), chat panel (9200) and study
       panel (9300) — at the old z-index:55 these modals silently opened
       *behind* the black video during a call and looked completely broken. */
    z-index:9750; align-items:center; justify-content:center; padding:20px;
  }
  .teacher-modal{
    background:var(--paper); border-radius:var(--radius-lg);
    max-width:380px; width:100%; max-height:85vh; overflow-y:auto;
    padding:22px 20px; position:relative; font-family:var(--font);
  }
  .teacher-modal-close{
    position:absolute; top:8px; right:8px; background:var(--paper-dark); border:none;
    width:40px; height:40px; border-radius:999px; line-height:1;
    font-size:16px; color:var(--ink); cursor:pointer; z-index:2;
    display:flex; align-items:center; justify-content:center;
  }
  /* Reserve room for the close button so titles never run underneath it.
     Centered titles get the same reserve on both sides so they stay truly
     centered instead of being nudged left by the right-only padding. */
  .teacher-modal-name{ padding-right:44px; min-height:26px; }
  .teacher-modal-name.centered{ padding-left:44px; text-align:center; }
  .teacher-modal video, .teacher-modal iframe{
    width:100%; border-radius:var(--radius); margin-bottom:12px; background:#000;
  }
  .teacher-modal-name{ font-size:19px; font-weight:800; color:var(--ink); }
  .teacher-modal-bio{ font-size:13px; color:var(--muted); line-height:1.5; margin:10px 0; }
  .teacher-contact-btn{
    display:block; width:100%; text-align:center; text-decoration:none;
    background:var(--cover); color:var(--on-cover); font-weight:700; font-size:14px;
    padding:12px; border-radius:999px; margin-top:14px; box-sizing:border-box;
  }
  .teacher-disclaimer{
    font-size:11px; color:var(--muted-soft); text-align:center; margin-top:10px; line-height:1.4;
  }
  .deck-label{
    display:block; font-family:var(--font); font-size:11px; font-weight:700;
    color:var(--muted); text-transform:uppercase; letter-spacing:0.3px; margin-bottom:4px;
  }
  textarea.teacher-search{ font-family:var(--font); }
  .star-btn{
    background:none; border:none; font-size:22px; color:var(--line); cursor:pointer; padding:0 2px;
  }
  .star-btn.active{ color:var(--gold); }
  .review-item{
    padding:8px 0; border-bottom:1px solid var(--line);
    font-family:var(--font); font-size:12.5px;
  }
  .review-item .rev-stars{ color:var(--gold); font-size:12px; }
  .review-item .rev-comment{ color:var(--muted); margin-top:2px; }
  .deck-item-row{
    display:flex; gap:6px; margin-bottom:6px; align-items:center;
  }
  .deck-item-row input{
    font-family:var(--font); font-size:12.5px; padding:8px 10px;
    border-radius:10px; border:2px solid var(--line); background:var(--card); color:var(--ink); outline:none; flex:1; min-width:0;
  }
  .deck-item-row button{
    flex:none; background:var(--bad-bg); color:var(--bad); border:none; border-radius:8px;
    width:28px; height:28px; cursor:pointer; font-size:14px;
  }

  /* TTS speed toggle */
  .speed-toggle {
    display: flex;
    gap: 7px;
    margin-bottom: 10px;
  }
  .speed-toggle button {
    flex: 1;
    font-family: var(--font);
    font-size: 12px;
    font-weight:700;
    padding: 8px 4px;
    border-radius: 999px;
    border: none;
    background: var(--paper-dark);
    color: var(--muted);
    cursor: pointer;
  }
  .speed-toggle button.active {
    background: var(--cover);
    color:var(--on-cover);
  }

  /* Session goal */
  .goal-ring-wrap {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
    padding: 10px 12px;
    background: var(--paper-dark);
    border: none;
    border-radius: var(--radius);
  }
  .goal-ring {
    width: 38px; height: 38px;
    border-radius: 50%;
    background: conic-gradient(var(--gold) var(--pct), var(--line) 0);
    display: flex; align-items: center; justify-content: center;
    font-family: var(--font);
    font-size: 10px; font-weight: 800; color: var(--ink);
  }
  .goal-ring-inner {
    width: 29px; height: 29px;
    border-radius: 50%;
    background: var(--card);
    display: flex; align-items: center; justify-content: center;
  }
  .goal-text {
    font-family: var(--font);
    font-size: 12px;
    font-weight:600;
    color: var(--ink);
  }
  .goal-text span { color: var(--muted); font-size: 10.5px; font-weight:500; }

  /* ---------- FULLSCREEN FOCUS MODE ----------
     Hides everything around the flashcard (title, tabs, tier/category chips,
     search, word-count badge, the add-word tools) so the card fills the
     screen for a distraction-free study session. Only the card itself, the
     prev/next row, the SRS grading buttons, and the context toggle stay put.
     Also tries the real Fullscreen API (hides the browser chrome/address bar
     on Android Chrome); iOS Safari doesn't support that API, but the CSS-only
     version below still works there regardless. */
  body.focus-mode .cover-title,
  body.focus-mode nav.tabs,
  body.focus-mode #teacherAdBanner,
  body.focus-mode .stamp,
  body.focus-mode #learnTitle,
  body.focus-mode #learnDesc,
  body.focus-mode #sessionGoalWrap,
  body.focus-mode #reviewBanner,
  body.focus-mode #listFilterBanner,
  body.focus-mode #tierSelect,
  body.focus-mode #tierNote,
  body.focus-mode #wordSearch,
  body.focus-mode #wordSearchResults,
  body.focus-mode #myListsRow,
  body.focus-mode #learnCats,
  body.focus-mode .tone-legend,
  body.focus-mode #learnToolsRow,
  body.focus-mode #addWordForm,
  body.focus-mode #customWordsSearch,
  body.focus-mode #customWordsList,
  body.focus-mode footer{
    display:none !important;
  }
  body.focus-mode .book{ padding-top:4px; }
  body.focus-mode .page{ padding-top:4px; }
  body.focus-mode .content{ padding-top:4px; }
  body.focus-mode .card-wrap{ margin-top:14px; }
  body.focus-mode .card{ min-height:52vh; padding:32px 46px 32px 22px; }
  body.focus-mode .card .vn{ font-size:min(15vw, 44px); }
  body.focus-mode .card .en{ font-size:18px; }
  body.focus-mode #focusModeBtn{
    position:fixed;
    top:10px; right:10px;
    z-index:50;
    background:var(--card);
    box-shadow:var(--shadow);
  }

  /* Focus mode, one screen on a phone: a slim topic / sub-topic switcher pinned
     at the top (left of the ✕), a shorter card, icon-only tool row, and only
     the answer + grading buttons below. Nothing should need scrolling. */
  body.focus-mode #learnFilterBar{
    position:fixed; top:8px; left:10px; right:64px; z-index:50; margin:0; flex-wrap:nowrap; gap:6px; align-items:center;
  }
  body.focus-mode #learnFilterBar .lf-f{ flex:1 1 0; min-width:0; }
  body.focus-mode #learnFilterBar .lf-f > span{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); }
  body.focus-mode #learnFilterBar select{ min-height:40px; padding:6px 26px 6px 10px; font-size:13px; border-radius:12px; }
  body.focus-mode #lfToneWrap, body.focus-mode #lfReset, body.focus-mode #lfDelCat{ display:none !important; }
  body.focus-mode .content{ padding-top:52px; }
  body.focus-mode .card{ min-height:min(38vh, 340px); padding:16px 40px 16px 18px; }
  @supports (height:1dvh){ body.focus-mode .card{ min-height:min(38dvh, 340px); } }
  body.focus-mode .card-wrap{ margin-top:6px; }
  body.focus-mode .font-size-ctrl, body.focus-mode #contextToggle, body.focus-mode #iconLegendShow,
  body.focus-mode #pronFeedback:empty, body.focus-mode #recordFeedback:empty, body.focus-mode #srsFeedback:empty{ display:none; }
  body.focus-mode .card-tools{ flex-wrap:nowrap; gap:6px; margin-top:8px; }
  body.focus-mode .card-tools .speak-btn{ min-width:0; flex:1 1 0; max-width:64px; height:44px; padding:0; flex-direction:row; justify-content:center; }
  body.focus-mode .card-tools .speak-btn::after{ display:none; }
  body.focus-mode .fc-nav{ margin-top:8px !important; }
  body.focus-mode .fc-nav .count small{ display:none; }
  body.focus-mode #learnSettingsDetails, body.focus-mode #learnBrowseDetails, body.focus-mode #bottomNav, body.focus-mode #vcSuggestModeBtn{ display:none !important; }
  /* Answer / grading buttons sit right under the card (not at the screen edge),
     and the card is tall enough to use the screen, so nothing is left floating. */
  body.focus-mode #showAnswerBtn, body.focus-mode #srsRow{ margin:14px 0 0 !important; }
  body.focus-mode #srsRow .srs-btn{ display:flex; flex-direction:row; align-items:center; justify-content:center; gap:4px; height:48px; min-height:48px; padding:0 4px; font-size:14px; white-space:nowrap; }
  body.focus-mode #contextBox{ margin-bottom:0; }
  body.focus-mode #vcHwLearn{ display:none !important; }
  body.focus-mode .content{ padding-bottom:16px; }

  /* ---------- SESSION MODE (Start Today guided flow) ---------- */
  body.session-mode{ padding-top:56px; padding-bottom:118px; }
  body.session-mode nav.tabs,
  body.session-mode .cover-title{ display:none !important; }
  body.session-mode #teacherAdBanner{ display:none !important; }
  #sessionTopBar{
    display:none; position:fixed; top:0; left:0; right:0; z-index:9999;
    background:linear-gradient(135deg, var(--cover), var(--cover-light));
    color:#fff; padding:12px 16px; text-align:center;
    font-family:var(--font); font-weight:800; font-size:14px;
    box-shadow:var(--shadow-sm);
  }
  #sessionBar{
    display:none; position:fixed; left:0; right:0; bottom:0; z-index:9999;
    background:var(--card); box-shadow:0 -8px 24px rgba(20,21,43,0.14);
    padding:10px 16px calc(10px + env(safe-area-inset-bottom));
  }
  #sessionBarTop{ display:flex; align-items:center; justify-content:space-between; margin-bottom:8px; }
  #sessionStepLabel{ font-family:var(--font); font-size:11.5px; font-weight:700; color:var(--muted); }
  #sessionExitBtn{ border:none; background:none; color:var(--muted); font-family:var(--font); font-size:12px; font-weight:600; cursor:pointer; padding:2px 4px; }
  #sessionTrack{ height:5px; background:var(--paper-dark); border-radius:99px; margin-bottom:10px; overflow:hidden; }
  #sessionProgressBar{ height:100%; background:var(--cover); border-radius:99px; transition:width .25s ease; }
  #sessionNextBtn{
    width:100%; border:none; border-radius:999px; padding:13px; font-family:var(--font);
    font-weight:800; font-size:14px; color:var(--on-cover); background:var(--cover); cursor:pointer;
  }
  #sessionNextBtn:disabled{ background:var(--muted-soft); cursor:not-allowed; }

  /* ---------- Practice Rooms: redesigned browse UI ---------- */
  :root{ --group:#6d5bd0; --group-light:#9285e8; }
  .pr-pill:active{ transform:scale(0.97); }

  /* ---------- Session goal nudge in a stranger call ---------- */
  #practiceGoalPill{
    position:absolute; left:50%; transform:translateX(-50%);
    top:calc(56px + env(safe-area-inset-top)); z-index:7;
    display:none; align-items:center; gap:7px;
    background:rgba(0,0,0,0.55); backdrop-filter:blur(6px); color:#fff;
    border-radius:999px; padding:7px 14px; font-family:var(--font);
    font-weight:800; font-size:12px; white-space:nowrap;
  }
  #practiceGoalPill.show{ display:flex; }
  #practiceGoalPill.done{ background:rgba(22,163,74,0.85); }
  #practiceGoalPill .gp-ring{
    width:16px; height:16px; border-radius:50%; flex-shrink:0;
    background:conic-gradient(#4ade80 var(--pct,0%), rgba(255,255,255,0.25) 0);
  }
  /* Group room layout control */
  .live-layout-btn{
    border:none; background:rgba(255,255,255,0.16); color:#fff; border-radius:999px;
    height:34px; padding:0 12px; font-family:var(--font); font-weight:800;
    font-size:11.5px; cursor:pointer; backdrop-filter:blur(6px); flex-shrink:0;
  }
  .live-tiles.stacked{ grid-template-columns:1fr !important; }
  .live-tiles.sidebyside{ grid-template-columns:1fr 1fr !important; }
  .live-tiles.focus-one{ grid-template-columns:1fr !important; }
  .live-tiles.focus-one .live-tile:not(.focused){ display:none; }


  /* Video sizing lives here, not in inline style attributes — inline styles
     beat the stylesheet, which is why split mode could never resize them and
     the self-view ended up drawn over the bottom half of the partner. */
  #practiceRemoteVideo{
    width:100%; height:100%; object-fit:cover; background:#111; display:block;
  }
  #practiceLocalVideo{
    position:absolute; bottom:10px; right:10px; width:96px; height:72px;
    object-fit:cover; border-radius:10px; border:2px solid rgba(255,255,255,0.85);
    background:#222; display:block;
  }


  /* ---------- Shared deck library ---------- */
  .lib-tabs{ display:flex; gap:6px; margin:12px 0 10px; }
  .lib-tab{
    flex:1; border:1.5px solid var(--paper-dark); background:var(--paper); color:var(--ink);
    border-radius:12px; padding:9px 6px; font-family:var(--font); font-weight:800;
    font-size:12.5px; cursor:pointer;
  }
  .lib-tab.active{ background:var(--cover); border-color:transparent; color:var(--on-cover); }
  .lib-filters{ display:flex; gap:6px; overflow-x:auto; padding-bottom:8px; scrollbar-width:none; }
  .lib-filters::-webkit-scrollbar{ display:none; }
  .lib-chip{
    flex:0 0 auto; border:1.5px solid var(--paper-dark); background:var(--paper); color:var(--ink);
    border-radius:999px; padding:7px 13px; font-family:var(--font); font-weight:700;
    font-size:12px; cursor:pointer; white-space:nowrap;
  }
  .lib-chip.active{ background:var(--cover); border-color:transparent; color:var(--on-cover); }
  .deck-card{
    background:var(--paper); border:1px solid var(--paper-dark); border-radius:var(--radius-sm);
    padding:14px; margin-bottom:10px;
  }
  .deck-card .dc-top{ display:flex; align-items:flex-start; gap:10px; }
  .deck-card .dc-title{ font-weight:800; font-size:15px; color:var(--ink); line-height:1.3; }
  .deck-card .dc-meta{ font-size:11.5px; color:var(--muted); margin-top:3px; display:flex; flex-wrap:wrap; gap:3px 10px; }
  .deck-card .dc-desc{ font-size:12.5px; color:var(--muted); margin-top:7px; line-height:1.45; }
  .deck-card .dc-preview{
    background:var(--card); border-radius:10px; padding:9px 11px; margin-top:9px;
    font-size:12.5px; color:var(--ink); line-height:1.5;
  }
  .deck-card .dc-actions{ display:flex; gap:7px; margin-top:11px; flex-wrap:wrap; align-items:center; }
  .deck-card .dc-btn{
    border:none; border-radius:999px; padding:8px 15px; font-family:var(--font);
    font-weight:800; font-size:12.5px; cursor:pointer; background:var(--cover); color:var(--on-cover);
  }
  .deck-card .dc-btn.ghost{ background:var(--paper-dark); color:var(--ink); }
  .deck-card .dc-vote{
    border:1.5px solid var(--paper-dark); background:var(--card); color:var(--muted);
    border-radius:999px; padding:6px 11px; font-family:var(--font); font-weight:700;
    font-size:12px; cursor:pointer;
  }
  .deck-card .dc-vote.on{ background:var(--cover); border-color:transparent; color:var(--on-cover); }
  .lib-level{
    font-size:10px; font-weight:800; text-transform:uppercase; letter-spacing:.04em;
    background:var(--paper-dark); color:var(--muted); border-radius:999px; padding:2px 8px;
  }


  /* ---------- Community sentence corrections ---------- */
  .corr-badge{
    display:inline-flex; align-items:center; gap:3px; font-size:9.5px; font-weight:800;
    background:#dcfce7; color:#166534; border-radius:999px; padding:2px 7px; margin-left:6px;
    vertical-align:middle;
  }
  .corr-badge.pending{ background:#fef3c7; color:#92400e; }
  body.dark-mode .corr-badge{ background:#14532d; color:#bbf7d0; }
  body.dark-mode .corr-badge.pending{ background:#78350f; color:#fde68a; }
  .corr-actions{ display:flex; align-items:center; gap:7px; margin-top:8px; flex-wrap:wrap; }
  .corr-btn{
    border:1.5px solid var(--paper-dark); background:var(--card); color:var(--muted);
    border-radius:999px; padding:5px 11px; font-family:var(--font); font-weight:700;
    font-size:11.5px; cursor:pointer;
  }
  .corr-btn.on{ background:var(--cover); border-color:transparent; color:var(--on-cover); }
  .corr-btn.suggest{ color:var(--cover); border-color:var(--cover); }
  .corr-btn.flag{ color:var(--stamp); border-color:var(--stamp); }
  .corr-btn.flag.on{ background:var(--stamp); border-color:transparent; color:#fff; opacity:.85; }
  .corr-credit{ font-size:10.5px; color:var(--muted-soft); }
  #corrModal .cm-word{
    font-size:20px; font-weight:800; color:var(--ink); text-align:center; margin-bottom:2px;
  }
  #corrModal .cm-gloss{ font-size:13px; color:var(--muted); text-align:center; margin-bottom:12px; }
  #corrModal .cm-current{
    background:var(--paper-dark); border-radius:12px; padding:10px 12px; margin-bottom:12px;
    font-size:12.5px; color:var(--muted); line-height:1.45;
  }


  /* Empty feedback strips used to reserve height, leaving a dead band between
     the card nav and the tone legend. They now collapse when they have nothing
     to say and only take space once a message appears. */
  #pronFeedback:empty, #recordFeedback:empty{ display:none; }
  .tone-legend{ margin-top:2px !important; }



  /* Collapse marketing copy for signed-in users — it's onboarding material,
     not something worth re-reading on every screen. */
  body.signed-in .cover-title{ padding-top:12px; padding-bottom:12px; }
  body.signed-in .cover-title h1{ font-size:22px; }

  /* Dismissible teachers banner */
  #teacherAdWrap{ position:relative; }
  #teacherAdDismiss{
    position:absolute; top:8px; right:8px; z-index:2;
    border:none; background:rgba(255,255,255,0.25); color:#fff;
    width:26px; height:26px; border-radius:999px; font-size:13px; cursor:pointer;
  }
  .empty-cta{
    margin-top:14px; border:none; border-radius:999px; padding:12px 22px;
    background:var(--cover); color:var(--on-cover); font-family:var(--font);
    font-weight:800; font-size:13.5px; cursor:pointer;
  }
  .online-stack{ display:inline-flex; align-items:center; gap:5px; }
  .online-stack .os-avatars{ display:flex; }
  .online-stack .os-avatars .teacher-avatar{
    width:20px !important; height:20px !important; font-size:9px !important;
    margin-left:-6px; border:2px solid var(--card);
  }
  .online-stack .os-avatars .teacher-avatar:first-child{ margin-left:0; }


  /* ---------- Signed-out value pitch ---------- */
  .signin-pitch{
    text-align:center; padding:26px 20px; background:var(--paper);
    border:1px solid var(--paper-dark); border-radius:var(--radius); margin-top:14px;
  }
  .signin-pitch .sp-icon{ font-size:34px; }
  .signin-pitch .sp-title{ font-weight:800; font-size:17px; margin-top:8px; color:var(--ink); }
  .signin-pitch .sp-sub{ font-size:13.5px; color:var(--muted); margin-top:6px; line-height:1.5; }
  .signin-pitch ul{ text-align:left; margin:14px auto 0; padding-left:20px; max-width:280px; }
  .signin-pitch li{ font-size:13px; color:var(--ink); line-height:1.9; }
  .signin-pitch .sp-btn{
    width:100%; margin-top:16px; border:none; border-radius:999px; padding:13px;
    background:var(--cover); color:var(--on-cover); font-family:var(--font); font-weight:800;
    font-size:14.5px; cursor:pointer;
  }
  .signin-pitch .sp-note{ font-size:11.5px; color:var(--muted-soft); margin-top:10px; }




  /* ===================== Slides ===================== */
  /* Every slide renders inside a 16:9 box that is its own size container, so
     one set of cqw-based sizes works for a tiny thumbnail, the editor
     preview, a phone in a call and a projector. */
  .sl-box{ position:relative; aspect-ratio:16/9; width:100%; container-type:size; overflow:hidden; background:#fff; border-radius:10px; }
  .sl{ position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2cqh; padding:5cqh 5cqw; box-sizing:border-box; color:#062822; font-family:'Plus Jakarta Sans',system-ui,sans-serif; text-align:center; background:linear-gradient(160deg,#fffdf7 0%,#fff6e3 100%); }
  .sl *{ margin:0; }
  .sl-ph{ color:#b8ad93; font-weight:600; }
  .sl-muted{ color:#516d66 !important; }
  .sl-t1{ font-family:'Syne','Plus Jakarta Sans',sans-serif; font-size:7.5cqw; line-height:1.05; font-weight:800; color:#006b57; }
  .sl-titlewrap{ position:relative; z-index:1; display:flex; flex-direction:column; gap:2.5cqh; align-items:center; background:rgba(255,253,247,.86); padding:3cqh 4cqw; border-radius:2cqw; }
  .sl-sub{ font-size:3.2cqw; color:#516d66; font-weight:600; white-space:pre-line; }
  .sl-bgimg{ position:absolute; inset:0; z-index:0; }
  .sl-bgimg .sl-img{ width:100%; height:100%; object-fit:cover; opacity:.9; }
  .sl-h{ font-size:4.6cqw; font-weight:800; line-height:1.1; color:#062822; }
  .sl-imgwrap{ flex:1; min-height:0; width:100%; display:flex; align-items:center; justify-content:center; }
  .sl-imgwrap.sl-small{ flex:0 1 38cqh; }
  .sl-img{ max-width:100%; max-height:100%; object-fit:contain; border-radius:1.2cqw; user-select:none; -webkit-user-drag:none; }
  .sl-imgph{ flex:1; width:100%; display:flex; align-items:center; justify-content:center; border:0.3cqw dashed #e3dac1; border-radius:1.5cqw; color:#b8ad93; font-size:3cqw; font-weight:700; }
  .sl-cap{ font-size:3cqw; color:#334; font-weight:600; white-space:pre-line; }
  .sl-vocab{ display:flex; align-items:center; justify-content:center; gap:4cqw; width:100%; height:100%; }
  .sl-vocab.with-img .sl-imgwrap{ flex:0 0 42%; height:80%; }
  .sl-vocab-txt{ display:flex; flex-direction:column; gap:2cqh; align-items:center; }
  .sl-vocab.with-img .sl-vocab-txt{ align-items:flex-start; text-align:left; flex:1; }
  .sl-vn{ font-size:9cqw; font-weight:800; color:#e85d4a; line-height:1.05; cursor:pointer; }
  .sl-spk{ font-size:3.2cqw; vertical-align:middle; opacity:.55; }
  .sl-en{ font-size:4.2cqw; color:#516d66; font-weight:700; }
  .sl-ex{ font-size:3cqw; color:#334; font-style:italic; white-space:pre-line; }
  .sl-sentence{ font-size:5.6cqw; font-weight:800; line-height:1.35; color:#062822; }
  .sl-blank{ display:inline-block; min-width:12cqw; border-bottom:0.6cqw solid #1d9178; margin:0 0.6cqw; color:#1d9178; }
  .sl-blank.on{ background:#bef1e6; border-radius:1cqw 1cqw 0 0; padding:0 1cqw; }
  .sl-cols{ display:flex; gap:4cqw; width:100%; flex:1; min-height:0; align-items:center; }
  .sl-cols.with-img .sl-imgwrap{ flex:0 0 40%; height:100%; }
  .sl-ul{ flex:1; text-align:left; list-style:none; padding:0; display:flex; flex-direction:column; gap:1.6cqh; }
  .sl-ul li{ font-size:3.6cqw; font-weight:700; padding-left:4cqw; position:relative; line-height:1.25; }
  .sl-ul li::before{ content:''; position:absolute; left:.6cqw; top:1.3cqw; width:1.5cqw; height:1.5cqw; border-radius:50%; background:#f2c451; }
  .sl-ul li[data-say]{ cursor:pointer; }
  .sl-ul.dense li{ font-size:2.8cqw; }
  .sl-ul.xdense li{ font-size:2.2cqw; }
  .sl-ul.dense, .sl-ul.xdense{ gap:1cqh; }
  .sl-full{ position:absolute; inset:0; background:#111; display:flex; align-items:center; justify-content:center; }
  .sl-full .sl-img{ width:100%; height:100%; object-fit:contain; border-radius:0; }
  .sl.sl--full{ padding:0; }
  .sl-credit{ position:absolute; right:1.2cqw; bottom:0.8cqh; font-size:1.5cqw; color:#666; background:rgba(255,255,255,.75); padding:.2cqh .8cqw; border-radius:.8cqw; }
  .sl-empty{ background:#fff; }

  /* Studio */
  .sl-studio-ov{ z-index:9842; }
  .vc-modal.sl-studio{ max-width:1000px; width:100%; max-height:94vh; }
  @media (min-width:700px){ .vc-modal.sl-studio{ height:90vh; } }
  .sl-tabs{ display:flex; gap:6px; margin-bottom:10px; }
  .sl-lib-acts{ display:flex; gap:8px; flex-wrap:wrap; }
  .sl-lib-acts > *{ flex:1; min-height:44px; }
  .sl-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(210px,1fr)); gap:12px; }
  .sl-deck{ background:var(--paper); border:1px solid var(--line); border-radius:14px; padding:8px; display:flex; flex-direction:column; gap:6px; }
  .sl-thumb{ cursor:pointer; box-shadow:0 2px 8px rgba(0,0,0,.08); }
  .sl-deck-meta{ display:flex; flex-direction:column; font:13px var(--font); color:var(--ink); }
  .sl-deck-meta span{ color:var(--muted); font-size:12px; }
  .sl-deck-acts{ display:flex; gap:5px; flex-wrap:wrap; }
  .sl-deck-acts .gb-act{ padding:6px 9px; }
  .sl-present-btn{ background:var(--cover) !important; color:var(--on-cover) !important; border-color:transparent !important; }
  .sl-starters{ display:flex; gap:8px; overflow-x:auto; padding-bottom:4px; }
  .sl-starter{ flex:0 0 auto; border:1px solid var(--line); background:var(--card); color:var(--ink); border-radius:14px; padding:10px 14px; font:700 13px var(--font); cursor:pointer; display:flex; flex-direction:column; align-items:flex-start; gap:2px; }
  .sl-starter small{ color:var(--muted); font-weight:600; }
  .sl-ed-head{ gap:8px; }
  .sl-deck-title{ flex:1; min-width:0; border:1px solid transparent; background:transparent; font:800 17px var(--font); color:var(--ink); padding:6px 8px; border-radius:10px; }
  .sl-deck-title:focus{ border-color:var(--line); background:var(--paper); outline:none; }
  .sl-strip{ display:flex; gap:8px; overflow-x:auto; padding:4px 2px 8px; margin-bottom:8px; }
  .sl-strip-item{ flex:0 0 120px; border:2px solid transparent; background:none; padding:0; border-radius:12px; cursor:pointer; position:relative; }
  .sl-strip-item.on{ border-color:var(--cover); }
  .sl-strip-item > span{ position:absolute; left:4px; top:3px; font:800 10px var(--font); background:rgba(0,0,0,.55); color:#fff; border-radius:6px; padding:0 5px; }
  .sl-strip-add{ flex:0 0 70px; border:2px dashed var(--line); background:var(--paper); border-radius:12px; font-size:26px; color:var(--muted); cursor:pointer; }
  .sl-ed-main{ display:grid; grid-template-columns:1fr; gap:12px; }
  @media (min-width:820px){ .sl-ed-main{ grid-template-columns:1.25fr 1fr; align-items:start; } }
  .sl-stage-preview{ box-shadow:0 6px 20px rgba(0,0,0,.12); }
  .sl-ed-form .teacher-search{ width:100%; box-sizing:border-box; margin-bottom:8px; }
  .sl-layouts{ display:flex; gap:6px; flex-wrap:wrap; margin-bottom:10px; }
  .sl-layout{ border:1px solid var(--line); background:var(--card); color:var(--ink); border-radius:12px; padding:7px 10px; font:700 12px var(--font); cursor:pointer; display:flex; gap:5px; align-items:center; }
  .sl-layout.on{ background:var(--cover); color:var(--on-cover); border-color:transparent; }
  .sl-img-acts{ display:flex; gap:6px; flex-wrap:wrap; margin-bottom:4px; }
  .sl-img-acts .skip-btn{ flex:1; min-height:40px; white-space:nowrap; }
  .sl-notes{ margin:8px 0; }
  .sl-notes summary{ cursor:pointer; font:700 12.5px var(--font); color:var(--muted); margin-bottom:6px; }
  .sl-slide-acts{ display:flex; gap:6px; flex-wrap:wrap; margin-top:6px; }
  .sl-slide-acts .gb-act:disabled{ opacity:.4; cursor:default; }
  .sl-import-status{ background:var(--gold-tint); color:var(--ink); border-radius:10px; padding:8px 12px; font:700 13px var(--font); margin-bottom:10px; }
  .sl-ph-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(120px,1fr)); gap:8px; max-height:60vh; overflow:auto; margin-bottom:8px; }
  .sl-ph-item{ border:none; padding:0; background:var(--paper); border-radius:10px; overflow:hidden; aspect-ratio:4/3; cursor:pointer; }
  .sl-ph-item img{ width:100%; height:100%; object-fit:cover; display:block; }

  /* Viewer */
  .sl-viewer{ position:fixed; inset:0; z-index:9860; background:#0d1614; display:none; flex-direction:column; }
  .sl-viewer.show{ display:flex; }
  .sl-viewer-top{ display:flex; justify-content:space-between; align-items:center; padding:10px 14px; color:#fff; font:800 15px var(--font); }
  .sl-viewer-stage{ flex:1; min-height:0; display:flex; align-items:center; justify-content:center; padding:0 12px; }
  .sl-viewer-stage .sl-box{ width:min(100%, calc((100vh - 140px) * 16 / 9)); border-radius:12px; }
  .sl-viewer-nav{ display:flex; gap:10px; justify-content:center; align-items:center; padding:12px; padding-bottom:calc(12px + env(safe-area-inset-bottom)); color:#fff; font:700 14px var(--font); }
  .sl-viewer-nav .skip-btn{ min-width:64px; min-height:46px; }

  /* Presenting inside the whiteboard */
  .wb-stage{ position:absolute; inset:0; }
  .wb-stage > canvas{ position:absolute; inset:0; z-index:1; }
  .wb-slide-layer{ position:absolute; inset:0; z-index:0; container-type:size; overflow:hidden; }
  .wb-slide-layer:empty{ display:none; }
  .wb-body.slide-mode{ background:#20302c !important; }
  .wb-stage.fit{ box-shadow:0 4px 18px rgba(0,0,0,.35); }
  .wb-slide-nav{ position:absolute; left:50%; bottom:8px; transform:translateX(-50%); z-index:6; display:none; align-items:center; gap:6px; background:rgba(13,22,20,.86); color:#fff; border-radius:999px; padding:5px 8px; font:700 13px var(--font); box-shadow:0 4px 16px rgba(0,0,0,.3); max-width:calc(100% - 16px); }
  .wb-slide-nav button{ border:none; background:rgba(255,255,255,.14); color:#fff; border-radius:999px; min-width:38px; height:34px; padding:0 10px; font:800 13px var(--font); cursor:pointer; }
  .wb-slide-nav button:disabled{ opacity:.35; cursor:default; }
  .wb-slide-nav #wbSlideEnd{ background:#e7000b; }
  .wb-slide-nav #wbSlideWho{ opacity:.8; font-size:12px; padding:0 4px; white-space:nowrap; }
  .wb-slide-notes{ position:absolute; left:8px; right:8px; top:8px; z-index:6; background:rgba(255,248,214,.95); color:#3a2e00; border-radius:10px; padding:6px 10px; font:600 12.5px var(--font); max-height:30%; overflow:auto; }
  #whiteboardPanel.presenting{ min-width:min(560px, 96vw); }
  /* ===================== UX polish pass ===================== */
  .hw-rec{ margin-top:8px; }
  .hw-rec-row{ display:flex; gap:8px; align-items:center; }
  .hw-rec-time{ font:700 13px var(--font); color:var(--muted); font-variant-numeric:tabular-nums; min-width:80px; text-align:right; }
  .hw-rec-live{ color:var(--bad); font-weight:800; padding:8px 0; }
  .hw-media{ display:block; width:100%; max-width:420px; margin:6px 0; border-radius:12px; background:#000; }
  audio.hw-media{ background:none; height:40px; }

  /* Header icons were 28px — too small to hit reliably with a thumb. */
  .dark-toggle, .account-toggle{ width:40px !important; height:40px !important; font-size:17px; }

  /* Onboarding: the full-width "Not sure yet" looked like a second green CTA
     competing with "Start learning". Make it a quiet link-style option. */
  .su-opts[data-su="region"] button[data-val=""]{ flex-basis:100%; background:none !important; border:1px dashed var(--line) !important; color:var(--muted) !important; font-weight:700; min-height:38px; }
  .su-opts[data-su="region"] button[data-val=""].on{ border-style:solid !important; border-color:var(--cover) !important; color:var(--cover) !important; }

  .home-hw-card{ margin:18px 0 0; background:var(--card); border:1.5px solid var(--gold); border-radius:22px; padding:16px; box-shadow:0 10px 26px rgba(6,40,34,.08); font-family:var(--font); color:var(--ink); }
  .home-hw-card.overdue{ border-color:var(--bad); }
  .home-hw-top{ display:flex; justify-content:space-between; gap:8px; align-items:center; font-size:12px; font-weight:800; }
  .home-hw-badge{ background:var(--gold-tint); color:var(--ink); border-radius:999px; padding:4px 10px; }
  .home-hw-due{ color:var(--muted); }
  .home-hw-card.overdue .home-hw-due{ color:var(--bad); }
  .home-hw-title{ font-weight:800; font-size:18px; margin-top:10px; }
  .home-hw-from{ font-size:13px; color:var(--muted); margin-top:2px; }
  .home-hw-acts{ display:flex; gap:8px; margin-top:12px; }
  .home-hw-acts button{ min-height:46px; }

  /* Flashcards on a phone: the level / tone / topic chip rows wrapped onto
     ~8 lines and pushed the card itself below the fold. One swipeable row
     each keeps every filter one tap away and the card on screen. */
  @media (max-width:700px){
    #tab-learn .cats, #tab-reading .cats{ flex-wrap:nowrap; overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:none; padding-bottom:2px; margin-bottom:8px; }
    #tab-learn .cats::-webkit-scrollbar, #tab-idioms .cats::-webkit-scrollbar, #tab-survival .cats::-webkit-scrollbar, #tab-reading .cats::-webkit-scrollbar{ display:none; }
    #tab-learn .cats > *, #tab-reading .cats > *{ flex:0 0 auto; white-space:nowrap; }
  }
  /* Tone filters are about Vietnamese tones — meaningless when learning English. */
  body.english-mode #learnTones{ display:none; }
  /* Flashcard filter bar: Topic / Sub-topic / Tone as dropdowns, so nothing
     needs a sideways scroll. Phone = stacked full-width rows (topic first,
     sub-topic under it, tone + clear on the last); wide screens = one row. */
  .lf-bar{ display:flex; flex-wrap:wrap; gap:8px; align-items:flex-end; margin:0 0 10px; }
  .lf-f{ display:flex; flex-direction:column; gap:3px; min-width:0; flex:1 1 180px; }
  .lf-f > span{ font-size:11px; font-weight:800; letter-spacing:.04em; text-transform:uppercase; color:var(--muted); padding-left:4px; }
  .lf-f select{ width:100%; min-height:44px; padding:8px 34px 8px 12px; font:inherit; font-size:15px; font-weight:700; color:var(--ink); background:var(--card, #fff); border:1.5px solid var(--line, #d9d4c7); border-radius:12px; appearance:none; -webkit-appearance:none; text-overflow:ellipsis;
    background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%); background-position:calc(100% - 18px) 50%,calc(100% - 13px) 50%; background-size:5px 5px,5px 5px; background-repeat:no-repeat; }
  .lf-f select.lf-on{ border-color:var(--gold, #c9a227); background-color:var(--gold-tint, #fff6d8); }
  .lf-topic, .lf-sub{ flex:1 1 100%; }
  .lf-tone{ flex:1 1 120px; }
  .lf-reset, .lf-del{ flex:0 0 44px; min-height:44px; border-radius:12px; border:1.5px solid var(--line, #d9d4c7); background:var(--card, #fff); font-size:16px; cursor:pointer; color:var(--ink); }
  @media (max-width:700px){
    .lf-bar{ gap:6px; }
    .lf-f > span{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); }
    .lf-f select{ min-height:42px; }
  }
  @media (min-width:701px){
    .lf-topic{ flex:2 1 240px; } .lf-sub{ flex:2 1 220px; } .lf-tone{ flex:1 1 160px; }
  }
  body.english-mode #lfToneWrap{ display:none !important; }

  body:not(.fc-revealed) #srsRow{ display:none !important; }
  body.fc-revealed #showAnswerBtn{ display:none; }
  #srsRow .srs-btn{ min-height:48px; }

  .hw-due-chips{ display:flex; gap:6px; flex-wrap:wrap; margin-bottom:6px; }
  .hw-due-chips button{ border:1px solid var(--line); background:var(--card); color:var(--ink); border-radius:999px; padding:7px 12px; font:700 12.5px var(--font); cursor:pointer; min-height:36px; }
  .hw-due-chips button.on{ background:var(--cover); color:var(--on-cover); border-color:transparent; }

  /* Homework cards reuse .card (the flashcard style: centred, 46px side
     padding, min-height) — reset that so they read as normal list rows. */
  #hwList .card, #hwOverdueDigest .card{ text-align:left; align-items:stretch; justify-content:flex-start; min-height:0; cursor:default; }
  #hwList .card > div{ width:100%; }
  .hw-teacher-acts{ display:flex; gap:6px; margin-top:10px; }
  .hw-teacher-acts .skip-btn{ flex:1; white-space:nowrap; padding-left:6px; padding-right:6px; font-size:12.5px; min-height:40px; }
  .hw-teacher-acts .hw-unassign-btn{ color:var(--bad); }

  /* Listen / hear-the-tone Play buttons: the round 32px .speak-btn squeezed
     "🔊 Play" into a blob with the word spilling out underneath. */
  #quizListenPlay, #quizListenReplay, .speak-btn.speak-wide{ width:auto; height:auto; min-height:44px; border-radius:999px; gap:6px; white-space:nowrap; }
  /* Quiz modes: one scrollable row of pills that size to their label, instead
     of five squeezed ovals wrapping onto 3–4 lines each. */
  .mode-toggle{ flex-wrap:nowrap; overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:none; padding-bottom:2px; }
  .mode-toggle::-webkit-scrollbar{ display:none; }
  .mode-toggle button{ flex:0 0 auto; white-space:nowrap; padding:10px 14px; min-height:40px; }
  /* Flashcard topic badge sat on top of the word. Keep it in the flow. */
  .card .cat-tag{ position:static; display:inline-block; margin:0 0 6px; align-self:center; }
  /* More menu pin icons were escaping to the top of the screen. */
  .more-item{ position:relative; }
  /* Reading translation: coral at 75% opacity on white was ~2.7:1. */
  .reading-en{ color:var(--muted); opacity:1; font-size:13.5px; }
  /* Start Here in dark mode: the Tailwind-built hero kept light-theme tokens,
     so "Island journey" was dark ink on a dark background. */
  body.dark-mode #homeBanner{ color:var(--ink); }
  body.dark-mode #homeBanner .bg-card{ background-color:var(--card); }
  body.dark-mode #homeBanner .border-border{ border-color:var(--line); }
  body.dark-mode #homeBanner .text-muted-foreground{ color:var(--muted); }
  body.dark-mode #homeBanner .bg-muted{ background-color:var(--paper-dark); }
  body.dark-mode #homeBanner .bg-pond{ background-color:var(--primary-tint); }
  body.dark-mode #homeBanner .text-coral-foreground{ color:var(--ink); }
  body.dark-mode #homeBanner .text-primary{ color:var(--cover); }
  body.dark-mode #homeJourneyCount{ color:var(--ink); }
  /* Toasts sat underneath the bottom nav, so success messages were invisible. */
  #undoToast{ background:#15332c !important; color:#fff !important;
    bottom:calc(96px + env(safe-area-inset-bottom)) !important; z-index:9990 !important; max-width:calc(100vw - 32px); box-shadow:0 10px 30px rgba(0,0,0,.25); }
  body.dark-mode #undoToast{ background:#eaf6f1 !important; color:#062822 !important; }
  body.dark-mode #undoToastBtn{ color:#00806a !important; }
  body.in-type-tutor #undoToast{ bottom:calc(20px + env(safe-area-inset-bottom)) !important; }
  /* ---------- Generic modal (hw editor, gradebook) — same look as the sheets above ---------- */
  .vc-modal-overlay{ position:fixed; inset:0; z-index:9840; display:none; background:rgba(20,21,43,0.5); align-items:flex-end; justify-content:center; }
  .vc-modal-overlay.show{ display:flex; }
  .vc-modal{ width:100%; max-width:460px; max-height:90vh; overflow:auto; background:var(--card); color:var(--ink);
    border-radius:20px 20px 0 0; padding:18px 18px calc(20px + env(safe-area-inset-bottom)); box-sizing:border-box; }
  .vc-modal-wide{ max-width:820px; }
  @media (min-width:700px){ .vc-modal-overlay{ align-items:center; } .vc-modal{ border-radius:20px; } }
  .vc-modal-head{ display:flex; justify-content:space-between; align-items:center; margin-bottom:10px; }
  .vc-modal-head h3{ margin:0; font-family:var(--font); font-weight:800; font-size:17px; }
  .vc-modal-x{ border:none; background:var(--paper-dark); color:var(--ink); border-radius:999px; width:34px; height:34px; cursor:pointer; font-size:15px; }
  .gb-scroll{ overflow-x:auto; -webkit-overflow-scrolling:touch; }
  .gb-table{ width:100%; border-collapse:collapse; font-family:var(--font); font-size:13px; min-width:560px; }
  .gb-table th{ text-align:left; border-bottom:2px solid var(--line); padding:0; white-space:nowrap; }
  .gb-sort{ background:none; border:none; color:var(--muted); font:inherit; font-weight:800; padding:8px 6px; cursor:pointer; }
  .gb-table td{ padding:8px 6px; border-bottom:1px solid var(--line); vertical-align:middle; white-space:nowrap; }
  .gb-row{ cursor:pointer; }
  .gb-table th:first-child, .gb-row td:first-child{ position:sticky; left:0; background:var(--card); z-index:1; }
  .gb-row:hover, .gb-row:focus{ background:var(--paper); outline:none; }
  .gb-behind td:first-child{ box-shadow:inset 3px 0 0 var(--bad); }
  .gb-bad{ color:var(--bad); font-weight:800; }
  .gb-bar{ display:inline-block; width:46px; height:6px; border-radius:6px; background:var(--line); vertical-align:middle; margin-left:4px; overflow:hidden; }
  .gb-bar i{ display:block; height:100%; background:var(--ok, #2a9d6a); }
  .gb-detail td{ white-space:normal; background:var(--paper); }
  .gb-item{ display:flex; justify-content:space-between; align-items:center; gap:10px; padding:8px 0; border-bottom:1px dashed var(--line); }
  .gb-item-main{ min-width:0; flex:1; }
  .gb-item-title{ font-weight:700; white-space:normal; }
  .gb-sub{ font-size:12.5px; color:var(--muted); background:var(--card); border-radius:8px; padding:6px 8px; margin-top:4px; white-space:normal; }
  .gb-item-acts{ display:flex; gap:6px; flex-shrink:0; }
  .gb-act{ border:1px solid var(--line); background:var(--card); color:var(--ink); border-radius:999px; padding:6px 10px; font:700 12.5px var(--font); cursor:pointer; white-space:nowrap; }
  .gb-act:hover{ border-color:var(--cover); }
  .gb-act.danger{ color:var(--bad); }
  .gb-detail-inner{ position:sticky; left:0; max-width:min(780px, calc(100vw - 72px)); }
  @media (max-width:600px){ .gb-item{ flex-direction:column; align-items:stretch; } .gb-item-acts{ justify-content:flex-start; } }
  .gb-item:last-child{ border-bottom:none; }
  #confirmOverlay.alert-only #confirmCancel{ display:none; }
  /* ---------- In-app confirm sheet (replaces browser confirm) ---------- */
  #confirmOverlay{
    position:fixed; inset:0; z-index:9850; display:none;
    background:rgba(20,21,43,0.5); align-items:flex-end; justify-content:center;
  }
  #confirmOverlay.show{ display:flex; }
  #confirmSheet{
    width:100%; max-width:420px; background:var(--card);
    border-radius:20px 20px 0 0; padding:20px 18px calc(20px + env(safe-area-inset-bottom));
  }
  #confirmSheet .cf-title{ font-weight:800; font-size:16.5px; color:var(--ink); }
  #confirmSheet .cf-body{ font-size:13.5px; color:var(--muted); line-height:1.55; margin-top:8px; white-space:pre-line; }
  #confirmSheet .cf-row{ display:flex; gap:9px; margin-top:18px; }
  #confirmSheet button{
    flex:1; border:none; border-radius:999px; padding:13px; font-family:var(--font);
    font-weight:800; font-size:14px; cursor:pointer;
  }
  #confirmCancel{ background:var(--paper-dark); color:var(--ink); }
  #confirmOk{ background:var(--cover); color:var(--on-cover); }
  #confirmOk.danger{ background:var(--bad); }

  /* Prompt + picker sheets — same shell as the confirm sheet above. */
  #promptOverlay, #pickOverlay{
    position:fixed; inset:0; z-index:9860; display:none;
    background:rgba(20,21,43,0.5); align-items:flex-end; justify-content:center;
  }
  #promptOverlay.show, #pickOverlay.show{ display:flex; }
  #promptSheet, #pickSheet{
    width:100%; max-width:420px; background:var(--card);
    border-radius:20px 20px 0 0; padding:20px 18px calc(20px + env(safe-area-inset-bottom));
  }
  #promptSheet .cf-title, #pickSheet .cf-title{ font-weight:800; font-size:16.5px; color:var(--ink); }
  #promptSheet .cf-hint{ font-size:12.5px; color:var(--muted); line-height:1.5; margin-top:6px; }
  #promptInput{
    width:100%; box-sizing:border-box; margin-top:12px; padding:12px 14px;
    border:2px solid var(--line); border-radius:12px; background:var(--paper);
    color:var(--ink); font-family:var(--font); font-size:15px; outline:none;
  }
  #promptInput:focus{ border-color:var(--cover); }
  #promptSheet .cf-row, #pickSheet .cf-row{ display:flex; gap:9px; margin-top:16px; }
  #promptSheet button, #pickSheet button.sheet-act{
    flex:1; border:none; border-radius:999px; padding:13px; font-family:var(--font);
    font-weight:800; font-size:14px; cursor:pointer;
  }
  #promptCancel, #pickCancel{ background:var(--paper-dark); color:var(--ink); }
  #promptOk{ background:var(--cover); color:var(--on-cover); }
  #pickList{ margin-top:12px; max-height:52vh; overflow-y:auto; }
  .pick-row{
    display:flex; flex-direction:column; align-items:flex-start; gap:2px;
    width:100%; text-align:left; border:1.5px solid var(--line); background:var(--paper);
    border-radius:14px; padding:12px 14px; margin-bottom:8px; cursor:pointer;
    font-family:var(--font); min-height:48px;
  }
  .pick-row:active{ border-color:var(--cover); }
  .pick-label{ font-size:14.5px; font-weight:700; color:var(--ink); }
  .pick-sub{ font-size:12px; color:var(--muted); }


  /* ---------- Rich call card in chat ---------- */
  .call-card{
    border-radius:16px; padding:13px 14px; min-width:210px; max-width:280px;
    background:linear-gradient(135deg, var(--cover), var(--cover-light)); color:#fff;
    box-shadow:0 4px 14px rgba(79,70,229,0.28);
  }
  .call-card .cc-top{ display:flex; align-items:center; gap:9px; }
  .call-card .cc-icon{
    width:36px; height:36px; border-radius:50%; background:rgba(255,255,255,0.22);
    display:flex; align-items:center; justify-content:center; font-size:17px; flex-shrink:0;
  }
  .call-card .cc-title{ font-weight:800; font-size:13.5px; line-height:1.25; }
  .call-card .cc-status{ font-size:11px; opacity:.9; margin-top:1px; display:flex; align-items:center; gap:4px; }
  .call-card .cc-dot{
    width:7px; height:7px; border-radius:50%; background:#4ade80; display:inline-block;
    animation:ccPulse 1.6s ease-in-out infinite;
  }
  @keyframes ccPulse{ 0%,100%{opacity:1;} 50%{opacity:.35;} }
  .call-card .cc-join{
    width:100%; margin-top:11px; border:none; border-radius:999px; padding:10px;
    background:#fff; color:var(--cover); font-family:var(--font); font-weight:800;
    font-size:13px; cursor:pointer;
  }
  .call-card .cc-join[disabled]{ background:rgba(255,255,255,0.28); color:#fff; cursor:default; }
  .chat-row.mine .call-card{ background:linear-gradient(135deg,#3f3a8f,#5b52c9); }

  /* Picture and file bubbles in DM — same footprint as a call-card so a
     conversation with a mix of text, invites, photos and files reads as one
     consistent feed rather than three different widget styles. */
  .dm-img-card{ display:block; max-width:240px; border-radius:14px; overflow:hidden; line-height:0; }
  .dm-img-card img{ width:100%; height:auto; max-height:280px; object-fit:cover; display:block; }
  .dm-file-card{
    display:flex; align-items:center; gap:10px; border-radius:14px; padding:11px 13px;
    min-width:200px; max-width:270px; text-decoration:none;
    background:var(--paper); border:1px solid var(--paper-dark);
  }
  .chat-row.mine .dm-file-card{ background:rgba(255,255,255,0.14); border-color:rgba(255,255,255,0.24); }
  .dm-file-icon{
    width:36px; height:36px; border-radius:10px; background:var(--cover); color:var(--on-cover);
    display:flex; align-items:center; justify-content:center; font-size:16px; flex-shrink:0;
  }
  .dm-file-name{ font-weight:700; font-size:13px; color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .chat-row.mine .dm-file-name{ color:#fff; }
  .dm-file-size{ font-size:11px; color:var(--muted); margin-top:1px; }
  .chat-row.mine .dm-file-size{ color:rgba(255,255,255,0.75); }

  /* ---------- Emoji picker ---------- */
  #emojiPanel{
    position:fixed; left:12px; right:12px; z-index:9700; display:none;
    background:var(--card); border:1px solid var(--paper-dark); border-radius:16px;
    padding:10px; box-shadow:0 -6px 26px rgba(0,0,0,0.2); max-height:220px; overflow-y:auto;
  }
  #emojiPanel.show{ display:block; }
  .emoji-grid{ display:grid; grid-template-columns:repeat(8,1fr); gap:4px; }
  .emoji-grid button{
    border:none; background:none; font-size:22px; cursor:pointer; padding:6px 0;
    border-radius:8px; line-height:1;
  }
  .emoji-grid button:active{ background:var(--paper-dark); }
  .emoji-cat{ font-size:10.5px; font-weight:800; color:var(--muted); text-transform:uppercase;
    letter-spacing:.04em; margin:6px 0 4px; }
  .input-icon-btn{
    border:none; background:var(--paper-dark); color:var(--ink); border-radius:999px;
    width:38px; height:38px; font-size:17px; cursor:pointer; flex-shrink:0;
  }

  /* ---------- Friends row on the inbox ---------- */
  .friends-strip{ display:flex; gap:12px; overflow-x:auto; padding:4px 2px 10px; scrollbar-width:none; }
  .friends-strip::-webkit-scrollbar{ display:none; }
  .friend-chip{
    flex:0 0 auto; width:60px; text-align:center; cursor:pointer; background:none; border:none; padding:0;
  }
  .fc-avatar{ position:relative; display:inline-block; }
  .fc-dot{
    position:absolute; bottom:0; right:0; width:13px; height:13px; border-radius:50%;
    background:#22c55e; border:2.5px solid var(--card);
  }
  .friend-chip .fc-name{
    font-size:10.5px; font-weight:700; color:var(--ink); margin-top:4px;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .read-tick{ color:#38bdf8; font-weight:800; }


  /* ---------- Partner cards (online list) ---------- */
  .pr-person-row{ align-items:flex-start !important; padding:13px 12px !important; }
  .lang-pair{ display:flex; align-items:center; gap:7px; margin-top:5px; }
  .lang-chip{ display:flex; flex-direction:column; align-items:flex-start; gap:2px; }
  .lang-code{ font-size:11.5px; font-weight:800; color:var(--ink); letter-spacing:.02em; }
  .lang-dots{ display:flex; gap:2.5px; }
  .lang-dots i{ width:5px; height:5px; border-radius:50%; background:var(--muted-soft); opacity:.45; display:block; }
  .lang-dots i.on{ opacity:1; background:var(--cover); }
  .lang-native .lang-dots i{ background:#16a34a; opacity:1; }
  .lang-arrow{ color:var(--muted-soft); font-size:13px; margin:0 1px; align-self:center; }
  .partner-bio{
    font-size:12.5px; color:var(--muted); line-height:1.4; margin-top:6px;
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  }
  .partner-tags{ display:flex; flex-wrap:wrap; gap:5px; margin-top:7px; }
  .partner-tag{
    font-size:10.5px; font-weight:700; background:var(--paper-dark); color:var(--muted);
    border-radius:999px; padding:3px 9px;
  }
  .partner-tag.highlight{ background:#fff1e6; color:#b45309; font-weight:800; }
  body.dark-mode .partner-tag.highlight{ background:#78350f; color:#fde68a; }


  /* Import a deck straight from the study panel */
  .study-import{
    border:1.5px dashed var(--paper-dark); border-radius:14px;
    padding:13px; margin-bottom:12px; text-align:center;
  }
  .study-import .si-title{ font-weight:800; font-size:13px; color:var(--ink); }
  .study-import .si-sub{ font-size:11.5px; color:var(--muted); margin-top:3px; line-height:1.45; }
  .study-import .si-row{ display:flex; gap:7px; margin-top:9px; }
  .study-import button{
    flex:1; border:none; border-radius:999px; padding:9px; font-family:var(--font);
    font-weight:800; font-size:12px; cursor:pointer; background:var(--cover); color:var(--on-cover);
  }
  .study-import button.ghost{ background:var(--paper-dark); color:var(--ink); }
  #studyImportMsg{ font-size:11.5px; margin-top:8px; line-height:1.45; }


  /* Study session: deck picker + context sentence */
  .study-example{
    margin-top:14px; padding:11px 13px; background:var(--paper-dark);
    border-radius:12px; text-align:left; width:100%;
  }
  .study-example .se-label{
    font-size:9.5px; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
    color:var(--muted); margin-bottom:5px;
  }
  .study-example .se-vn{ font-size:13.5px; color:var(--ink); line-height:1.45; }
  .study-example .se-en{ font-size:12px; color:var(--muted); line-height:1.4; margin-top:3px; }
  .study-deck-row{ display:flex; flex-wrap:wrap; gap:7px; margin-bottom:10px; }
  .study-deck-btn{
    flex:1 1 30%; border:1.5px solid var(--paper-dark); background:var(--paper); color:var(--ink);
    border-radius:12px; padding:9px 6px; font-family:var(--font); font-weight:800;
    font-size:12px; cursor:pointer;
  }
  .study-deck-btn.active{ background:var(--cover); border-color:transparent; color:var(--on-cover); }
  .study-shared-tag{
    display:inline-block; font-size:10px; font-weight:800; background:var(--stamp);
    color:#fff; border-radius:999px; padding:2px 8px; margin-left:6px;
  }


  /* ---------- Keyboard focus ----------
     There were no visible focus styles at all, which makes the app hard to use
     with a keyboard or switch control. :focus-visible only shows the ring for
     keyboard users, so mouse/touch interaction looks unchanged. */
  :focus-visible{
    outline:3px solid var(--cover);
    outline-offset:2px;
    border-radius:6px;
  }
  .live-act:focus-visible, .call-util-btn:focus-visible{ outline-color:#fff; }
  .bn-btn:focus-visible{ outline-offset:-3px; } /* v224: the bar is white, so the ring keeps the teal colour (white on white was invisible) */

  /* ---------- Offline banner ---------- */
  #offlineBar{
    position:fixed; left:0; right:0; top:0; z-index:9950; display:none;
    background:var(--bad); color:#fff; text-align:center;
    font-family:var(--font); font-weight:800; font-size:12.5px;
    padding:calc(7px + env(safe-area-inset-top)) 12px 7px;
  }
  #offlineBar.show{ display:block; }
  /* v224: the bar no longer covers the header buttons — the page moves down under it */
  body:has(#offlineBar.show) .book{ padding-top:34px; }
  html.vc-vd body:has(#offlineBar.show) .cover-title{ top:34px; }


  /* ---------- Touch target sizing ----------
     Several icon buttons render at 24-34px, which is below the 44px minimum
     Apple recommends and the 48dp Material recommends. Rather than inflate the
     visuals, we extend the hit area with a transparent overlay so they look the
     same but are reliably tappable — especially one-handed on a phone. */
  /* NOTE: .dark-toggle is deliberately excluded here — it is positioned
     absolutely in the header, and a blanket position:relative would override
     that and drop it back into the flow. It already has a position, so the
     ::after hit area below anchors correctly regardless. */
  .pr-back-btn, .fav-icon-btn, .call-util-btn, .prompt-close,
  .live-tile-menu, .live-act, .layout-btn,
  .msg-tab, .ev-btn, .more-pin{
    position:relative;
  }
  /* .teacher-modal-close is absolute (top-right) — it was in the list above and
     got knocked into the flow, sitting on top of every dialog's title. */
  .pr-back-btn::after, .fav-icon-btn::after, .call-util-btn::after,
  .prompt-close::after, .live-tile-menu::after, .dark-toggle::after,
  .live-act::after, .layout-btn::after, .teacher-modal-close::after{
    content:''; position:absolute; left:50%; top:50%;
    width:44px; height:44px; transform:translate(-50%,-50%);
  }
  /* Give the smallest ones a touch more breathing room in their rows. */
  .live-tile-menu{ width:26px; height:26px; }
  .solo-util{ gap:8px !important; }
  .fav-actions{ gap:10px !important; }


  /* More sheet: descriptions + pin affordance */
  .more-item .more-desc{
    font-size:10px; font-weight:600; color:var(--muted); line-height:1.25;
    margin-top:2px; text-align:center;
  }
  .more-item .more-pin{
    position:absolute; top:5px; right:6px; font-size:11px; opacity:.85;
  }
  .more-item.pinned{ border-color:var(--cover); }
  /* Edit mode: tiles stop being links and start being checkboxes. The badge
     replaces the pin marker so both states are visible — a pinned tile shows
     what removing does, an unpinned one shows what adding does. */
  .more-grid.editing .more-item{ border-style:dashed; }
  .more-grid.editing .more-item.pinned{ border-style:solid; background:var(--paper-dark); }
  .more-grid.editing .more-item .more-pin{ display:none; }
  .more-item .more-check{
    position:absolute; top:4px; right:5px; font-size:12px; line-height:1;
    width:17px; height:17px; border-radius:50%;
    display:flex; align-items:center; justify-content:center;
    background:var(--paper-dark); color:var(--muted);
  }
  .more-item.pinned .more-check{ background:var(--cover); color:var(--on-cover); }
  #navEditToggle.on{ background:var(--cover); color:var(--on-cover); }
  .more-hint{
    font-size:11.5px; color:var(--muted); text-align:center; margin-top:12px; line-height:1.5;
  }
  .pin-toast{
    position:fixed; left:50%; transform:translateX(-50%);
    bottom:calc(86px + env(safe-area-inset-bottom)); z-index:9900;
    background:var(--ink); color:var(--card); border-radius:999px;
    padding:10px 18px; font-family:var(--font); font-weight:700; font-size:12.5px;
    box-shadow:0 8px 24px rgba(0,0,0,0.3); opacity:0; pointer-events:none;
    transition:opacity .2s ease, transform .2s ease;
  }
  .pin-toast.show{ opacity:1; transform:translateX(-50%) translateY(-4px); }


  /* ---------- Event discussion thread ---------- */
  .ev-chat-panel{
    position:fixed; left:0; right:0; bottom:0; z-index:9400;
    background:var(--card); border-radius:20px 20px 0 0; box-shadow:0 -8px 30px rgba(20,21,43,0.22);
    display:none; flex-direction:column; max-height:80vh;
  }
  .ev-chat-panel.show{ display:flex; }
  .ev-chat-head{
    display:flex; align-items:flex-start; gap:10px; padding:14px 14px 10px;
    border-bottom:1px solid var(--paper-dark);
  }
  .ev-chat-title{ font-weight:800; font-size:14.5px; color:var(--ink); line-height:1.3; }
  .ev-chat-sub{ font-size:11.5px; color:var(--muted); margin-top:2px; }
  .ev-chat-body{ flex:1; overflow-y:auto; padding:12px 14px; min-height:200px; }
  .ev-chat-foot{
    display:flex; gap:8px; padding:10px 14px calc(14px + env(safe-area-inset-bottom));
    border-top:1px solid var(--paper-dark);
  }
  .host-tag{
    font-size:9.5px; font-weight:800; background:var(--cover); color:var(--on-cover);
    border-radius:999px; padding:1px 6px; margin-left:5px; vertical-align:middle;
  }
  .ev-chat-count{
    display:inline-flex; align-items:center; gap:3px; font-size:11px; font-weight:800;
    color:var(--muted);
  }


  /* ---------- Event map ---------- */
  .ev-view-toggle{ display:flex; gap:6px; margin:10px 0 8px; }
  .ev-view-btn{
    flex:1; border:1.5px solid var(--paper-dark); background:var(--paper); color:var(--ink);
    border-radius:12px; padding:9px; font-family:var(--font); font-weight:800; font-size:12.5px; cursor:pointer;
  }
  .ev-view-btn.active{ background:var(--cover); border-color:transparent; color:var(--on-cover); }
  #eventMap{
    height:340px; width:100%; border-radius:var(--radius-sm); overflow:hidden;
    border:1px solid var(--paper-dark); background:var(--paper-dark); display:none;
  }
  #eventMap.show{ display:block; }
  .leaflet-container{ font-family:var(--font); }
  .ev-popup-title{ font-weight:800; font-size:13.5px; margin-bottom:3px; }
  .ev-popup-meta{ font-size:11.5px; color:#555; }
  .ev-popup-btn{
    display:inline-block; margin-top:7px; background:var(--cover); color:var(--on-cover);
    border:none; border-radius:999px; padding:5px 12px; font-family:var(--font);
    font-weight:800; font-size:11.5px; cursor:pointer; text-decoration:none;
  }
  /* Address autocomplete */
  .addr-wrap{ position:relative; }
  .addr-results{
    position:absolute; left:0; right:0; top:100%; z-index:40; background:var(--card);
    border:1px solid var(--paper-dark); border-radius:12px; margin-top:4px;
    max-height:210px; overflow-y:auto; box-shadow:0 8px 24px rgba(0,0,0,0.18); display:none;
  }
  .addr-results.show{ display:block; }
  .addr-item{ padding:10px 12px; cursor:pointer; border-bottom:1px solid var(--paper-dark); }
  .addr-item:last-child{ border-bottom:none; }
  .addr-item:active{ background:var(--paper-dark); }
  .addr-item .ai-name{ font-weight:700; font-size:13px; color:var(--ink); }
  .addr-item .ai-sub{ font-size:11.5px; color:var(--muted); margin-top:1px; }
  #evPickMap{ height:200px; border-radius:12px; overflow:hidden; margin-bottom:10px; display:none; border:1px solid var(--paper-dark); }
  #evPickMap.show{ display:block; }


  /* Incoming call invite has to beat the immersive call shell (z-index 8800),
     otherwise it renders behind the video and is never seen. */
  #practiceInviteOverlay{ z-index:9800 !important; }
  body.in-solo-call #practiceInviteOverlay,
  body.in-live-room #practiceInviteOverlay{
    align-items:flex-start; padding-top:calc(70px + env(safe-area-inset-top));
    background:rgba(0,0,0,0.55);
  }
  .invite-toast{
    background:var(--card); border-radius:18px; padding:16px 18px; width:100%;
    max-width:380px; box-shadow:0 12px 40px rgba(0,0,0,0.45);
  }


  /* Solo call: dismissible bilingual prompt + layout modes */
  #practiceRoomView.solo .solo-prompt{ bottom:150px; padding:12px 14px 12px; }
  #practiceRoomView.solo .solo-prompt.hidden{ display:none; }
  .prompt-close{
    border:none; background:rgba(255,255,255,0.18); color:#fff; width:26px; height:26px;
    border-radius:999px; font-size:13px; cursor:pointer; flex-shrink:0;
  }
  .prompt-vn{ font-size:15px; font-weight:700; color:#fff; line-height:1.4; }
  .prompt-en{ font-size:12.5px; color:rgba(255,255,255,0.72); line-height:1.4; margin-top:4px; }
  #promptReopen{
    position:absolute; right:12px; bottom:150px; z-index:6; display:none;
    border:none; background:rgba(0,0,0,0.55); backdrop-filter:blur(6px); color:#fff;
    border-radius:999px; padding:8px 14px; font-family:var(--font); font-weight:800;
    font-size:12px; cursor:pointer;
  }
  #practiceRoomView.solo #promptReopen.show{ display:block; }

  /* ---------- Multi-pane modes, TikTok-tile model ----------
     Panes are NOT full-bleed halves. A 50%x100% pane on a phone is roughly
     1:4, so object-fit:cover crops the face down to a vertical sliver — that
     was the "long and weird" look. Instead each feed is a rounded tile with a
     sane aspect ratio, centered on black with a gap, exactly like TikTok's
     multi-guest tiles. Heights are min() of a viewport-height and a
     viewport-width term so the geometry stays deterministic (the name tags
     below rely on knowing the tile's half-height). */

  /* Stacked ("one TV"): two wide tiles, roughly 4:3, meeting at the middle.
     width MUST be explicit, never auto. For replaced elements (<video>), an
     absolutely positioned box with width:auto uses the element's INTRINSIC
     width (CSS 2.1 §10.3.8) and ignores `right` as over-constrained — so the
     tile ended up sized by the camera's resolution, and a 640x480 local next
     to a 1280x720 remote produced two mismatched boxes. Explicit width means
     stream resolution is irrelevant to layout; object-fit:cover does the rest.
     !important because #practiceLocalVideo doubles as the draggable PiP
     self-view, which writes inline left/top/width/height. */
  #practiceRoomView.solo.split #practiceRemoteVideo{
    position:absolute !important; left:8px !important; right:auto !important; top:auto !important;
    bottom:calc(50% + 5px) !important;
    width:calc(100% - 16px) !important; height:min(38vh, 68vw) !important;
    max-width:none !important; max-height:none !important; min-width:0 !important; aspect-ratio:auto !important;
    object-fit:cover !important; object-position:center center;
    border-radius:16px; background:#000;
  }
  #practiceRoomView.solo.split #practiceLocalVideo{
    position:absolute !important; left:8px !important; right:auto !important;
    top:calc(50% + 5px) !important; bottom:auto !important;
    width:calc(100% - 16px) !important; height:min(38vh, 68vw) !important;
    max-width:none !important; max-height:none !important; min-width:0 !important; aspect-ratio:auto !important;
    object-fit:cover !important; object-position:center center;
    border-radius:16px; background:#000;
    border:none; box-shadow:none; cursor:default; transform:none !important;
  }
  /* Name tags sit inside their own tile, anchored to the shared seam so they
     stay correct whatever height the tile resolves to. */
  #practiceRoomView.solo.split #practicePeerLabel{ display:none; }
  .split-tag{ display:none; }
  #practiceRoomView.solo.split .split-tag,
  #practiceRoomView.solo.side .split-tag{
    position:absolute; z-index:6; display:block;
    background:rgba(0,0,0,0.55); color:#fff; font-weight:800; font-size:11.5px;
    padding:4px 10px; border-radius:999px; pointer-events:none;
  }
  #practiceRoomView.solo.split .split-tag.top{ left:18px; top:auto; bottom:calc(50% + 16px); }
  #practiceRoomView.solo.split .split-tag.bottom{ left:18px; top:calc(50% + 16px); bottom:auto; }
  /* The gap between tiles reads as the divider now, so the drawn line goes. */
  .solo-split-line{ display:none; }

  /* Side-by-side: two portrait tiles, roughly 3:4, centered vertically. */
  #practiceRoomView.solo.side:not(.split) #practiceRemoteVideo{
    position:absolute !important; left:8px !important; right:auto !important;
    top:50% !important; bottom:auto !important;
    transform:translateY(-50%) !important;
    width:calc(50% - 11px) !important; height:min(74vh, 76vw) !important;
    max-width:none !important; max-height:none !important; min-width:0 !important; aspect-ratio:auto !important;
    object-fit:cover !important; object-position:center center;
    border-radius:16px; background:#000;
  }
  #practiceRoomView.solo.side:not(.split) #practiceLocalVideo{
    position:absolute !important; right:8px !important; left:auto !important;
    top:50% !important; bottom:auto !important;
    transform:translateY(-50%) !important;
    width:calc(50% - 11px) !important; height:min(74vh, 76vw) !important;
    max-width:none !important; max-height:none !important; min-width:0 !important; aspect-ratio:auto !important;
    object-fit:cover !important; object-position:center center;
    border-radius:16px; background:#000;
    border:none; box-shadow:none; cursor:default;
  }
  #practiceRoomView.solo.side #practicePeerLabel{ display:none; }
  /* Anchored to the bottom edge of the tiles: half-height is min(37vh,38vw). */
  #practiceRoomView.solo.side .split-tag{
    top:auto; bottom:calc(50% - min(37vh, 38vw) + 10px);
  }
  #practiceRoomView.solo.side .split-tag.top{ left:18px; right:auto; }
  #practiceRoomView.solo.side .split-tag.bottom{ left:auto; right:18px; }

  .layout-btn{
    border:none; background:rgba(255,255,255,0.16); color:#fff; border-radius:999px;
    height:34px; padding:0 12px; font-family:var(--font); font-weight:800; font-size:11.5px;
    cursor:pointer; backdrop-filter:blur(6px);
  }
  /* Study/Chat move inline with the call controls instead of floating on top. */
  body.in-solo-call #roomFloatBar{ display:none; }


  /* ---------- 1:1 call: full-bleed immersive stage ---------- */
  body.in-solo-call{ background:#000; overflow:hidden; }
  body.in-solo-call #bottomNav,
  body.in-solo-call footer{ display:none !important; }
  #practiceRoomView.solo{
    position:fixed; inset:0; z-index:8800; margin:0 !important;
    background:#000; display:flex; flex-direction:column;
  }
  #practiceRoomView.solo #practiceCallStage{
    position:absolute; inset:0; border-radius:0 !important; max-height:none !important;
    aspect-ratio:auto !important; background:#000; overflow:hidden;
  }
  #practiceRoomView.solo #practiceRemoteVideo{
    width:100%; height:100%; object-fit:cover; background:#0b0b0f;
  }
  /* The small self-view: draggable, tap to swap which feed is large. */
  #practiceRoomView.solo #practiceLocalVideo{
    position:absolute; width:104px; height:150px; object-fit:cover;
    border-radius:14px; border:none; background:#181820; z-index:6;
    box-shadow:0 6px 20px rgba(0,0,0,0.5); cursor:grab; touch-action:none;
    transition:box-shadow .15s ease, transform .18s cubic-bezier(.2,.9,.3,1);
  }
  #practiceRoomView.solo #practiceLocalVideo.dragging{
    cursor:grabbing; transition:none; box-shadow:0 10px 30px rgba(0,0,0,0.65); transform:scale(1.04);
  }
  #practiceRoomView.solo .solo-topbar{
    position:absolute; top:0; left:0; right:0; z-index:7; display:flex; align-items:center; gap:8px;
    padding:calc(10px + env(safe-area-inset-top)) 12px 26px;
    background:linear-gradient(to bottom, rgba(0,0,0,0.72), rgba(0,0,0,0));
    pointer-events:none;
  }
  #practiceRoomView.solo .solo-topbar > *{ pointer-events:auto; }
  #practiceRoomView.solo #practiceCallTimer,
  #practiceRoomView.solo #practicePeerLabel{
    position:static !important; background:rgba(255,255,255,0.16); backdrop-filter:blur(6px);
    color:#fff; font-weight:800; font-size:12px; padding:6px 12px; border-radius:999px;
  }
  #practiceRoomView.solo .solo-util{ margin-left:auto; display:flex; gap:6px; }
  #practiceRoomView.solo .solo-controls{
    position:absolute; left:0; right:0; bottom:0; z-index:7;
    padding:14px 12px calc(16px + env(safe-area-inset-bottom));
    background:linear-gradient(to top, rgba(0,0,0,0.8), rgba(0,0,0,0));
    display:flex; flex-direction:column; gap:9px;
  }
  #practiceRoomView.solo .solo-controls .solo-row{ display:flex; gap:9px; justify-content:center; }
  #practiceRoomView.solo .solo-controls button{
    border:none; border-radius:999px; font-family:var(--font); font-weight:800; cursor:pointer;
    background:rgba(255,255,255,0.16); color:#fff; backdrop-filter:blur(8px);
    height:52px; min-width:52px; font-size:12px; display:flex; flex-direction:column;
    align-items:center; justify-content:center; gap:2px; padding:0 14px; flex:0 0 auto;
  }
  #practiceRoomView.solo .solo-controls button.on{ background:#fff; color:#111; }
  #practiceRoomView.solo .solo-controls button.primary{ background:var(--cover); }
  #practiceRoomView.solo .solo-controls button.danger{ background:var(--bad); }
  #practiceRoomView.solo .solo-controls .solo-row.secondary{
    flex-wrap:wrap; gap:7px;
    /* Collapsed by default — five extra buttons permanently on screen buried
       whoever was in the lower half of the frame. The ⋯ More button reveals
       them; everything keeps its existing bindings and state. */
    display:none;
  }
  #practiceRoomView.solo .solo-controls.more-open .solo-row.secondary{ display:flex; }
  #practiceRoomView.solo .solo-controls .solo-row.secondary button{
    height:34px; font-size:11px; flex-direction:row; gap:4px; padding:0 11px;
    background:rgba(255,255,255,0.11);
  }
  #practiceRoomView.solo #soloMoreBtn.active{ background:#fff; color:#111; }

  /* Minimize the whole control bar — not just the secondary row — down to a
     thin restore pill, so the bar itself can get out of the way entirely. */
  .solo-min-btn{
    position:absolute; top:2px; left:50%; transform:translateX(-50%);
    border:none; background:rgba(255,255,255,0.16); color:#fff; backdrop-filter:blur(6px);
    width:44px; height:18px; border-radius:999px; font-size:12px; line-height:1;
    cursor:pointer; display:none;
  }
  /* NOTE: .solo-controls is already position:absolute (bottom:0), which is its
     own containing block — do NOT add position:relative here. Doing so
     overrides the absolute positioning and drops the whole bar back into flex
     flow at the TOP of the screen, on top of everything else. */
  body.in-solo-call .solo-min-btn{ display:block; }
  body.in-solo-call.ctl-minimized #soloControls{ display:none; }
  .solo-restore-btn{
    display:none; position:fixed; left:50%; transform:translateX(-50%);
    bottom:calc(10px + env(safe-area-inset-bottom)); z-index:7;
    border:none; background:rgba(255,255,255,0.16); color:#fff; backdrop-filter:blur(6px);
    width:56px; height:26px; border-radius:999px; font-size:13px; cursor:pointer;
  }
  body.in-solo-call.ctl-minimized .solo-restore-btn{ display:block; }

  /* Chrome auto-hides during a call so the video is unobstructed. Tapping the
     stage brings it back (and that tap does NOT also swap the feeds). */
  #practiceRoomView.solo.chrome-hidden .solo-topbar,
  #practiceRoomView.solo.chrome-hidden .solo-controls,
  #practiceRoomView.solo.chrome-hidden .solo-prompt,
  #practiceRoomView.solo.chrome-hidden #promptReopen{
    opacity:0; pointer-events:none;
  }
  #practiceRoomView.solo .solo-topbar,
  #practiceRoomView.solo .solo-controls,
  #practiceRoomView.solo .solo-prompt{ transition:opacity .22s ease; }

  /* Split/side reserve a real strip for the controls instead of letting them
     float over the lower pane — that strip is why faces kept getting covered. */
  #practiceRoomView.solo.split #practiceCallStage,
  #practiceRoomView.solo.side #practiceCallStage{ inset:0 0 104px 0; }
  #practiceRoomView.solo.split.ctl-tall #practiceCallStage,
  #practiceRoomView.solo.side.ctl-tall #practiceCallStage{ inset:0 0 152px 0; }
  #practiceRoomView.solo.split .solo-controls,
  #practiceRoomView.solo.side .solo-controls{
    background:#0b0b0f; padding-top:12px;
  }
  #practiceRoomView.solo.split.chrome-hidden #practiceCallStage,
  #practiceRoomView.solo.side.chrome-hidden #practiceCallStage{ inset:0; }
  body.ctl-minimized #practiceRoomView.solo.split #practiceCallStage,
  body.ctl-minimized #practiceRoomView.solo.side #practiceCallStage{ inset:0; }
  /* Tiles are centered on the stage, so shrinking the stage lifts them clear of
     the study sheet automatically — no separate per-tile offsets needed. */
  body.in-solo-call.study-open #practiceRoomView.solo.split #practiceCallStage,
  body.in-solo-call.study-open #practiceRoomView.solo.side #practiceCallStage{
    inset:0 0 calc(104px + 24dvh) 0;
  }
  body.in-solo-call.study-open #practiceRoomView.solo.split #practiceRemoteVideo,
  body.in-solo-call.study-open #practiceRoomView.solo.split #practiceLocalVideo{
    height:min(26vh, 60vw) !important;
  }
  body.in-solo-call.study-open #practiceRoomView.solo.side #practiceRemoteVideo,
  body.in-solo-call.study-open #practiceRoomView.solo.side:not(.split) #practiceLocalVideo{
    height:min(46vh, 62vw) !important;
  }
  body.in-solo-call.study-open #practiceRoomView.solo.side .split-tag{
    bottom:calc(50% - min(23vh, 31vw) + 10px);
  }

  /* ---------- TikTok-Live model: video is a full-screen background layer;
     study is a compact floating card, never a document-flow section that
     resizes the video. The previous version shrank #practiceRoomView.solo
     itself to make room, which visibly letterboxed the video — that's exactly
     the bug this replaces. The video's box is now untouched by study state. ---------- */
  body.in-solo-call.study-open #practiceRoomView.solo .solo-prompt{ display:none; }
  /* Study panel, in-call only: floating card anchored above the control row,
     hard-capped so it can never grow into or push the video. Long content
     scrolls inside .study-body instead of growing the sheet. */
  body.in-solo-call .study-panel{
    left:12px; right:12px; bottom:calc(96px + env(safe-area-inset-bottom));
    max-width:480px; margin:0 auto; border-radius:18px;
    background:rgba(255,255,255,0.94); backdrop-filter:blur(16px);
    box-shadow:0 14px 40px rgba(0,0,0,0.4);
    max-height:32dvh !important; z-index:9300;
  }
  body.dark-mode.in-solo-call .study-panel{ background:rgba(24,25,42,0.9); }
  body.in-solo-call.ctl-tall-open .study-panel{ bottom:calc(142px + env(safe-area-inset-bottom)); }
  /* Controls minimized: the sheet reclaims the space they were reserving. */
  body.in-solo-call.ctl-minimized .study-panel{ bottom:calc(52px + env(safe-area-inset-bottom)); }
  /* Card content shrinks to fit rather than growing the sheet: clamp() text
     size plus a line-clamp on the longer strings keeps a 3-line worst case. */
  body.in-solo-call .study-head{ padding:8px 12px 6px; }
  body.in-solo-call .study-title{ font-size:12.5px; }
  body.in-solo-call .study-sub{ font-size:10.5px; }
  body.in-solo-call .study-body{ padding:6px 12px; }
  body.in-solo-call .study-card{ padding:14px 14px; min-height:0; gap:5px; }
  body.in-solo-call .study-card-cat{ font-size:10px; padding:2px 9px; }
  body.in-solo-call .study-card-vn{ font-size:clamp(22px, 6.4vw, 30px); line-height:1.15; }
  body.in-solo-call .study-card-en{
    font-size:clamp(14px, 4vw, 18px); margin-top:3px;
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  }
  body.in-solo-call .study-card-hint{ font-size:10px; }
  body.in-solo-call .study-progress{ margin-top:6px; font-size:10.5px; }
  body.in-solo-call .study-foot{ padding:6px 12px calc(8px + env(safe-area-inset-bottom)); gap:6px; }
  body.in-solo-call .study-foot button{ height:40px; font-size:13px; }
  /* The auto-hide-after-idle behavior further down is for distraction-free
     video; while studying, the floating sheet is anchored just above the
     control row, so hiding that row leaves the sheet floating with nothing
     below it. Keep controls visible for the duration of a study session. */
  body.in-solo-call.study-open #practiceRoomView.solo.chrome-hidden .solo-controls{
    opacity:1; pointer-events:auto;
  }
  /* Prompt card floats over the video instead of pushing layout around. */
  #practiceRoomView.solo .solo-prompt{
    position:absolute; left:12px; right:12px; bottom:170px; z-index:6;
    background:rgba(0,0,0,0.5); backdrop-filter:blur(8px); border-radius:16px;
    padding:11px 14px; color:#fff; margin:0 !important;
  }
  #practiceRoomView.solo .solo-prompt .section-title{ color:#fff !important; }
  #practiceRoomView.solo .solo-prompt #practicePromptText{ color:rgba(255,255,255,0.92); }
  .swap-hint{
    position:absolute; bottom:6px; left:50%; transform:translateX(-50%);
    background:rgba(0,0,0,0.6); color:#fff; font-size:9px; font-weight:800;
    padding:2px 7px; border-radius:999px; pointer-events:none; white-space:nowrap;
  }

  .pr-pill .pr-pill-dot{ width:8px;height:8px;border-radius:50%;background:var(--muted-soft); flex-shrink:0; }
  .pr-pill[data-mode="vi"].active{ background:linear-gradient(135deg, var(--cover), var(--cover-light)); border-color:transparent; color:#fff; }
  .pr-pill[data-mode="en"].active{ background:linear-gradient(135deg, var(--stamp), var(--stamp-light)); border-color:transparent; color:#fff; }
  .pr-pill[data-mode="live"].active{ background:linear-gradient(135deg, var(--cover), var(--cover-light)); border-color:transparent; color:#fff; }
  #prPillRow .pr-pill[hidden]{ display:none !important; }
  .pr-lang-seg[hidden]{ display:none !important; }
  .pr-my-langs{ display:flex; flex-wrap:wrap; gap:6px; margin:10px 0 4px; align-items:center; font:700 12.5px var(--font); }
  .pr-my-langs .pl-chip{ background:rgba(255,255,255,.22); border-radius:999px; padding:4px 10px; }
  .pr-my-langs button{ border:0; background:none; color:inherit; text-decoration:underline; font:700 12px var(--font); cursor:pointer; opacity:.9; }
  .pr-match-prefs{ margin:8px 0 2px; } .pr-match-prefs > summary{ cursor:pointer; font:700 12.5px var(--font); opacity:.92; list-style:none; }
  .pr-match-prefs > summary::-webkit-details-marker{ display:none; }
  .pr-person-avatar-wrap{ position:relative; }
  .pr-flag-badge{ position:absolute; right:-4px; bottom:-3px; width:22px; height:22px; border-radius:50%; background:var(--card); box-shadow:0 1px 4px rgba(0,0,0,.18);
    display:flex; align-items:center; justify-content:center; font-size:13px; line-height:1; }
  .pr-lang-line{ font:700 12px var(--font); color:var(--muted); margin-top:2px; }
  .pr-lang-line b{ color:var(--ink); }
  .lang-swap-chip{ position:absolute; left:50%; top:50px; transform:translateX(-50%); z-index:6; display:flex; align-items:center; gap:8px; background:rgba(0,0,0,.55);
    color:#fff; border-radius:999px; padding:5px 12px; font:800 12.5px var(--font); backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px); cursor:pointer; border:0; white-space:nowrap; }
  .lang-swap-chip.flash{ animation:swapFlash 1s ease 3; background:var(--gold); color:#1a1300; }
  @keyframes swapFlash{ 50%{ transform:translateX(-50%) scale(1.12); } }
  .hw-self-cta{ display:flex; align-items:center; gap:12px; width:100%; text-align:left; margin:10px 0 4px; padding:12px 14px; border-radius:var(--radius); border:1.5px dashed var(--cover);
    background:var(--primary-tint); color:var(--ink); font-family:var(--font); cursor:pointer; }
  .hw-self-cta b{ display:block; font-size:14.5px; } .hw-self-cta small{ display:block; font-size:12.5px; color:var(--muted); margin-top:2px; }
  .hw-self-cta-icon{ font-size:26px; }
  #hwAssignOverlay .hw-self-only{ display:none; }
  #hwAssignOverlay.self-mode .hw-self-only{ display:block; }
  #hwAssignOverlay.self-mode .hw-teacher-only, #hwAssignOverlay.self-mode #hwDirNote{ display:none !important; }
  .hw-goal-tag{ display:inline-block; background:var(--gold-tint); color:#8a5a00; border-radius:999px; padding:1px 8px; font-weight:800; font-size:11.5px; }
  .pr-lang-seg{ display:flex; gap:6px; background:var(--paper-dark); border-radius:999px; padding:4px; margin:12px 0 10px; }
  .pr-lang-seg button{ flex:1; border:0; background:transparent; color:var(--ink); border-radius:999px; padding:9px 8px; font:800 13.5px var(--font); cursor:pointer; }
  .pr-lang-seg button.on{ background:var(--card); box-shadow:var(--shadow-sm); color:var(--cover-deep); }
  #groupRoomsHome.pr-merged{ margin-top:18px; }
  .pr-pill[data-mode="group"].active{ background:linear-gradient(135deg, var(--group), var(--group-light)); border-color:transparent; color:#fff; }
  .pr-pill.active .pr-pill-dot{ background:#fff; }

  .pr-hero{
    border-radius:var(--radius); padding:20px; color:#fff; margin-top:10px;
    background:linear-gradient(135deg, var(--cover), var(--cover-light));
    box-shadow:var(--shadow-sm);
  }
  .pr-hero.en{ background:linear-gradient(135deg, var(--stamp), var(--stamp-light)); }
  .pr-hero-eyebrow{ font-size:11.5px; font-weight:800; letter-spacing:.04em; text-transform:uppercase; opacity:.85; }
  .pr-hero-title{ font-size:19px; font-weight:800; margin-top:4px; }
  .pr-hero-sub{ font-size:13px; opacity:.92; margin-top:3px; }
  .pr-hero-btn{
    margin-top:14px; width:100%; border:none; border-radius:999px; padding:13px;
    background:rgba(255,255,255,0.96); color:var(--ink); font-family:var(--font);
    font-weight:800; font-size:14.5px; cursor:pointer; display:flex; align-items:center; justify-content:center; gap:8px;
    box-shadow:0 4px 0 rgba(0,0,0,0.18); transition:transform .08s ease, box-shadow .08s ease;
  }
  .pr-hero-btn:active{ transform:translateY(3px); box-shadow:0 1px 0 rgba(0,0,0,0.18); }

  .pr-section-label{ font-size:12px; font-weight:800; letter-spacing:.03em; text-transform:uppercase; color:var(--muted); margin:18px 2px 8px; }

  .pr-person-row{
    display:flex; align-items:center; gap:12px; padding:12px; margin-bottom:8px;
    background:var(--paper); border:1px solid var(--paper-dark); border-radius:var(--radius-sm);
  }
  .pr-person-avatar-wrap{ position:relative; flex-shrink:0; }
  .pr-status-dot{ position:absolute; bottom:-1px; right:-1px; width:11px; height:11px; border-radius:50%; background:#22c55e; border:2px solid var(--paper); }
  .pr-person-name{ font-weight:800; font-size:14.5px; color:var(--ink); }
  .pr-person-meta{ font-size:12px; color:var(--muted); margin-top:1px; display:flex; align-items:center; gap:5px; }
  .pr-invite-btn{
    flex-shrink:0; border:none; border-radius:999px; padding:9px 16px; font-family:var(--font);
    font-weight:800; font-size:13px; color:var(--on-cover); background:var(--cover); cursor:pointer;
    box-shadow:0 3px 0 var(--cover-deep); transition:transform .08s ease, box-shadow .08s ease;
  }
  .pr-invite-btn:active{ transform:translateY(2px); box-shadow:0 1px 0 var(--cover-deep); }
  .pr-invite-btn.en{ background:var(--stamp); box-shadow:0 3px 0 #c05a3d; }
  .pr-invite-btn.en:active{ box-shadow:0 1px 0 #c05a3d; }
  .pr-empty{ text-align:center; padding:34px 18px; color:var(--muted); font-size:13.5px; }
  .pr-empty-icon{ font-size:30px; margin-bottom:8px; }

  .pr-room-grid{ display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:8px; }
  .pr-room-card{
    border-radius:var(--radius-sm); overflow:hidden; background:var(--paper);
    border:1px solid var(--paper-dark); text-align:left; cursor:pointer; padding:0;
    display:flex; flex-direction:column; box-shadow:var(--shadow-sm);
  }
  .pr-room-cover{
    position:relative; height:132px; background-size:cover; background-position:center;
    background:linear-gradient(135deg, var(--group), var(--group-light));
    display:flex; flex-direction:column; justify-content:space-between; padding:9px;
  }
  .pr-room-cover.audio{ background:linear-gradient(135deg, var(--stamp), var(--stamp-light)); }
  .pr-room-cover.has-photo{ background-color:#000; }
  .pr-room-cover-scrim{
    position:absolute; inset:0; background:linear-gradient(to bottom, rgba(0,0,0,0) 40%, rgba(0,0,0,0.72) 100%);
  }
  .pr-room-top-row{ position:relative; display:flex; justify-content:space-between; align-items:flex-start; z-index:1; }
  .pr-room-kind-badge{
    display:flex; align-items:center; gap:4px; background:rgba(0,0,0,0.34); backdrop-filter:blur(2px);
    color:#fff; font-size:10.5px; font-weight:800; border-radius:999px; padding:4px 9px;
  }
  .pr-room-occupancy{
    display:flex; align-items:center; gap:3px; background:rgba(0,0,0,0.34); color:#fff;
    border-radius:999px; padding:4px 9px; font-size:11px; font-weight:800;
  }
  .pr-room-cover-text{ position:relative; z-index:1; color:#fff; }
  .pr-room-title{ font-weight:800; font-size:13.5px; line-height:1.25; text-shadow:0 1px 3px rgba(0,0,0,0.35); }
  .pr-room-host{ font-size:11px; opacity:.92; margin-top:2px; }
  .pr-room-body{ padding:8px 10px 10px; }
  .pr-room-join{
    width:100%; border:none; border-radius:999px; padding:8px;
    background:var(--paper-dark); color:var(--ink); font-family:var(--font);
    font-weight:800; font-size:12.5px; cursor:pointer;
  }
  .pr-room-join.full{ color:var(--muted-soft); }
  .pr-create-row{ display:flex; gap:10px; margin-top:10px; }
  .pr-create-card{
    flex:1; border:none; border-radius:var(--radius); padding:16px 14px; text-align:left; cursor:pointer;
    background:var(--paper); border:1px solid var(--paper-dark);
  }
  .pr-create-card .pr-create-icon{ font-size:20px; }
  .pr-create-card .pr-create-title{ font-weight:800; font-size:13.5px; color:var(--ink); margin-top:6px; }
  .pr-create-card .pr-create-sub{ font-size:11.5px; color:var(--muted); margin-top:2px; }
  .pr-back-row{ display:flex; align-items:center; gap:10px; margin:12px 0 4px; }
  .pr-back-btn{ border:none; background:var(--paper-dark); color:var(--ink); border-radius:999px; width:34px; height:34px; font-size:15px; cursor:pointer; flex-shrink:0; }
  .pr-back-btn.active{ background:var(--cover); color:var(--on-cover); }

  /* ---------- Chat bubbles (call chat + DMs) ---------- */
  .chat-row{ display:flex; gap:7px; align-items:flex-end; max-width:100%; }
  .chat-row.mine{ justify-content:flex-end; }
  .chat-row.theirs{ justify-content:flex-start; }
  .chat-row .chat-mini-avatar{ flex-shrink:0; }
  .chat-bubble-col{ display:flex; flex-direction:column; max-width:76%; min-width:0; }
  .chat-row.mine .chat-bubble-col{ align-items:flex-end; }
  .chat-row.theirs .chat-bubble-col{ align-items:flex-start; }
  .chat-name{ font-size:10.5px; font-weight:800; color:var(--muted); margin:0 3px 2px; }
  .chat-bubble{ padding:8px 12px; border-radius:16px; font-size:13.5px; line-height:1.38; word-break:break-word; }
  .chat-row.mine .chat-bubble{ background:var(--cover); color:var(--on-cover); border-bottom-right-radius:4px; }
  .chat-row.theirs .chat-bubble{ background:var(--paper-dark); color:var(--ink); border-bottom-left-radius:4px; }

  /* ---------- Fullscreen / picture-in-picture call controls ---------- */
  .call-stage{ position:relative; }
  .call-stage:fullscreen{ background:#000; display:flex; align-items:center; justify-content:center; }
  .call-stage:fullscreen video{ max-height:100vh; }
  .call-util-btn{
    border:none; background:rgba(0,0,0,0.45); color:#fff; border-radius:999px;
    width:32px; height:32px; font-size:14px; cursor:pointer; display:flex; align-items:center; justify-content:center;
  }

  /* ---------- Friends / Favorites / DMs ---------- */
  .fav-row{
    display:flex; align-items:center; gap:12px; padding:12px; margin-bottom:8px;
    background:var(--paper); border:1px solid var(--paper-dark); border-radius:var(--radius-sm); cursor:pointer;
  }
  .fav-actions{ display:flex; gap:6px; flex-shrink:0; }
  .fav-icon-btn{ border:none; background:var(--paper-dark); color:var(--ink); border-radius:999px; width:34px; height:34px; font-size:15px; cursor:pointer; }
  .dm-thread-header{ display:flex; align-items:center; gap:10px; margin-bottom:10px; }
  /* ---------- Floating chat (pop up a DM from anywhere, including mid-call) ----------
     Same "becomes position:fixed on demand" trick as the study panel /
     whiteboard / video stage — this reuses the entire real DM thread
     (messages, sending, photos, notes, everything) rather than building a
     second, smaller messaging system that would drift out of sync with it. */
  .dm-thread-view.floating{
    position:fixed; z-index:9500; display:flex; flex-direction:column;
    left:auto; right:16px; bottom:16px; top:auto;
    width:320px; height:420px; max-width:calc(100vw - 24px); max-height:calc(100vh - 32px);
    background:var(--card); border-radius:16px; box-shadow:0 16px 50px rgba(0,0,0,0.35);
    padding:12px; margin:0 !important;
  }
  .dm-thread-view.floating .dm-log{ flex:1; min-height:0; }
  .dm-thread-view.floating .dm-drag-grip{ display:inline-block !important; cursor:grab; }
  .dm-thread-view.floating #dmThreadHeader{ cursor:grab; touch-action:none; }
  .dm-thread-view.floating.dragging #dmThreadHeader{ cursor:grabbing; }
  .dm-thread-view.floating #dmBackBtn{ display:none; }
  .dm-thread-view.floating #dmFloatCloseBtn{ display:inline-flex !important; }
  /* Dragging a small resizable box is a desktop mouse interaction — on a
     phone screen there's no room for one anyway, so it opens as a normal
     full-height sheet instead, same as any other mobile chat overlay, with
     no drag/resize handles to fight with. */
  @media (max-width:759px){
    .dm-thread-view.floating{
      left:0; right:0; top:0; bottom:0; width:auto; height:auto; max-width:none; max-height:none;
      border-radius:0; padding:12px; padding-top:calc(12px + env(safe-area-inset-top));
      padding-bottom:calc(12px + env(safe-area-inset-bottom));
    }
    .dm-thread-view.floating .dm-drag-grip,
    .dm-thread-view.floating #dmFloatResize{ display:none !important; }
    .dm-thread-view.floating #dmThreadHeader{ cursor:default; touch-action:auto; }
  }

  /* ---------- Persistent chat launcher (visible on every screen, incl. calls) ---------- */
  #chatLauncherBtn{
    position:fixed; right:16px; bottom:16px; z-index:9490;
    width:52px; height:52px; border-radius:50%; border:none; cursor:pointer;
    background:var(--cover); color:var(--on-cover); font-size:22px; box-shadow:0 8px 24px rgba(0,0,0,0.3);
    display:none; align-items:center; justify-content:center;
  }
  #chatLauncherBtn.show{ display:flex; }
  /* On phone the bottom nav bar is ~65px tall including its safe-area
     padding — at bottom:16px the chat button was sitting directly on top of
     it, covering the More button. Desktop has no bottom nav in the way, so
     this only needs to move up on narrow screens. */
  @media (max-width:759px){
    #chatLauncherBtn{ bottom:calc(74px + env(safe-area-inset-bottom)); }
    #chatLauncherMenu{ bottom:calc(134px + env(safe-area-inset-bottom)); }
  }
  /* The video call's own control bar occupies the same corner — lift the
     launcher clear of it so it doesn't sit on top of the mic/camera/leave
     buttons during a room. */
  body.in-live-room #chatLauncherBtn{ bottom:calc(84px + env(safe-area-inset-bottom)); }
  body.in-live-room #chatLauncherMenu{ bottom:calc(144px + env(safe-area-inset-bottom)); }
  #chatLauncherBadge{
    position:absolute; top:-2px; right:-2px; min-width:18px; height:18px; padding:0 4px;
    background:#ef4444; color:#fff; border-radius:999px; font-size:10.5px; font-weight:800;
    display:none; align-items:center; justify-content:center; box-shadow:0 0 0 2px var(--card);
  }
  #chatLauncherBadge.show{ display:flex; }
  #chatLauncherMenu{
    position:fixed; right:16px; bottom:76px; z-index:9490; width:280px; max-height:60vh; overflow-y:auto;
    background:var(--card); border-radius:14px; box-shadow:0 16px 50px rgba(0,0,0,0.35); padding:8px;
    display:none;
  }
  #chatLauncherMenu.show{ display:block; }
  #hwTimerBar{
    position:fixed; left:12px; right:12px; z-index:9300;
    top:calc(10px + env(safe-area-inset-top, 0px));
    display:none; align-items:center; gap:10px; padding:10px 12px;
    background:var(--card); border-radius:14px; box-shadow:0 8px 24px rgba(0,0,0,0.18);
    border:1.5px solid var(--gold, #f5b942);
  }
  #hwTimerBar.show{ display:flex; }
  #hwTimerElapsed{ font-variant-numeric:tabular-nums; font-weight:800; font-size:18px; line-height:1.1; }
  #hwTimerPill{
    display:none; position:fixed; right:12px; z-index:9300;
    top:calc(10px + env(safe-area-inset-top, 0px));
    background:var(--card); border:1.5px solid var(--gold, #f5b942); border-radius:999px;
    padding:6px 12px; font-weight:800; font-size:13px; box-shadow:0 6px 18px rgba(0,0,0,0.18);
    font-variant-numeric:tabular-nums; cursor:pointer;
  }
  #hwTimerPill.show{ display:block; }
  /* In the typing tutor the top-right is its own settings/Finish buttons. */
  body.in-type-tutor #hwTimerPill{ top:auto; bottom:calc(12px + env(safe-area-inset-bottom)); }
  .hw-section-head{ font-weight:800; font-size:12px; text-transform:uppercase; letter-spacing:.04em; opacity:.7; margin:16px 2px 2px; }
  .hw-archive-wrap summary{ cursor:pointer; font-weight:800; font-size:12px; text-transform:uppercase; letter-spacing:.04em; opacity:.7; margin:16px 2px 2px; }
  #hwTimerBar.done{ border-color:var(--bad); animation:hwTimerPulse 1.4s ease-in-out infinite; }
  @keyframes hwTimerPulse{ 0%,100%{ box-shadow:0 8px 24px rgba(0,0,0,0.18); } 50%{ box-shadow:0 8px 24px rgba(220,38,38,0.35); } }
  #hwTimerInfo{ flex:1; min-width:0; }
  #hwTimerTitle{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .dm-log{ display:flex; flex-direction:column; gap:8px; padding:4px 2px; min-height:200px; max-height:52vh; overflow-y:auto; }

  /* ---------- TikTok-style bottom nav ---------- */
  body{ padding-bottom:calc(70px + env(safe-area-inset-bottom)); }
  @media (min-width:1600px) and (hover:hover) and (pointer:fine){ body{ padding-bottom:calc(76px * 1.05 + env(safe-area-inset-bottom)); } }
  @media (min-width:1900px) and (hover:hover) and (pointer:fine){ body{ padding-bottom:calc(76px * 1.12 + env(safe-area-inset-bottom)); } }
  @media (min-width:2300px) and (hover:hover) and (pointer:fine){ body{ padding-bottom:calc(76px * 1.26 + env(safe-area-inset-bottom)); } }
  #shCelebrateOverlay{
    display:none; position:fixed; inset:0; background:rgba(0,0,0,0.5); z-index:9750;
    align-items:center; justify-content:center; padding:20px;
  }
  #shCelebrateCard{
    background:var(--card); border-radius:22px; padding:28px 22px; max-width:340px;
    width:100%; text-align:center; font-family:var(--font);
  }
  #shFloatBar{
    display:none; position:fixed; left:8px; right:8px; z-index:8990;
    bottom:calc(64px + env(safe-area-inset-bottom));
    background:var(--cover); color:var(--on-cover); border-radius:16px;
    padding:10px 12px; box-shadow:0 6px 18px rgba(0,0,0,0.25);
    font-family:var(--font);
  }
  #shFloatLabel{
    font-size:10.5px; font-weight:700; opacity:.85; margin-bottom:6px;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  #shFloatBar .skip-btn{
    background:rgba(255,255,255,0.16); color:#fff; border:none; flex:1;
  }
  #shFloatBar .check-btn{
    background:#fff; color:var(--cover); flex:2; font-weight:800;
  }
  #shFloatBar button{ white-space:nowrap; font-size:13px; padding:10px 8px; min-height:44px; margin:0; }
  #shFloatBar .skip-btn{ min-width:0; }

  /* Word browser: tap-to-pick rows */
  .wb-hint{ margin:0 0 8px; font-size:11.5px; opacity:.8; }
  .wb-hint.flash{ animation: wbFlash 1.4s ease; }
  @keyframes wbFlash{ 0%,100%{ background:transparent; } 30%{ background:var(--primary-tint); } }
  .wb-cat-head{ display:flex; align-items:center; justify-content:space-between; gap:8px; margin:12px 0 4px; font-family:var(--font); font-size:12.5px; font-weight:700; color:var(--cover); }
  .wb-cat-head em{ font-style:normal; font-weight:400; opacity:.6; }
  .wb-pick-all{ border:none; background:var(--primary-tint); color:var(--cover); font:700 11px var(--font); padding:5px 11px; border-radius:999px; cursor:pointer; }
  .wb-row{ display:flex; align-items:center; gap:8px; margin:4px 0; padding:6px 8px; border-radius:12px; border:1.5px solid transparent; background:var(--card); cursor:pointer; -webkit-tap-highlight-color:transparent; transition:background .15s, border-color .15s; }
  .wb-row:hover{ border-color:var(--paper-dark); }
  .wb-row.picked{ background:var(--primary-tint); border-color:var(--primary, #4f46e5); }
  .wb-row.hidden-word .wb-text{ opacity:.5; }
  .wb-check{ flex:none; width:22px; height:22px; border-radius:50%; border:2px solid var(--paper-dark); display:flex; align-items:center; justify-content:center; font-size:13px; font-weight:800; color:#fff; }
  .wb-row.picked .wb-check{ background:var(--primary, #4f46e5); border-color:var(--primary, #4f46e5); }
  .wb-say{ padding:5px 9px !important; font-size:13px !important; flex:none; }
  .wb-text{ flex:1; min-width:0; font-family:var(--font); font-size:13px; display:flex; flex-direction:column; line-height:1.25; }
  .wb-text > span{ font-size:12px; opacity:.72; }
  .wb-hidden-tag{ font-style:normal; font-size:10.5px; color:var(--muted-soft); }
  .wb-hide{ flex:none; border:none; background:none; font-size:15px; padding:6px; border-radius:10px; cursor:pointer; opacity:.55; font-family:var(--font); }
  .wb-row.hidden-word .wb-hide{ font-size:11px; font-weight:700; opacity:1; background:var(--paper-dark); color:var(--cover); padding:5px 9px; }
  .wb-hide:hover{ opacity:1; background:var(--paper-dark); }
  #wbPickBar{ position:fixed; left:12px; right:76px; margin:0 auto; max-width:460px; transform:translateY(20px); bottom:calc(84px + env(safe-area-inset-bottom)); z-index:9001; display:flex; align-items:center; gap:6px; padding:7px 7px 7px 14px; border-radius:999px; background:var(--cover, #1e1b4b); color:#fff; box-shadow:0 10px 30px rgba(20,21,43,.28); font-family:var(--font); font-size:13px; opacity:0; pointer-events:none; transition:opacity .2s, transform .2s; white-space:nowrap; }
  #wbPickBar .wb-pb-count{ flex:1; min-width:0; }
  #wbPickBar button{ flex:none; }
  #wbPickBar.show{ opacity:1; pointer-events:auto; transform:translateY(0); }
  /* v224: keep the hidden bar out of the Tab order (opacity:0 alone left three invisible tab stops on every screen) */
  #wbPickBar{ visibility:hidden; transition:opacity .2s, transform .2s, visibility 0s linear .2s; }
  #wbPickBar.show{ visibility:visible; transition-delay:0s; }
  #wbPickBar button{ border:none; border-radius:999px; font:700 12.5px var(--font); cursor:pointer; padding:8px 13px; }
  #wbPickBar .wb-pb-study{ background:#fff; color:var(--cover, #1e1b4b); }
  #wbPickBar .wb-pb-save{ background:rgba(255,255,255,.16); color:#fff; }
  #wbPickBar .wb-pb-clear{ background:none; color:#fff; opacity:.75; padding:8px 9px; }
  body.in-live-room #wbPickBar, body.in-solo-call #wbPickBar{ display:none; }
  #bottomNav{
    position:fixed; left:0; right:0; bottom:0; z-index:9000;
    display:flex; background:var(--card); border-top:1px solid var(--paper-dark);
    padding:7px 6px calc(6px + env(safe-area-inset-bottom));
    box-shadow:0 -4px 20px rgba(20,21,43,0.09);
  }
  .bn-btn{
    flex:1; border:none; background:none; cursor:pointer; padding:6px 2px 5px;
    display:flex; flex-direction:column; align-items:center; gap:4px;
    font-family:var(--font); font-size:11px; font-weight:700; color:var(--muted);
    border-radius:14px; transition:color .18s ease, background .18s ease;
    -webkit-tap-highlight-color:transparent;
  }
  .bn-btn .bn-icon{
    display:flex; align-items:center; justify-content:center; width:26px; height:26px;
    transition:transform .18s ease;
  }
  .bn-btn .bn-icon svg{ width:23px; height:23px; display:block; }
  .bn-btn:active .bn-icon{ transform:scale(0.88); }
  .bn-btn.active{ color:var(--cover); background:var(--paper-dark); }
  .bn-btn.active .bn-icon{ transform:translateY(-1px); }
  /* The middle nav button — elevated above the bar itself, like a camera
     app's shutter button, so it reads as "the one quick action" rather than
     a sixth equal tab. */
  .bn-btn.bn-fab{ position:relative; padding-top:0; }
  .bn-fab-circle{
    position:absolute; left:50%; top:-22px; transform:translateX(-50%);
    width:52px; height:52px; border-radius:50%; background:var(--gold, #f5b942);
    display:flex; align-items:center; justify-content:center;
    box-shadow:0 6px 16px rgba(0,0,0,0.25); border:4px solid var(--card);
  }
  .bn-fab-circle .bn-icon{ width:auto; height:auto; font-size:22px; }
  .bn-btn.bn-fab #navFabLabel{ margin-top:32px; }
  .bn-btn.bn-fab:active .bn-fab-circle{ transform:translateX(-50%) scale(0.92); }
  @media (prefers-reduced-motion: reduce){
    .bn-btn, .bn-btn .bn-icon{ transition:none; }
  }
  #moreSheet{
    position:fixed; inset:0; z-index:9500; display:none;
    background:rgba(20,21,43,0.45); align-items:flex-end;
  }
  #moreSheet.show{ display:flex; }
  #moreSheetPanel{
    width:100%; background:var(--card); border-radius:22px 22px 0 0;
    padding:18px 16px calc(20px + env(safe-area-inset-bottom)); max-height:76vh; overflow-y:auto;
  }
  .ctx-speak{
    border:none; background:var(--paper-dark); cursor:pointer;
    border-radius:50%; width:22px; height:22px; font-size:11px; line-height:1;
    padding:0; vertical-align:middle; margin-left:2px;
  }
  .ctx-speak:active{ transform:scale(0.92); }
  #setupOverlay{
    position:fixed; inset:0; background:rgba(0,0,0,0.45); z-index:9800;
    display:flex; align-items:center; justify-content:center; padding:16px;
  }
  #setupSheet{
    background:var(--card); border-radius:20px; padding:20px 18px 18px;
    max-width:440px; width:100%; max-height:88dvh; overflow-y:auto;
    font-family:var(--font);
  }
  #setupSheet .su-title{ font-size:21px; font-weight:800; color:var(--ink); }
  #setupSheet .su-sub{ font-size:13.5px; color:var(--muted); margin:4px 0 14px; }
  #setupSheet .su-q{ font-size:13px; font-weight:800; color:var(--ink); margin:14px 0 6px; }
  #setupSheet .su-opts{ display:flex; flex-wrap:wrap; gap:6px; }
  #setupSheet .su-opts button{
    flex:1 1 30%; min-width:96px; border:1.5px solid var(--paper-dark); background:var(--paper);
    color:var(--ink); border-radius:12px; padding:10px 8px; min-height:48px; font-family:var(--font);
    font-weight:800; font-size:13.5px; cursor:pointer; text-align:center; line-height:1.25;
  }
  #setupSheet .su-opts button span{
    display:block; font-weight:600; font-size:12px; color:var(--muted); margin-top:2px;
  }
  #setupSheet .su-opts button.on{ background:var(--cover); border-color:transparent; color:var(--on-cover); }
  #setupSheet .su-opts button.on span{ color:var(--on-cover); opacity:.92; }
  #setupSheet .su-note{ font-size:12px; color:var(--muted); margin-top:6px; min-height:14px; }
  .nav-order{
    display:flex; gap:6px; margin:12px 0 4px; align-items:stretch;
  }
  .nav-order .no-item{
    flex:1; display:flex; flex-direction:column; align-items:center; gap:3px;
    padding:8px 2px 6px; border:1.5px solid var(--paper-dark); border-radius:12px;
    background:var(--paper); font-family:var(--font); font-size:10px; font-weight:800;
    color:var(--ink); text-align:center;
    /* Without this the sheet scrolls instead of the chip moving. */
    touch-action:none;
  }
  .nav-order .no-item.dragging{ opacity:.55; border-color:var(--cover); }
  .nav-order .no-ico{ font-size:17px; line-height:1; }
  .nav-order .no-arrows{ display:flex; gap:3px; margin-top:2px; }
  .nav-order .no-arrows button{
    border:none; background:var(--paper-dark); color:var(--ink);
    border-radius:8px; font-size:15px; line-height:1; width:32px; height:32px; padding:0; cursor:pointer;
  }
  .nav-order .no-arrows button:disabled{ opacity:.3; cursor:default; }
  .nav-order-note{
    font-family:var(--font); font-size:10.5px; color:var(--muted);
    text-align:center; margin:0 0 6px;
  }
  .more-grid{ display:flex; flex-direction:column; gap:8px; margin-top:12px; }
  .more-group{ border:1px solid var(--paper-dark); border-radius:var(--radius-sm); overflow:hidden; }
  .more-group-header{
    display:flex; align-items:center; gap:8px; cursor:pointer; list-style:none;
    font-family:var(--font); font-size:12.5px; font-weight:800; color:var(--ink);
    padding:12px 14px; user-select:none;
  }
  .more-group-header::-webkit-details-marker{ display:none; }
  .more-group-header::before{
    content:'▸'; display:inline-block; color:var(--muted); font-size:11px;
    transition:transform .15s ease; flex-shrink:0;
  }
  .more-group[open] > .more-group-header::before{ transform:rotate(90deg); }
  .more-group-count{
    margin-left:auto; font-size:10.5px; font-weight:700; color:var(--muted);
    background:var(--paper-dark); border-radius:999px; padding:1px 7px;
  }
  .more-group-tiles{
    display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px;
    padding:0 12px 12px;
  }
  @media (min-width:760px){ .more-group-tiles{ grid-template-columns:repeat(4,1fr); } }
  .more-item{
    border:1px solid var(--paper-dark); background:var(--paper); border-radius:var(--radius-sm);
    padding:14px 8px; cursor:pointer; font-family:var(--font); font-weight:700; font-size:11.5px;
    color:var(--ink); display:flex; flex-direction:column; align-items:center; gap:6px; text-align:center;
  }
  .more-item.featured{ border:1.5px solid var(--cover); }
  .more-item .more-icon{ font-size:21px; }
  .more-item.active{ border-color:var(--cover); color:var(--cover); }

  /* ---------- Practice sub-nav: all four fit, no scrolling ---------- */
  .pr-pill-row{ display:grid; grid-template-columns:repeat(4,1fr); gap:6px; overflow:visible; padding:2px 0 6px; margin:14px 0 4px; }
  .pr-pill-row.hidden{ display:none; }
  .pr-pill{
    width:100%; flex:none; display:flex; flex-direction:column; align-items:center; gap:3px;
    border:1.5px solid var(--paper-dark); background:var(--paper); color:var(--ink);
    border-radius:14px; padding:9px 4px; font-family:var(--font); font-weight:700; font-size:11px;
    cursor:pointer; white-space:nowrap; text-align:center; position:relative;
    transition:border-color .15s ease, background .15s ease, color .15s ease, transform .1s ease;
  }
  .friends-entry-dot{
    position:absolute; top:2px; right:6px; min-width:16px; height:16px; padding:0 3px;
    background:#22c55e; color:#fff; border-radius:999px; font-size:9.5px; font-weight:800;
    display:flex; align-items:center; justify-content:center; line-height:1;
    box-shadow:0 0 0 2px var(--paper);
  }
  .pr-pill .pr-pill-emoji{ font-size:17px; line-height:1; }
  .pr-pill .pr-pill-dot{ display:none; }

  /* ---------- Room chat: chat-app layout ---------- */
  .room-chat-panel{
    position:fixed; left:0; right:0; bottom:0; z-index:9200;
    background:var(--card); border-radius:18px 18px 0 0; box-shadow:0 -8px 28px rgba(20,21,43,0.18);
    display:none; flex-direction:column; max-height:72vh;
  }
  .room-chat-panel.show{ display:flex; }
  @media (min-width:760px){
    .room-chat-panel:not(.floating){ left:auto; right:24px; bottom:24px; width:360px; border-radius:16px; max-height:60vh; }
  }
  .room-chat-panel.floating{ left:auto; right:auto; bottom:auto; border-radius:16px; max-height:none; box-shadow:0 14px 40px rgba(0,0,0,0.4); }
  .room-chat-panel .study-resize-handle{ display:block; }
  .room-chat-head{
    display:flex; align-items:center; gap:6px; padding:12px 14px 8px; border-bottom:1px solid var(--paper-dark);
    flex-wrap:wrap; cursor:grab; touch-action:none;
  }
  .room-chat-panel.floating .room-chat-head{ cursor:grabbing; }
  .room-chat-tab{
    border:none; background:none; font-family:var(--font); font-weight:800; font-size:13px;
    color:var(--muted); cursor:pointer; padding:5px 10px; border-radius:999px; flex-shrink:0; white-space:nowrap;
  }
  .room-chat-tab.active{ background:var(--paper-dark); color:var(--ink); }
  .room-chat-body{ flex:1; overflow-y:auto; padding:10px 12px; min-height:180px; }
  .room-chat-foot{
    display:flex; gap:8px; padding:10px 12px calc(12px + env(safe-area-inset-bottom));
    border-top:1px solid var(--paper-dark); background:var(--card);
  }
  .msg-group{ display:flex; gap:9px; margin-bottom:12px; }
  .msg-group.mine{ flex-direction:row-reverse; }
  .msg-avatar{ flex-shrink:0; width:32px; }
  .msg-content{ min-width:0; flex:1; }
  .msg-group.mine .msg-content{ display:flex; flex-direction:column; align-items:flex-end; }
  .msg-meta{ display:flex; align-items:baseline; gap:6px; margin-bottom:3px; }
  .msg-author{ font-weight:800; font-size:12.5px; color:var(--ink); cursor:pointer; }
  .msg-time{ font-size:10px; color:var(--muted-soft); }
  .msg-line{
    background:var(--paper-dark); color:var(--ink); padding:7px 11px; border-radius:14px;
    font-size:13.5px; line-height:1.4; margin-top:3px; display:inline-block; max-width:100%;
    word-break:break-word; text-align:left;
  }
  .msg-group.mine .msg-line{ background:var(--cover); color:var(--on-cover); }
  .msg-system{ text-align:center; font-size:11.5px; color:var(--muted-soft); margin:8px 0; }

  /* ---------- Participant roster ---------- */
  .roster-row{
    display:flex; align-items:center; gap:10px; padding:9px 4px; cursor:pointer;
    border-bottom:1px solid var(--paper-dark);
  }
  .roster-name{ font-weight:700; font-size:13.5px; color:var(--ink); }
  .roster-tag{
    font-size:10px; font-weight:800; padding:2px 7px; border-radius:999px;
    background:var(--paper-dark); color:var(--muted);
  }
  .roster-tag.host{ background:var(--cover); color:var(--on-cover); }
  /* Floating room actions share one row, so they can't stack on top of
     each other the way two separately-positioned fixed buttons did. */
  #roomFloatBar{
    position:fixed; right:12px; left:12px; bottom:calc(78px + env(safe-area-inset-bottom));
    z-index:9100; display:flex; justify-content:flex-end; gap:8px; pointer-events:none;
  }
  body.in-live-room #roomFloatBar{ bottom:calc(72px + env(safe-area-inset-bottom)); }
  #roomFloatBar > button{
    pointer-events:auto; display:none; align-items:center; gap:6px; border:none; cursor:pointer;
    color:#fff; border-radius:999px; padding:10px 15px; font-family:var(--font);
    font-weight:800; font-size:12.5px; white-space:nowrap; flex:0 0 auto;
    box-shadow:0 4px 14px rgba(0,0,0,0.28);
  }
  #roomFloatBar > button.show{ display:flex; }
  /* Never clip a button off the left edge on narrow phones (longer Vietnamese
     labels made that happen) — wrap to a second row instead. */
  #roomFloatBar{ flex-wrap:wrap; row-gap:6px; }
  html[data-ui-lang="vi"] #roomFloatBar > button{ padding:10px 12px; gap:5px; }
  #roomChatToggle{ background:var(--cover); }
  #studyToggle{ background:var(--stamp); }

  /* ---------- Immersive (TikTok-style) live room ---------- */
  body.in-live-room{ background:#000; }
  body.in-live-room #bottomNav,
  body.in-live-room footer,
  body.in-live-room .page > .content > #teacherAdBanner{ display:none !important; }

  /* ---------- Gõ Chữ typing tutor — full takeover, same idea as the live
     room above: its own separate page (own footer, own chrome) needs the
     parent's own nav out of the way entirely rather than stacked under it.
     goToTab() still just sets #tab-type's own display:block/none as usual;
     this only changes what "shown" looks like, gated on the body class
     rather than trying to sniff the inline style string it sets. */
  body.in-type-tutor #bottomNav{ display:none !important; }
  /* The floating chat bubble covered the typing tutor's controls. */
  body.in-type-tutor #chatLauncherBtn{ display:none !important; }
  body.in-type-tutor #tab-type{
    display:flex !important; position:fixed; inset:0; z-index:8800;
    background:var(--card); flex-direction:column; padding:0 !important;
  }
  .type-tutor-topbar{
    display:flex; align-items:center; gap:10px; padding:12px 14px calc(10px + env(safe-area-inset-bottom, 0px));
    padding-top:calc(12px + env(safe-area-inset-top, 0px));
    border-bottom:1px solid var(--paper-dark); flex-shrink:0;
  }
  #typeTutorFrame{ flex:1; min-height:0; }
  .live-shell{
    position:fixed; inset:0; z-index:8800; background:#000; display:none;
    flex-direction:column; color:#fff;
  }
  .live-shell.show{ display:flex; }
  /* ---------- Minimized call — shrinks the same shell into a small floating
     window instead of tearing anything down, so the WebRTC connection, chat,
     everything just keeps running underneath while the rest of the app
     becomes reachable again. Only #liveShell (group rooms) supports this —
     Go Live's broadcast shells are a different, audience-facing use case. ---------- */
  #liveShell.minimized{
    inset:auto; left:16px; top:auto; right:auto; bottom:calc(16px + env(safe-area-inset-bottom, 0px));
    width:200px; height:230px; border-radius:16px; overflow:hidden;
    box-shadow:0 14px 40px rgba(0,0,0,0.5); z-index:9350;
  }
  #liveShell.minimized .live-topbar,
  #liveShell.minimized .live-bottombar,
  #liveShell.minimized .live-captions,
  #liveShell.minimized .live-chat-feed,
  #liveShell.minimized .live-stage-handle,
  #liveShell.minimized .live-stage-resize,
  #liveShell.minimized #liveReactLayer,
  #liveShell.minimized #hostKnockPanel{ display:none !important; }
  #liveShell.minimized .live-stage{ padding:0; height:100%; }
  #liveShell.minimized .live-tiles{ height:100%; }
  .live-mini-bar{
    display:none; position:absolute; left:0; right:0; bottom:0; z-index:2;
    align-items:center; gap:6px; padding:6px 8px;
    background:linear-gradient(to top, rgba(0,0,0,0.75), rgba(0,0,0,0));
  }
  #liveShell.minimized .live-mini-bar{ display:flex; }
  .live-mini-btn{
    border:none; background:rgba(255,255,255,0.18); color:#fff; border-radius:8px;
    width:28px; height:28px; font-size:13px; cursor:pointer; flex-shrink:0;
  }
  .live-mini-btn.live-mini-leave{ background:rgba(220,38,38,0.85); }
  .live-mini-status{ flex:1; font-size:10.5px; font-weight:800; text-align:center; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* ---------- Minimized 1:1 call — same "keep the call running while the
     rest of the app becomes reachable" idea as the group room's minimize
     button above. The wrinkle: #practiceRoomView normally lives inside the
     Practice tab's own panel, so goToTab() sets it to display:none the
     instant you switch tabs. These two rules keep it — and only it — on
     screen no matter which tab is actually showing underneath, which is what
     makes a small camera PiP possible while browsing/sharing another tab's
     content in this same browser tab. ---------- */
  body.solo-pip-mode #tab-practice{ display:block !important; }
  body.solo-pip-mode #tab-practice > *:not(#practiceRoomView){ display:none !important; }
  #practiceRoomView.pip-mode{
    position:fixed !important; inset:auto !important; margin:0 !important;
    left:16px; top:auto; right:auto; bottom:calc(16px + env(safe-area-inset-bottom, 0px));
    width:170px; height:210px; border-radius:16px; overflow:hidden;
    box-shadow:0 14px 40px rgba(0,0,0,0.5); z-index:9350; cursor:pointer;
  }
  #practiceRoomView.pip-mode #practiceCallStage{ border-radius:16px !important; }
  #practiceRoomView.pip-mode .solo-controls,
  #practiceRoomView.pip-mode .solo-prompt,
  #practiceRoomView.pip-mode #promptReopen,
  #practiceRoomView.pip-mode #soloRestoreBtn,
  #practiceRoomView.pip-mode .solo-util,
  #practiceRoomView.pip-mode #practiceCallTimer,
  #practiceRoomView.pip-mode #lessonFocusBadge{ display:none !important; }
  #practiceRoomView.pip-mode .solo-topbar{ padding:6px 8px; }
  #practiceRoomView.pip-mode #practicePeerLabel{ font-size:10.5px; }
  #practiceRoomView.pip-mode #practiceLocalVideo{ width:46px !important; height:64px !important; pointer-events:none; }
  .pip-mini-bar{
    display:none; position:absolute; left:0; right:0; bottom:0; z-index:2;
    align-items:center; gap:6px; padding:6px 8px;
    background:linear-gradient(to top, rgba(0,0,0,0.75), rgba(0,0,0,0));
  }
  #practiceRoomView.pip-mode .pip-mini-bar{ display:flex; }
  .live-topbar{
    display:flex; align-items:center; gap:9px; padding:calc(8px + env(safe-area-inset-top)) 12px 8px;
    background:linear-gradient(to bottom, rgba(0,0,0,0.7), rgba(0,0,0,0));
  }
  .live-host-chip{
    display:flex; align-items:center; gap:8px; background:rgba(255,255,255,0.14);
    border-radius:999px; padding:5px 12px 5px 5px; backdrop-filter:blur(6px); min-width:0;
  }
  .live-host-name{ font-weight:800; font-size:13px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:130px; }
  .live-host-sub{ font-size:10.5px; opacity:.75; }
  .live-count-chip{
    display:flex; align-items:center; gap:5px; background:rgba(255,255,255,0.14);
    border-radius:999px; padding:6px 12px; font-weight:800; font-size:12.5px; backdrop-filter:blur(6px);
  }
  .live-x{
    margin-left:auto; border:none; background:rgba(255,255,255,0.14); color:#fff;
    width:40px; height:40px; border-radius:999px; font-size:16px; cursor:pointer; flex-shrink:0;
  }
  .live-stage{ flex:1; min-height:0; overflow:hidden; padding:4px 8px; display:flex; flex-direction:column; position:relative; }
  /* Desktop only — on phone the full-bleed video is already right and this
     stays off. A small grip strip appears above the tiles; drag it to pop
     the video into its own floating, resizable window, same behavior as
     the study panel / whiteboard / chat box. */
  .live-stage-handle{ display:none; }
  @media (min-width:760px){
    .live-stage-handle{
      display:flex; align-items:center; gap:8px; flex-shrink:0; padding:2px 4px 6px;
      cursor:grab; touch-action:none; color:rgba(255,255,255,0.6); font-size:11.5px; font-weight:800;
    }
    .live-stage-handle .study-grip{ color:rgba(255,255,255,0.6); }
    .live-stage-handle button{
      margin-left:auto; border:none; background:rgba(255,255,255,0.14); color:#fff;
      border-radius:8px; padding:3px 8px; font-size:10.5px; font-weight:800; cursor:pointer; display:none;
    }
    .live-stage.floating .live-stage-handle button{ display:inline-flex; }
    .live-stage.floating .live-stage-handle{ cursor:grabbing; }
  }
  .live-stage.floating{
    position:fixed !important; z-index:8820; padding:6px;
    background:#000; border-radius:14px; box-shadow:0 16px 50px rgba(0,0,0,0.6);
    flex:none !important;
  }
  .live-stage.floating .live-tiles{ min-height:60px; }
  .live-topbar, .live-bottombar{ position:relative; z-index:8830; }
  .live-stage-resize{ display:none; }
  .live-stage.floating .live-stage-resize{
    display:block; position:absolute; right:6px; bottom:6px; width:20px; height:20px; cursor:nwse-resize; z-index:2;
    background: linear-gradient(135deg, transparent 0 42%, rgba(255,255,255,0.5) 42% 48%, transparent 48% 62%, rgba(255,255,255,0.5) 62% 68%, transparent 68%);
  }
  .live-tiles{
    display:grid; gap:4px; flex:1; min-height:0;
    grid-auto-rows:1fr;      /* every row shares the stage height equally */
  }
  .live-tile{
    position:relative; background:#111; border-radius:10px; overflow:hidden; min-height:0;
  }
  /* One person on screen keeps a portrait-ish frame; grids fill the space. */
  .live-tiles.solo .live-tile{ aspect-ratio:3/4; align-self:center; }
  /* Exactly two people: give each tile its own sane aspect ratio instead of
     stretching to fill whatever raw shape the grid math leaves — that's what
     was cropping faces down to a strip of mouth (wide desktop, stacked into
     two short rows) or a strip of forehead (narrow phone, side-by-side into
     two skinny columns). Capping it here fixes both directions at once,
     whether the grid stacked or went side-by-side, and whether that came
     from the default layout or someone's manual layout pick. */
  .live-tiles.pair .live-tile{ aspect-ratio:3/4; align-self:center; justify-self:center; width:100%; max-height:100%; }
  .live-tile.speaking{ outline:2.5px solid #2dd4bf; outline-offset:-2px; }
  .live-tile video{ width:100%; height:100%; object-fit:cover; display:block; }
  .live-tile-name{
    position:absolute; left:6px; bottom:6px; display:flex; align-items:center; gap:5px;
    background:rgba(0,0,0,0.55); border-radius:999px; padding:3px 9px;
    font-size:11px; font-weight:700; max-width:calc(100% - 12px);
  }
  .live-tile-name span{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .live-tile-badge{
    position:absolute; left:6px; top:6px; background:rgba(0,0,0,0.5);
    border-radius:999px; padding:3px 8px; font-size:10px; font-weight:800;
  }
  .live-tile-badge.host{ background:#f59e0b; color:#1a1206; }
  .live-tile-reconnect{
    position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
    background:rgba(0,0,0,0.55); color:#fff; font-size:12px; font-weight:800; z-index:1; text-align:center;
  }
  .live-tile-menu{
    position:absolute; right:5px; top:5px; border:none; background:rgba(0,0,0,0.5); color:#fff;
    width:24px; height:24px; border-radius:8px; font-size:12px; cursor:pointer;
  }
  .live-tile-muted{ position:absolute; right:6px; bottom:6px; font-size:12px; opacity:.9; }
  /* ---------- Focus a tile — expand one person's (or the screen share's)
     tile to fill the stage; everyone else becomes a small strip so they're
     still visible, just not equally sized. ---------- */
  .live-tile-focus-btn{
    position:absolute; left:5px; top:5px; border:none; background:rgba(0,0,0,0.5); color:#fff;
    width:32px; height:32px; border-radius:8px; font-size:13px; cursor:pointer; z-index:2;
  }
  .live-tiles.has-focus{
    display:flex !important; flex-direction:column; gap:6px; height:100%;
  }
  .live-tiles.has-focus .live-tile{ flex-shrink:0; }
  .live-tiles.has-focus .live-tile.is-focused{ flex:1; min-height:0; order:-1; }
  .live-tiles.has-focus .live-tile:not(.is-focused){
    flex:0 0 auto; height:72px; width:96px;
  }
  .live-tiles.has-focus{ flex-direction:column; }
  @media (min-width:600px){
    .live-tiles.has-focus{ flex-direction:row; flex-wrap:wrap; align-content:flex-start; }
    .live-tiles.has-focus .live-tile.is-focused{ width:100%; flex-basis:100%; }
  }
  .go-live-vis-btn.active{ border-color:#fff; background:rgba(255,255,255,.15); }
  .go-live-badge{
    display:inline-block; background:#e11d48; color:#fff; font-size:10px; font-weight:800;
    letter-spacing:.03em; padding:1px 6px; border-radius:4px; vertical-align:middle; margin-right:4px;
  }
  .go-live-hearts{ position:absolute; inset:0; pointer-events:none; overflow:hidden; }
  .pr-online-row{
    display:flex; align-items:center; justify-content:space-between; gap:10px;
    padding:8px 4px; border-bottom:1px solid var(--line); font-family:var(--font); font-size:13px;
  }
  .pr-online-row:last-child{ border-bottom:none; }
  .go-live-heart{
    position:absolute; bottom:60px; font-size:26px; opacity:0;
    animation: goLiveHeartFloat 2.2s ease-out forwards;
  }
  @keyframes goLiveHeartFloat{
    0%{ opacity:1; transform:translateY(0) scale(0.8); }
    15%{ transform:translateY(-20px) scale(1.1); }
    100%{ opacity:0; transform:translateY(-260px) scale(1) translateX(var(--heart-drift, 0px)); }
  }

  /* Audio-mode tile: avatar with a ring that pulses to the person's voice */
  .live-tile.audio-mode{ aspect-ratio:1/1; background:#15161f; display:flex; align-items:center; justify-content:center; }
  .voice-ring{ position:relative; display:flex; align-items:center; justify-content:center; }
  .voice-ring .vr-pulse{
    position:absolute; inset:-8px; border-radius:50%; border:2.5px solid #2dd4bf;
    opacity:0; transform:scale(0.9); transition:transform .09s linear, opacity .18s linear;
  }
  .voice-ring .vr-pulse.b{ inset:-16px; border-color:rgba(45,212,191,0.45); }
  .live-mic-meter{
    position:absolute; right:6px; bottom:6px; display:flex; align-items:flex-end; gap:2px; height:14px;
  }
  .live-mic-meter i{
    width:3px; background:#2dd4bf; border-radius:2px; height:3px; display:block;
    transition:height .08s linear; opacity:.9;
  }

  .live-chat-feed{
    padding:0 10px 6px; max-height:34vh; overflow-y:auto;
    -webkit-mask-image:linear-gradient(to bottom, transparent, #000 22px);
            mask-image:linear-gradient(to bottom, transparent, #000 22px);
  }
  .live-msg{ display:flex; gap:7px; margin-top:7px; align-items:flex-start; }
  .live-msg-body{
    background:rgba(0,0,0,0.42); border-radius:14px; padding:6px 11px; font-size:13px;
    line-height:1.38; max-width:88%; backdrop-filter:blur(3px);
  }
  .live-msg-author{ font-weight:800; font-size:12px; opacity:.85; margin-right:5px; cursor:pointer; }
  .live-msg.system .live-msg-body{ background:rgba(255,255,255,0.1); font-size:12px; opacity:.85; }
  .live-bottombar{
    display:flex; align-items:center; gap:8px; padding:8px 10px calc(10px + env(safe-area-inset-bottom));
    background:linear-gradient(to top, rgba(0,0,0,0.85), rgba(0,0,0,0));
  }
  .live-input{
    flex:1; min-width:0; border:none; border-radius:999px; padding:11px 16px;
    background:rgba(255,255,255,0.15); color:#fff; font-family:var(--font); font-size:13.5px;
    backdrop-filter:blur(6px);
  }
  .live-input::placeholder{ color:rgba(255,255,255,0.6); }
  .live-hands{
    margin:0 12px 6px; padding:8px 10px; border-radius:14px;
    background:rgba(12,12,22,0.78); backdrop-filter:blur(8px);
    font-family:var(--font); color:#fff; max-height:26vh; overflow-y:auto;
  }
  .live-hands .lh-title{ font-size:11px; font-weight:800; opacity:0.75; letter-spacing:0.3px; text-transform:uppercase; }
  .live-hands .lh-row{ display:flex; align-items:center; justify-content:space-between; gap:8px; margin-top:6px; }
  .live-hands .lh-name{ flex:1; min-width:0; font-size:13px; font-weight:700; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .live-hands button{
    flex-shrink:0; border:none; background:#fff; color:#111; font-family:var(--font);
    font-size:12px; font-weight:700; padding:7px 13px; border-radius:999px; cursor:pointer;
    min-height:34px;
  }
  .live-act{
    border:none; background:rgba(255,255,255,0.15); color:#fff; width:40px; height:40px;
    border-radius:999px; font-size:16px; cursor:pointer; flex-shrink:0; backdrop-filter:blur(6px);
  }
  .live-act.on{ background:#fff; color:#111; }
  .live-act.danger{ background:var(--bad); }

  /* ---------- Synced study session (practice the app together) ---------- */
  .study-panel{
    position:fixed; left:0; right:0; bottom:0; z-index:9300;
    background:var(--card); border-radius:20px 20px 0 0; box-shadow:0 -8px 30px rgba(20,21,43,0.22);
    display:none; flex-direction:column; max-height:82vh; color:var(--ink);
  }
  .study-panel.show{ display:flex; }
  /* Docked (not yet dragged/resized) on a wide screen: a full edge-to-edge
     sheet looks stretched and buries the card in whitespace on either side —
     cap it like any other centered panel until the person actually moves it. */
  @media (min-width:760px){
    .study-panel:not(.floating){ left:auto; right:24px; bottom:24px; width:400px; border-radius:16px; }
  }
  /* Dragged or resized at least once — switch from the docked bottom sheet
     to a freely positioned floating window (explicit left/top/width/height
     set by JS), so it can be moved clear of whoever you're video-calling. */
  .study-panel.floating{
    left:auto; right:auto; bottom:auto; border-radius:16px; max-height:none;
    box-shadow:0 14px 40px rgba(0,0,0,0.4);
  }
  .study-resize-handle{
    display:none; position:absolute; right:2px; bottom:2px; width:22px; height:22px; cursor:nwse-resize;
    background:
      linear-gradient(135deg, transparent 0 42%, var(--muted) 42% 48%, transparent 48% 62%, var(--muted) 62% 68%, transparent 68%);
    opacity:.55; z-index:2;
  }
  /* Available the moment the panel is open, not only after a drag has
     already happened — it used to be gated behind .floating, which meant
     resize was invisible and effectively broken until you'd dragged first. */
  .study-panel.show .study-resize-handle{ display:block; }
  #studyDock{ display:none; }
  .study-panel.floating #studyDock{ display:inline-flex; }
  .study-grip{ font-size:13px; color:var(--muted); line-height:1; user-select:none; flex-shrink:0; }
  .study-head{
    display:flex; align-items:center; gap:8px; padding:12px 14px 10px;
    border-bottom:1px solid var(--paper-dark); cursor:grab; touch-action:none; flex-wrap:wrap;
  }
  .study-panel.floating .study-head{ cursor:grabbing; }

  /* ---------- Waiting room ---------- */
  .host-knock-panel{
    position:fixed; z-index:9400; top:calc(64px + env(safe-area-inset-top)); right:12px;
    display:flex; flex-direction:column; gap:8px; max-width:280px;
  }
  .host-knock-card{
    background:rgba(20,20,30,0.94); backdrop-filter:blur(8px); color:#fff;
    border-radius:12px; padding:10px 12px; font-family:var(--font); box-shadow:0 8px 24px rgba(0,0,0,0.35);
  }
  .host-knock-name{ font-weight:800; font-size:13.5px; margin-bottom:6px; }
  .host-knock-actions{ display:flex; gap:6px; }
  .host-knock-actions button{
    flex:1; border:none; border-radius:8px; padding:6px 0; font-weight:800; font-size:12.5px; cursor:pointer; font-family:var(--font);
  }
  .host-knock-admit{ background:#16a34a; color:#fff; }
  .host-knock-deny{ background:rgba(255,255,255,0.15); color:#fff; }

  /* ---------- "More" menu (call controls that aren't self-explanatory
     as bare icons — mic/camera/people/leave stay in the main bar since
     those four are universal; everything else gets a real label here) ---- */
  .live-more-menu{
    position:fixed; z-index:9400; display:none; flex-direction:column;
    right:12px; bottom:calc(64px + env(safe-area-inset-bottom));
    background:rgba(20,20,30,0.94); backdrop-filter:blur(10px); border-radius:14px;
    padding:6px; min-width:230px; box-shadow:0 14px 40px rgba(0,0,0,0.4);
  }
  .live-more-menu.show{ display:flex; }
  .live-more-item{
    display:flex; align-items:center; gap:10px; border:none; background:none; color:#fff;
    text-align:left; padding:10px 10px; border-radius:9px; font-family:var(--font); font-size:13.5px;
    font-weight:700; cursor:pointer; width:100%;
  }
  .live-more-item:active{ background:rgba(255,255,255,0.1); }
  .live-more-item.on{ background:rgba(255,255,255,0.14); }
  .live-more-item .lmi-icon{ font-size:16px; width:22px; text-align:center; flex-shrink:0; }
  .live-more-item .lmi-hint{ margin-left:auto; font-weight:500; font-size:11px; opacity:.6; }
  .live-more-item#liveCaptionsLangBtn{ padding-left:20px; font-weight:500; font-size:12.5px; }
  .live-more-item#liveMuteAllBtn{ color:#ffb4b4; }

  /* ---------- Reactions ---------- */
  .live-react-bar{
    position:fixed; z-index:9400; display:none; gap:4px; padding:6px 8px; border-radius:999px;
    background:rgba(20,20,30,0.9); backdrop-filter:blur(8px);
    right:12px; bottom:calc(74px + env(safe-area-inset-bottom));
  }
  .live-react-bar.show{ display:flex; }
  .live-react-bar button{ border:none; background:none; font-size:24px; cursor:pointer; padding:2px 4px; min-width:44px; min-height:40px; border-radius:8px; }
  .live-react-bar button:active{ background:rgba(255,255,255,0.15); }
  .live-react-layer{ position:fixed; inset:0; pointer-events:none; z-index:9390; overflow:hidden; }
  .live-react-float{ position:absolute; bottom:90px; font-size:34px; text-align:center; animation:reactUp 2.6s ease-out forwards; }
  .live-react-float small{ display:block; font-size:10.5px; font-weight:800; color:#fff; background:rgba(0,0,0,0.55); border-radius:999px; padding:1px 6px; margin-top:2px; }
  @keyframes reactUp{ 0%{ transform:translateY(0) scale(.6); opacity:0; } 12%{ opacity:1; transform:translateY(-20px) scale(1.1); } 100%{ transform:translateY(-360px) scale(1); opacity:0; } }
  body.mirror-self .live-tile video.is-self{ transform:scaleX(-1); }
  body.mirror-self .live-tile video.is-self.is-screen{ transform:none; }

  /* ---------- Live translated captions ---------- */
  .live-captions{
    display:flex; flex-direction:column; gap:4px; padding:0 12px 6px; pointer-events:none;
  }
  .live-caption-line{
    align-self:flex-start; max-width:88%; background:rgba(0,0,0,0.68); color:#fff;
    border-radius:10px; padding:6px 10px; font-size:13.5px; line-height:1.35;
    animation:capFade 6s ease-out forwards;
  }
  .live-caption-line .cap-translated{ font-size:13px; margin-top:3px; color:#bfe3ff; font-weight:600; }
  .live-caption-line b{ font-weight:800; }
  @keyframes capFade{ 0%,80%{ opacity:1; } 100%{ opacity:0; } }

  /* ---------- Shared whiteboard ---------- */
  .wb-panel{
    position:fixed; z-index:9350; display:none; flex-direction:column;
    background:var(--card); color:var(--ink); border-radius:16px;
    box-shadow:0 14px 40px rgba(0,0,0,0.4); overflow:hidden;
    left:50%; top:50%; transform:translate(-50%,-50%);
    width:min(520px, calc(100vw - 24px)); height:min(420px, calc(100vh - 120px));
  }
  .wb-panel.show{ display:flex; }
  .wb-panel.positioned{ transform:none; }
  .wb-head{
    display:flex; align-items:center; gap:8px; padding:8px 10px;
    border-bottom:1px solid var(--paper-dark); cursor:grab; touch-action:none; flex-shrink:0;
    flex-wrap:wrap;
  }
  .wb-tools{ display:flex; align-items:center; gap:5px; margin-left:auto; flex-shrink:0; flex-wrap:wrap; }
  .wb-color{ width:22px; height:22px; border-radius:50%; border:2px solid transparent; cursor:pointer; padding:0; flex-shrink:0; }
  .wb-color.active{ border-color:var(--ink); box-shadow:0 0 0 2px var(--card); }
  .wb-tool{
    border:none; background:var(--paper-dark); color:var(--ink); border-radius:8px;
    width:30px; height:28px; font-size:13px; cursor:pointer; flex-shrink:0; font-family:var(--font);
  }
  .wb-tool.active{ background:var(--cover); color:var(--on-cover); }
  .wb-body{ flex:1; min-height:0; background:#fff; position:relative; }
  #wbCanvas{ width:100%; height:100%; display:block; touch-action:none; cursor:crosshair; }
  .wb-body.text-mode #wbCanvas{ cursor:text; }
  .wb-text-input{
    position:absolute; z-index:3; min-width:140px; max-width:80%; min-height:1.6em;
    border:2px dashed var(--cover); background:rgba(255,255,255,0.96); border-radius:6px;
    padding:4px 6px; font-family:var(--font); line-height:1.35; resize:both; outline:none;
  }
  body.dark-mode .wb-body{ background:#fafafa; }
  .wb-pointer-layer{ position:absolute; inset:0; pointer-events:none; z-index:4; overflow:hidden; }
  .wb-pointer{
    position:absolute; transform:translate(-3px,-3px); transition:left .08s linear, top .08s linear;
    opacity:0; will-change:left,top,opacity;
  }
  .wb-pointer.show{ opacity:1; }
  .wb-pointer .dot{ width:12px; height:12px; border-radius:50%; box-shadow:0 0 0 2px #fff; }
  .wb-pointer .lbl{
    position:absolute; left:14px; top:-4px; white-space:nowrap; color:#fff; font-size:10.5px; font-weight:800;
    padding:2px 6px; border-radius:6px;
  }
  .study-title{ font-weight:800; font-size:14.5px; }
  .study-sub{ font-size:11.5px; color:var(--muted); }
  .study-body{ flex:1; overflow-y:auto; padding:14px; }
  .study-card{
    background:var(--paper); border:1px solid var(--paper-dark); border-radius:var(--radius-sm);
    padding:30px 18px; text-align:center; cursor:pointer; user-select:none; min-height:150px;
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px;
  }
  .study-card-vn{ font-size:calc(26px * var(--flash-scale, 1)); font-weight:800; line-height:1.25; }
  .study-card-en{ font-size:calc(17px * var(--flash-scale, 1)); color:var(--cover); font-weight:700; }
  .study-card-hint{ font-size:11.5px; color:var(--muted-soft); letter-spacing:.04em; text-transform:uppercase; }
  .study-card-cat{
    font-size:10.5px; font-weight:800; color:var(--muted); background:var(--paper-dark);
    border-radius:999px; padding:3px 10px;
  }
  .study-progress{ display:flex; align-items:center; gap:8px; margin-top:12px; font-size:12px; color:var(--muted); }
  .study-bar{ flex:1; height:6px; background:var(--paper-dark); border-radius:999px; overflow:hidden; }
  .study-bar i{ display:block; height:100%; background:var(--cover); border-radius:999px; transition:width .25s ease; }
  .study-foot{
    display:flex; gap:8px; padding:10px 14px calc(14px + env(safe-area-inset-bottom));
    border-top:1px solid var(--paper-dark);
  }
  .study-who{
    display:inline-flex; align-items:center; gap:5px; font-size:11px; font-weight:700;
    color:var(--muted); background:var(--paper-dark); border-radius:999px; padding:3px 9px;
  }


  /* ---------- Messenger: inbox + rich threads ---------- */
  .msg-tabs{ display:flex; gap:6px; margin:12px 0 6px; }
  .msg-tab{
    flex:1; border:1.5px solid var(--paper-dark); background:var(--paper); color:var(--ink);
    border-radius:12px; padding:9px 6px; font-family:var(--font); font-weight:800; font-size:12.5px;
    cursor:pointer; display:flex; align-items:center; justify-content:center; gap:5px;
  }
  .msg-tab.active{ background:var(--cover); border-color:transparent; color:var(--on-cover); }
  .msg-badge{
    background:var(--bad); color:#fff; border-radius:999px; min-width:18px; height:18px;
    font-size:10.5px; font-weight:800; display:inline-flex; align-items:center; justify-content:center; padding:0 5px;
  }
  .msg-tab.active .msg-badge{ background:#fff; color:var(--cover); }
  .thread-row{
    display:flex; align-items:center; gap:11px; padding:11px 10px; cursor:pointer;
    border-radius:14px; transition:background .15s ease;
  }
  .thread-row:active{ background:var(--paper-dark); }
  .thread-row.unread{ background:rgba(79,70,229,0.06); }
  .thread-avatar-wrap{ position:relative; flex-shrink:0; }
  .thread-online{
    position:absolute; bottom:-1px; right:-1px; width:12px; height:12px; border-radius:50%;
    background:#22c55e; border:2.5px solid var(--card);
  }
  .thread-top{ display:flex; align-items:baseline; gap:8px; }
  .thread-name{ font-weight:800; font-size:14px; color:var(--ink); flex:1; min-width:0;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .thread-time{ font-size:10.5px; color:var(--muted-soft); flex-shrink:0; }
  .thread-preview{
    font-size:12.5px; color:var(--muted); margin-top:2px;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .thread-row.unread .thread-preview{ color:var(--ink); font-weight:700; }
  .dm-date-sep{ text-align:center; margin:14px 0 6px; }
  .dm-date-sep span{
    background:var(--paper-dark); color:var(--muted); font-size:10.5px; font-weight:800;
    border-radius:999px; padding:4px 12px;
  }
  .dm-meta-row{ display:flex; align-items:center; gap:5px; margin-top:3px; font-size:10px; color:var(--muted-soft); }
  .chat-row.mine .dm-meta-row{ justify-content:flex-end; }
  .dm-reaction{
    display:inline-block; margin-top:2px; background:var(--card);
    border:1px solid var(--paper-dark); border-radius:999px; padding:1px 6px; font-size:12px;
  }
  .dm-typing{ font-size:12px; color:var(--muted); font-style:italic; padding:6px; }
  #reactionBar{
    position:fixed; left:50%; transform:translateX(-50%); z-index:9600; display:none;
    background:var(--card); border:1px solid var(--paper-dark); border-radius:999px;
    padding:7px 10px; gap:6px; box-shadow:0 8px 24px rgba(0,0,0,0.2);
  }
  #reactionBar.show{ display:flex; }
  #reactionBar button{ border:none; background:none; font-size:20px; cursor:pointer; padding:2px; line-height:1; }

  /* ---------- Event board ---------- */
  .ev-city-row{ display:flex; flex-wrap:wrap; gap:7px; padding:2px 0 8px; } /* v224: every city visible (10 of 13 were cut off with no scroll hint) */
  .ev-city-row::-webkit-scrollbar{ display:none; }
  .ev-city{
    flex:0 0 auto; border:1.5px solid var(--paper-dark); background:var(--paper); color:var(--ink);
    border-radius:999px; padding:8px 14px; font-family:var(--font); font-weight:700; font-size:12.5px;
    cursor:pointer; white-space:nowrap;
  }
  .ev-city.active{ background:var(--cover); border-color:transparent; color:var(--on-cover); }
  .ev-card{
    display:flex; gap:12px; padding:13px; margin-bottom:9px;
    background:var(--paper); border:1px solid var(--paper-dark); border-radius:var(--radius-sm);
  }
  .ev-date{
    flex:0 0 auto; width:52px; text-align:center; background:var(--card);
    border:1px solid var(--paper-dark); border-radius:12px; padding:7px 4px; height:fit-content;
  }
  .ev-date .ev-mon{ font-size:10px; font-weight:800; color:var(--bad); text-transform:uppercase; letter-spacing:.05em; }
  .ev-date .ev-day{ font-size:20px; font-weight:800; color:var(--ink); line-height:1.1; }
  .ev-title{ font-weight:800; font-size:14.5px; color:var(--ink); line-height:1.3; }
  .ev-meta{ font-size:12px; color:var(--muted); margin-top:3px; display:flex; flex-wrap:wrap; gap:3px 10px; }
  .ev-kind{
    display:inline-block; font-size:11px; font-weight:800; text-transform:uppercase;
    letter-spacing:.04em; background:var(--paper-dark); color:var(--muted);
    border-radius:999px; padding:2px 8px; margin-bottom:5px;
  }
  .ev-actions{ display:flex; gap:7px; margin-top:9px; flex-wrap:wrap; }
  .ev-btn{
    border:1.5px solid var(--paper-dark); background:var(--card); color:var(--ink);
    border-radius:999px; padding:8px 14px; min-height:40px; font-family:var(--font); font-weight:800;
    font-size:12.5px; cursor:pointer;
  }
  .ev-btn.going{ background:#16a34a; border-color:transparent; color:#fff; }
  .ev-btn.interested{ background:var(--stamp); border-color:transparent; color:#fff; }

  /* ---------- Accent preference + profile details ---------- */
  .accent-row{ display:flex; gap:6px; margin-top:12px; }
  .accent-btn{
    flex:1; border:1.5px solid rgba(255,255,255,0.35); background:rgba(255,255,255,0.14);
    color:#fff; border-radius:12px; padding:8px 4px; font-family:var(--font);
    font-weight:800; font-size:11.5px; cursor:pointer; line-height:1.25;
  }
  .accent-btn small{ display:block; font-size:9.5px; font-weight:600; opacity:.8; margin-top:1px; }
  .accent-btn.active{ background:#fff; color:var(--ink); border-color:transparent; }
  .accent-label{ font-size:10.5px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; opacity:.85; margin-top:12px; }
  .region-badge{
    display:inline-flex; align-items:center; gap:3px; font-size:10px; font-weight:800;
    background:var(--paper-dark); color:var(--muted); border-radius:999px; padding:2px 7px;
  }
  .region-badge.north{ background:#e0e7ff; color:#3730a3; }
  .region-badge.central{ background:#fef3c7; color:#92400e; }
  .region-badge.south{ background:#dcfce7; color:#166534; }
  body.dark-mode .region-badge.north{ background:#312e81; color:#c7d2fe; }
  body.dark-mode .region-badge.central{ background:#78350f; color:#fde68a; }
  body.dark-mode .region-badge.south{ background:#14532d; color:#bbf7d0; }
  .profile-field{ text-align:left; margin-top:10px; }
  .profile-field .pf-label{ font-size:10.5px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); }
  .profile-field .pf-value{ font-size:13.5px; color:var(--ink); margin-top:2px; line-height:1.45; }

  /* ---------- "Soft & Friendly" pass (Sep 2026) ----------
     Additive on top of the Charmcraft base above, not a replacement — this
     is the direction Erick picked from 3 mockups (pastel-gradient tiles,
     deeper warm shadows, a mascot touch in empty states) after flagging
     the Practice Rooms / Events / Flashcards screens as flat and same-y.
     Kept as one block at the end of this stylesheet so it's easy to find
     and, if ever needed, easy to lift back out cleanly. */
  :root{
    --tile-1-bg: linear-gradient(160deg,#c9f3e4,#a6ecd3); --tile-1-ink:#0c4a3a;
    --tile-2-bg: linear-gradient(160deg,#ffe3d0,#ffcda8); --tile-2-ink:#7a3c14;
    --tile-3-bg: linear-gradient(160deg,#dcdafd,#c3bffb); --tile-3-ink:#382c8f;
    --tile-4-bg: linear-gradient(160deg,#ffd9ec,#ffbdde); --tile-4-ink:#8f1f5c;
  }
  body.dark-mode{
    --tile-1-bg: linear-gradient(160deg,#173a30,#124a37); --tile-1-ink:#a6ecd3;
    --tile-2-bg: linear-gradient(160deg,#3a2a18,#4a321a); --tile-2-ink:#ffcda8;
    --tile-3-bg: linear-gradient(160deg,#241f4a,#2c265a); --tile-3-ink:#c3bffb;
    --tile-4-bg: linear-gradient(160deg,#3a1f30,#4a2440); --tile-4-ink:#ffbdde;
  }
  /* A third soft blob (lavender, bottom-center) alongside the existing
     mint/coral ones — same technique, just one more color so the page
     doesn't read as a single flat cream field behind the card. */
  body{
    background-image:
      radial-gradient(600px circle at 8% -5%, rgba(29,145,120,0.12), transparent 55%),
      radial-gradient(600px circle at 100% 8%, rgba(242,126,109,0.10), transparent 50%),
      radial-gradient(560px circle at 50% 120%, rgba(147,130,240,0.09), transparent 55%);
  }
  /* Softer, bigger, warmer-tinted lift on the main card behind every tab —
     the single change with the widest reach, since .page wraps every screen. */
  .page{
    box-shadow: 0 20px 50px rgba(29,145,120,0.14), 0 2px 10px rgba(6,40,34,0.06);
  }
  /* Practice Rooms sub-nav + Events city filter: was a flat, single-color
     pill repeated 8-10 times. Each pill/chip now gets one of 4 pastel
     gradient tints, cycling in reading order, so the grid reads as
     colorful and inviting rather than a uniform wall of cream. Selectors
     use :nth-of-type (not :nth-child) since every sibling in each row is
     already a same-tag <button>, and stay scoped to the non-active state
     so the existing solid "picked" color (jade/coral/violet) still shows
     once a pill is selected. */
  .pr-pill:not(.active), .ev-city:not(.active){ box-shadow:0 4px 10px rgba(6,40,34,.07); }
  .pr-pill:not(.active):nth-of-type(4n+1){ background:var(--tile-1-bg); color:var(--tile-1-ink); border-color:transparent; }
  .pr-pill:not(.active):nth-of-type(4n+2){ background:var(--tile-2-bg); color:var(--tile-2-ink); border-color:transparent; }
  .pr-pill:not(.active):nth-of-type(4n+3){ background:var(--tile-3-bg); color:var(--tile-3-ink); border-color:transparent; }
  .pr-pill:not(.active):nth-of-type(4n+4){ background:var(--tile-4-bg); color:var(--tile-4-ink); border-color:transparent; }
  .ev-city:not(.active):nth-of-type(3n+1){ background:var(--tile-1-bg); color:var(--tile-1-ink); border-color:transparent; }
  .ev-city:not(.active):nth-of-type(3n+2){ background:var(--tile-3-bg); color:var(--tile-3-ink); border-color:transparent; }
  .ev-city:not(.active):nth-of-type(3n+3){ background:var(--tile-2-bg); color:var(--tile-2-ink); border-color:transparent; }
  /* Empty states ("Nobody's live right now", "Nothing posted yet") had a
     bare emoji floating on its own — wrapping it in a soft circle badge
     turns it into a small mascot moment instead of a placeholder icon. */
  .pr-empty-icon{
    width:60px; height:60px; border-radius:50%;
    background:linear-gradient(160deg,#fff,#fbf6ee);
    display:flex; align-items:center; justify-content:center;
    font-size:28px; margin:0 auto 10px;
    box-shadow:0 8px 20px rgba(6,40,34,0.10);
  }
  body.dark-mode .pr-empty-icon{ background:linear-gradient(160deg,#17352d,#122b25); }
  /* Flashcards' level row (#tierSelect) and tone row (#learnTones) share the
     app-wide .cat-chip class with dozens of other chip rows (category
     filters, survival/idiom topics, etc.), so the pastel treatment is
     scoped to just these two containers rather than to .cat-chip globally —
     a 24-chip category row cycling through 4 bright colors would read as
     noisy, not friendly. locked/forced/active chips are left alone: only
     an ordinary, unlocked, unselected chip gets a tint. */
  #tierSelect .cat-chip:not(.active):not(.locked):not(.forced):nth-of-type(4n+1),
  #learnTones .cat-chip:not(.active):nth-of-type(4n+1){ background:var(--tile-1-bg); color:var(--tile-1-ink); }
  #tierSelect .cat-chip:not(.active):not(.locked):not(.forced):nth-of-type(4n+2),
  #learnTones .cat-chip:not(.active):nth-of-type(4n+2){ background:var(--tile-2-bg); color:var(--tile-2-ink); }
  #tierSelect .cat-chip:not(.active):not(.locked):not(.forced):nth-of-type(4n+3),
  #learnTones .cat-chip:not(.active):nth-of-type(4n+3){ background:var(--tile-3-bg); color:var(--tile-3-ink); }
  #tierSelect .cat-chip:not(.active):not(.locked):not(.forced):nth-of-type(4n+4),
  #learnTones .cat-chip:not(.active):nth-of-type(4n+4){ background:var(--tile-4-bg); color:var(--tile-4-ink); }


  /* Placement test ("Find your level") — above the first-run setup sheet (9800). */
  #vcPlace{ position:fixed; inset:0; z-index:9850; display:none; align-items:center; justify-content:center; padding:16px; background:rgba(0,0,0,.5); }
  #vcPlace.show{ display:flex; }
  #vcPlace .pl-sheet{ position:relative; background:var(--card); color:var(--ink); border-radius:22px; width:100%; max-width:440px; max-height:90dvh; overflow-y:auto; padding:22px 18px 18px; box-shadow:0 20px 50px rgba(0,0,0,.3); text-align:center; }
  #vcPlace .pl-x{ position:absolute; top:8px; right:8px; width:44px; height:44px; border-radius:50%; border:0; background:var(--paper-dark); color:var(--ink); font-size:15px; cursor:pointer; }
  #vcPlace .pl-emoji{ font-size:44px; margin:6px 0 2px; }
  #vcPlace h2{ margin:4px 0 8px; font-size:22px; }
  #vcPlace p{ margin:0 0 14px; color:var(--muted); font-size:14.5px; line-height:1.45; }
  #vcPlace .pl-go{ width:100%; min-height:48px; margin:0; }
  #vcPlace .pl-sec{ width:100%; margin:8px 0 0; }
  #vcPlace .pl-prog{ height:6px; border-radius:99px; background:var(--paper-dark); overflow:hidden; margin:2px 40px 12px 0; }
  #vcPlace .pl-prog i{ display:block; height:100%; background:var(--cover); border-radius:99px; transition:width .25s; }
  #vcPlace .pl-lvl{ font-size:12px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--muted); text-align:left; margin-bottom:8px; }
  #vcPlace .pl-q{ font-size:19px; font-weight:800; margin:6px 0 4px; display:flex; align-items:center; justify-content:center; gap:10px; flex-wrap:wrap; }
  #vcPlace .pl-vn{ font-size:26px; }
  #vcPlace .pl-sub{ font-size:13px; color:var(--muted); margin-bottom:12px; }
  #vcPlace .pl-opts{ display:grid; gap:8px; margin-top:12px; }
  #vcPlace .pl-opt{ min-height:48px; padding:10px 14px; border-radius:14px; border:2px solid var(--line); background:var(--card); color:var(--ink); font:700 15px var(--font); cursor:pointer; text-align:center; }
  #vcPlace .pl-opt:active{ background:var(--paper-dark); }
  #vcPlace .pl-dk{ border-style:dashed; color:var(--muted); background:none; min-height:42px; font-weight:700; }
  #setupSheet .su-opts[data-su="tier"] button[data-val="test"]{ flex-basis:100%; border-style:dashed; }

/* v165 audit: dark mode — the bright mint buttons had white text (1.8:1); use the dark ink made for them. */
body.dark-mode .vc-td-go, body.dark-mode .vc-ui-lang-seg .on, body.dark-mode #groupRoomCodeJoinBtn,
body.dark-mode .accent-btn.active{ color:var(--on-cover) !important; }
body.dark-mode #wbPickBar .wb-pb-study{ background:var(--cover); color:var(--on-cover); }
body.dark-mode #homeQpMix{ color:#3a2d06; }
body.dark-mode #vcSuggestModeBtn{ background:var(--card); color:var(--ink); }

/* v166 audit: Flashcards on a phone — "Show answer" was under the bottom bar.
   Filters go on one row, the 6 card tools on one row, and A−/A+ move into Session settings (see JS). */
@media (max-width:520px){
  body:not(.focus-mode) .lf-topic{ flex:1.4 1 0; }
  body:not(.focus-mode) .lf-tone{ flex:1 1 0; }
  body:not(.focus-mode) .lf-sub{ flex:1 1 100%; order:5; }
  body:not(.focus-mode) .lf-bar{ flex-wrap:wrap; margin-bottom:8px; }
  body:not(.focus-mode) .card-tools{ flex-wrap:nowrap; gap:5px; }
  body:not(.focus-mode) .card-tools .speak-btn{ min-width:0; flex:1 1 0; max-width:62px; padding:7px 2px 5px; }
  body:not(.focus-mode) .card-tools .speak-btn::after{ font-size:9.5px; }
  #learnSettingsBody .font-size-ctrl{ display:inline-flex; margin:8px 0 2px; }
}
/* v166: after "Show answer" on a phone, the grade buttons stay in reach just above the bottom bar
   (they used to land ~150px below the screen, under the example box). */
@media (max-width:520px){
  body.fc-revealed:not(.focus-mode) #tab-learn #srsRow{
    position:fixed; left:10px; right:10px; z-index:60; margin:0 !important;
    bottom:calc(94px + env(safe-area-inset-bottom, 0px));
    background:var(--card, #fff); padding:8px; border-radius:16px; box-shadow:0 8px 24px rgba(6,40,34,.18);
  }
  body.fc-revealed:not(.focus-mode) #tab-learn #srsRow .srs-btn{ display:flex; align-items:center; justify-content:center; height:46px; min-height:46px; padding:0 4px; font-size:14px; white-space:nowrap; }
  body.fc-revealed:not(.focus-mode) #tab-learn{ padding-bottom:76px; }
}
/* v166: Survival & Idioms filters wrap instead of scrolling sideways (all choices visible at once). */
@media (max-width:520px){ #tab-idioms .cats, #tab-survival .cats{ gap:6px; margin-bottom:10px; } #tab-idioms .cat-chip, #tab-survival .cat-chip{ min-height:34px; display:inline-flex; align-items:center; } }
/* v166: "Hide example · Key · Focus mode" on one row on phones (it wrapped and pushed Show answer under the bar). */
@media (max-width:520px){
  body:not(.focus-mode) #tab-learn div:has(> #contextToggle){ display:flex !important; flex-wrap:nowrap !important; gap:6px !important; justify-content:center; }
  body:not(.focus-mode) #tab-learn div:has(> #contextToggle) > button{ flex:1 1 auto; min-width:0; margin:0 !important; padding:8px 6px !important; font-size:12px !important; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-height:40px; }
}
/* v167: the round Rooms button lights up when you're on Rooms (More used to). */
.bn-btn.bn-fab.active{ background:transparent !important; }
.bn-btn.bn-fab.active #navFabLabel{ color:var(--cover-deep, #12604f); font-weight:800; }
.bn-btn.bn-fab.active .bn-fab-circle{ box-shadow:0 0 0 3px var(--cover, #1d9178), 0 6px 16px rgba(0,0,0,.18); }
/* v167: on phones the call header ran ~80px off-screen (Minimize and Leave unreachable).
   Row 1 = room name + Leave; row 2 = the smaller chips, wrapped. */
@media (max-width:520px){
  #liveShell .live-topbar{ flex-wrap:wrap; row-gap:6px; gap:6px; padding-left:8px; padding-right:8px; }
  #liveShell .live-topbar .live-host-chip{ flex:1 1 calc(100% - 52px); order:0; min-width:120px; }
  #liveShell .live-topbar .live-host-name{ max-width:none; }
  #liveShell .live-topbar #liveClose{ order:1; width:40px; height:40px; margin-left:0; }
  #liveShell .live-topbar > :not(.live-host-chip):not(#liveClose){ order:2; padding:6px 10px; font-size:12px; min-height:34px; }
}
/* v167: one main button on the new-learner home — Today is primary, Start Here becomes the quieter "full course" link. */
.vc-home-secondary #homeContinueBtn{ background:transparent !important; color:var(--cover-deep, #12604f) !important; border:1.5px solid var(--line, #d9d4c7); height:46px !important; box-shadow:none !important; }
.vc-home-secondary #homeContinueBadge{ display:none !important; }
.dict-app-badge{ display:inline-block; font-size:10px; font-weight:800; color:var(--cover-deep, #12604f); background:var(--primary-tint, #e3f4ee); border-radius:999px; padding:1px 7px; margin-left:4px; vertical-align:1px; }
.dict-tab-add{ min-height:40px; }
/* v170: ➕ on the flashcard (right side, opposite ✎) */
.card-edit-btn.card-add-btn{ left:auto; right:10px; z-index:6; width:40px; height:40px; background:var(--card, #fff); color:var(--cover-deep, #12604f); border:1.5px solid var(--line, #d9d4c7); }
.card-edit-btn#flashEditWord{ width:40px; height:40px; }
/* Decks › My decks: decks on this device */
.ld-box{ margin:0 0 14px; }
.ld-h{ font-weight:800; font-size:14px; margin:0 0 8px; }
.ld-row{ display:flex; align-items:center; gap:10px; padding:10px 12px; border:1.5px solid var(--line, #e5e0d4); border-radius:14px; background:var(--card, #fff); margin-bottom:8px; }
.ld-name{ flex:1; min-width:0; font-weight:800; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ld-name small{ display:block; font-weight:600; color:var(--muted); font-size:12px; }
.ld-row .check-btn{ margin:0; min-height:40px; padding:8px 14px; }
.learn-due-pill{ float:right; margin:2px 0 0 8px; min-height:36px; padding:6px 12px; border-radius:999px; border:none; background:var(--gold-tint, #fff3d1); color:var(--ink); font:800 13px var(--font); cursor:pointer; }
/* v170: on a phone in a call, Chat sits above the call bar (it covered Mic and Leave) */
@media (max-width:759px){
  body.in-live-room .room-chat-panel:not(.floating), body.in-solo-call .room-chat-panel:not(.floating){ bottom:calc(76px + env(safe-area-inset-bottom, 0px)); max-height:calc(100dvh - 200px); border-radius:18px; }
  body.in-live-room .room-chat-panel .room-chat-foot{ padding-bottom:10px; }
}
.room-chat-body:empty::before{ content:'No messages yet — say hi 👋'; display:block; text-align:center; color:var(--muted); font-size:13px; padding:24px 8px; }
/* hover used to replace translateY(-50%) with the speak-btn hover transform, so ✎ / ➕ jumped away from the pointer */
.card-edit-btn:hover, .card-edit-btn:focus-visible{ transform:translateY(-50%) !important; }

/* v196 · Admin teacher lists (pending + live listings): one card per teacher, stacked so nothing is squeezed */
.adm-tl-bar{ display:flex; align-items:center; gap:10px; margin:6px 0 12px; }
.adm-tl-search{ flex:1; min-width:0; min-height:42px; padding:8px 12px; font:inherit; font-size:15px; border:1.5px solid var(--line); border-radius:12px; background:var(--card); color:var(--ink); }
.adm-tl-count{ font-size:13px; font-weight:800; color:var(--muted); white-space:nowrap; }
.adm-tl{ background:var(--card); border:1px solid var(--line); border-radius:18px; padding:14px 16px; margin-bottom:10px; display:flex; flex-direction:column; gap:8px; box-shadow:0 1px 3px rgba(11,38,33,.04); }
.adm-tl.is-off{ opacity:.6; }
.adm-tl-top{ display:flex; align-items:center; gap:12px; min-width:0; }
.adm-tl-av{ width:40px; height:40px; flex:none; border-radius:50%; display:flex; align-items:center; justify-content:center; font-weight:800; font-size:17px; color:var(--cover-deep, #047857); background:var(--primary-tint, #E6F7F4); }
.adm-tl-id{ flex:1; min-width:0; display:flex; flex-direction:column; }
.adm-tl-id b{ font-size:16.5px; font-weight:800; color:var(--ink); line-height:1.25; overflow-wrap:anywhere; }
.adm-tl-id small{ font-size:12.5px; color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.adm-tl-pill{ flex:none; font-size:11.5px; font-weight:800; padding:4px 10px; border-radius:999px; white-space:nowrap; }
.adm-tl-pill.on{ background:#dcfce7; color:#166534; } .adm-tl-pill.off{ background:#f5f5f4; color:#57534e; } .adm-tl-pill.wait{ background:#fef3c7; color:#92400e; }
.adm-tl-chips{ display:flex; flex-wrap:wrap; gap:6px; }
.adm-tl-chip{ font-size:12.5px; font-weight:700; padding:4px 10px; border-radius:999px; background:var(--paper-dark, #f5f5f4); color:var(--ink); }
.adm-tl-spec, .adm-tl-bio{ font-size:13.5px; color:var(--muted); line-height:1.45; overflow-wrap:anywhere; }
.adm-tl-bio{ color:var(--ink); }
.adm-tl-video{ font-size:13.5px; font-weight:700; color:var(--cover); }
.adm-tl-act{ display:flex; justify-content:flex-end; gap:8px; }
.adm-tl-act.two > *{ flex:1; }
.adm-tl-btn{ min-height:38px; padding:7px 16px; border-radius:999px; font:inherit; font-size:13.5px; font-weight:800; cursor:pointer; background:transparent; }
.adm-tl-btn.remove{ border:1.5px solid #fca5a5; color:#b91c1c; } .adm-tl-btn.remove:hover{ background:#fef2f2; }
.adm-tl-btn.restore{ border:1.5px solid var(--cover); color:var(--cover-deep, #047857); }
body.dark-mode .adm-tl-pill.on{ background:rgba(34,197,94,.15); color:#86efac; } body.dark-mode .adm-tl-pill.off{ background:rgba(255,255,255,.08); color:#d6d3d1; } body.dark-mode .adm-tl-pill.wait{ background:rgba(245,158,11,.15); color:#fcd34d; }
body.dark-mode .adm-tl-chip{ background:rgba(255,255,255,.08); } body.dark-mode .adm-tl-av{ background:rgba(94,234,212,.12); color:#5eead4; }
body.dark-mode .adm-tl-btn.remove{ border-color:#7f1d1d; color:#fca5a5; }
@media (min-width:700px){
  .adm-tl:has(> .adm-tl-act:not(.two)){ position:relative; }
  .adm-tl:has(> .adm-tl-act:not(.two)) > :is(.adm-tl-chips, .adm-tl-spec){ padding-right:130px; }
  .adm-tl > .adm-tl-act:not(.two){ position:absolute; right:16px; bottom:14px; }
}

/* v198 · 🛵 Motorbike licence (A1) test — src/js/236-driving-test.js */
.dh-card.dh-sit.dh-drive{ background:linear-gradient(135deg, #0f766e, #0ea5e9); box-shadow:0 4px 0 #115e59; }
.dh-card.dh-sit.dh-drive .dh-go{ color:#0f766e; }
#driveRoot{ display:flex; flex-direction:column; gap:12px; }
.dv-hero{ display:flex; align-items:center; gap:14px; padding:16px; border-radius:20px; background:linear-gradient(135deg, #ecfeff, #f0fdfa); border:1px solid #ccfbf1; }
.dv-hero-t{ flex:1; min-width:0; display:flex; flex-direction:column; gap:4px; } .dv-hero-t b{ font-size:17px; color:var(--ink); } .dv-hero-t small{ font-size:13px; color:var(--muted); line-height:1.45; }
.dv-ring{ --p:0; flex:none; width:74px; height:74px; border-radius:50%; display:grid; place-items:center; background:conic-gradient(#0d9488 calc(var(--p) * 1%), #e7e5e4 0); }
.dv-ring span{ width:58px; height:58px; border-radius:50%; background:var(--card, #fff); display:grid; place-items:center; font-size:11px; color:var(--muted); line-height:1.1; text-align:center; } .dv-ring b{ display:block; font-size:17px; color:var(--ink); }
.dv-big{ width:100%; display:flex; flex-direction:column; align-items:center; gap:2px; padding:14px; font-size:17px; } .dv-big small{ font-size:12.5px; opacity:.9; font-weight:700; }
.dv-last{ font-size:13.5px; padding:10px 14px; border-radius:14px; background:var(--paper-dark, #f5f5f4); } .dv-last.ok{ background:#dcfce7; color:#166534; } .dv-last.bad{ background:#fef3c7; color:#92400e; }
.dv-row{ display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.dv-tile{ display:flex; flex-direction:column; align-items:flex-start; gap:3px; padding:14px; text-align:left; border-radius:18px; border:1px solid var(--line); background:var(--card, #fff); font:inherit; cursor:pointer; color:var(--ink); }
.dv-tile span{ font-size:22px; } .dv-tile b{ font-size:15px; } .dv-tile small{ font-size:12.5px; color:var(--muted); } .dv-tile:disabled{ opacity:.55; cursor:default; }
.dv-label{ font-size:12.5px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); margin-top:4px; }
.dv-chs{ display:flex; flex-direction:column; gap:8px; }
.dv-ch{ display:grid; grid-template-columns:34px 1fr; grid-template-rows:auto auto; column-gap:12px; row-gap:6px; align-items:center; padding:12px 14px; border-radius:16px; border:1px solid var(--line); background:var(--card, #fff); font:inherit; text-align:left; cursor:pointer; color:var(--ink); }
.dv-ch-n{ grid-row:1 / 3; width:34px; height:34px; border-radius:10px; display:grid; place-items:center; font-weight:800; color:#0f766e; background:#ccfbf1; }
.dv-ch-t{ display:flex; justify-content:space-between; gap:8px; align-items:baseline; min-width:0; } .dv-ch-t b{ font-size:14.5px; } .dv-ch-t small{ font-size:12.5px; color:var(--muted); white-space:nowrap; }
.dv-bar{ display:block; height:6px; border-radius:99px; background:#e7e5e4; overflow:hidden; } .dv-bar i{ display:block; height:100%; background:#0d9488; border-radius:99px; }
.dv-all{ width:100%; }
.dv-src{ font-size:12px; color:var(--muted); line-height:1.5; }
.dv-top{ display:flex; align-items:center; gap:8px; } .dv-title{ flex:1; min-width:0; font-weight:800; font-size:15px; text-align:center; }
.dv-back, .dv-enbtn{ min-height:44px; padding:6px 12px; border-radius:999px; border:1px solid var(--line); background:var(--card, #fff); font:inherit; font-size:13.5px; font-weight:700; cursor:pointer; color:var(--ink); white-space:nowrap; }
.dv-enbtn.on{ background:#e0f2fe; border-color:#7dd3fc; color:#075985; }
.dv-prog{ display:grid; grid-template-columns:auto auto; justify-content:space-between; gap:6px; font-size:13px; color:var(--muted); font-weight:700; } .dv-prog .dv-bar{ grid-column:1 / -1; }
.dv-card{ background:var(--card, #fff); border:1px solid var(--line); border-radius:20px; padding:16px; display:flex; flex-direction:column; gap:12px; }
.dv-img{ display:block; max-width:100%; max-height:300px; margin:0 auto; border-radius:12px; object-fit:contain; background:#fff; } .dv-img.sm{ max-height:160px; }
.dv-q{ font-size:17px; font-weight:700; line-height:1.45; color:var(--ink); } .dv-num{ display:inline-block; margin-right:8px; padding:2px 8px; border-radius:8px; font-size:12px; background:#ccfbf1; color:#0f766e; vertical-align:2px; }
.dv-crit{ display:inline-block; font-size:11.5px; font-weight:800; padding:2px 8px; border-radius:99px; background:#fee2e2; color:#b91c1c; vertical-align:2px; }
.dv-en{ font-size:14px; color:#075985; background:#f0f9ff; border-radius:10px; padding:8px 10px; line-height:1.45; }
.dv-opts{ display:flex; flex-direction:column; gap:8px; }
.dv-opt{ display:flex; align-items:flex-start; gap:10px; width:100%; text-align:left; padding:12px 14px; border-radius:14px; border:1.5px solid var(--line); background:var(--card, #fff); font:inherit; font-size:15px; line-height:1.4; cursor:pointer; color:var(--ink); }
.dv-opt:disabled{ cursor:default; } .dv-k{ flex:none; width:24px; height:24px; border-radius:50%; display:grid; place-items:center; font-size:12px; font-weight:800; background:var(--paper-dark, #f5f5f4); color:var(--muted); }
.dv-ot{ display:flex; flex-direction:column; gap:3px; } .dv-ot small{ font-size:13px; color:#075985; }
.dv-opt.picked{ border-color:#0d9488; background:#f0fdfa; } .dv-opt.picked .dv-k{ background:#0d9488; color:#fff; }
.dv-opt.correct{ border-color:#16a34a; background:#dcfce7; } .dv-opt.correct .dv-k{ background:#16a34a; color:#fff; }
.dv-opt.wrong{ border-color:#dc2626; background:#fee2e2; } .dv-opt.wrong .dv-k{ background:#dc2626; color:#fff; }
.dv-nav{ display:flex; gap:8px; } .dv-nav > *{ flex:1; } .dv-nav > #dvPrev{ flex:0 0 52px; }
.dv-clock{ font-variant-numeric:tabular-nums; } .dv-clock.low{ color:#dc2626; }
.dv-grid{ display:grid; grid-template-columns:repeat(9, 1fr); gap:5px; }
.dv-gn{ min-height:34px; border-radius:9px; border:1px solid var(--line); background:var(--card, #fff); font:inherit; font-size:13px; font-weight:700; cursor:pointer; color:var(--ink); padding:0; }
.dv-gn.done{ background:#ccfbf1; border-color:#5eead4; } .dv-gn.cur{ outline:2px solid #0d9488; outline-offset:1px; }
.dv-done, .dv-result{ align-items:center; text-align:center; } .dv-big-n{ font-size:44px; font-weight:800; color:var(--ink); line-height:1; }
.dv-result.ok{ border-color:#86efac; background:#f0fdf4; } .dv-result.bad{ border-color:#fcd34d; background:#fffbeb; } .dv-verdict{ font-size:19px; } .dv-result p, .dv-done p{ margin:0; color:var(--muted); font-size:14px; } .dv-result .dv-nav{ width:100%; }
.dv-rev{ background:var(--card, #fff); border:1px solid var(--line); border-radius:16px; padding:12px 14px; display:flex; flex-direction:column; gap:6px; }
.dv-rev .dv-q{ font-size:15px; } .dv-yours{ font-size:14px; color:#b91c1c; } .dv-right{ font-size:14px; color:#166534; font-weight:700; display:flex; flex-direction:column; gap:2px; } .dv-right small{ color:#075985; font-weight:500; }
@media (min-width:700px){ .dv-grid{ grid-template-columns:repeat(13, 1fr); } #driveRoot{ max-width:760px; } }
body.dark-mode .dv-hero{ background:linear-gradient(135deg, rgba(13,148,136,.15), rgba(14,165,233,.1)); border-color:rgba(94,234,212,.2); }
body.dark-mode .dv-en, body.dark-mode .dv-ot small, body.dark-mode .dv-right small{ background:transparent; color:#7dd3fc; }
body.dark-mode .dv-opt.correct{ background:rgba(22,163,74,.18); } body.dark-mode .dv-opt.wrong{ background:rgba(220,38,38,.18); } body.dark-mode .dv-opt.picked{ background:rgba(13,148,136,.18); }
body.dark-mode .dv-gn.done, body.dark-mode .dv-ch-n, body.dark-mode .dv-num{ background:rgba(94,234,212,.15); color:#5eead4; }
body.dark-mode .dv-result.ok{ background:rgba(22,163,74,.1); } body.dark-mode .dv-result.bad{ background:rgba(245,158,11,.1); }
body.dark-mode .dv-img{ background:#fff; }

/* v199 · 🔤 Đánh vần (src/js/238-spelling.js); reuses .dv-top/.dv-card/.dv-bar/.dv-nav from the driving test */
#spellRoot{ display:flex; flex-direction:column; gap:12px; }
@media (min-width:700px){ #spellRoot{ max-width:760px; } }
.sp-intro{ padding:14px 16px; border-radius:18px; background:linear-gradient(135deg, #f5f3ff, #fdf2f8); border:1px solid #e9d5ff; font-size:14px; line-height:1.5; color:var(--ink); }
.sp-ex{ margin-top:8px; font-size:15px; } .sp-ex span{ color:#7c3aed; font-weight:700; }
.sp-abc > summary{ cursor:pointer; font-weight:800; font-size:14px; padding:10px 0; }
.sp-abc-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(58px, 1fr)); gap:6px; }
.sp-abc-k{ display:flex; flex-direction:column; align-items:center; padding:8px 4px; border-radius:12px; border:1px solid var(--line); background:var(--card, #fff); font:inherit; cursor:pointer; color:var(--ink); }
.sp-abc-k b{ font-size:22px; } .sp-abc-k small{ font-size:11.5px; color:var(--muted); }
.sp-levels{ display:flex; flex-direction:column; gap:10px; }
.sp-lv{ padding:12px 14px; border-radius:18px; border:1px solid var(--line); background:var(--card, #fff); display:flex; flex-direction:column; gap:10px; }
.sp-lv-h{ display:flex; gap:12px; align-items:center; } .sp-lv-n{ flex:none; width:34px; height:34px; border-radius:10px; display:grid; place-items:center; font-weight:800; color:#6d28d9; background:#ede9fe; }
.sp-lv-b{ display:flex; gap:8px; } .sp-lv-b > *{ flex:1; }
.sp-count{ font-size:13px; font-weight:700; color:var(--muted); }
.sp-card{ align-items:stretch; }
.sp-prompt{ display:flex; align-items:center; gap:10px; justify-content:center; flex-wrap:wrap; }
.sp-icon{ font-size:40px; line-height:1; } .sp-en{ font-size:16px; font-style:italic; color:var(--muted); }
.sp-hear{ min-height:44px; padding:6px 14px; border-radius:999px; border:1px solid #c4b5fd; background:#f5f3ff; color:#5b21b6; font:inherit; font-weight:800; cursor:pointer; }
.sp-word{ text-align:center; font-size:46px; font-weight:800; color:var(--ink); line-height:1.1; } .sp-word.ok{ color:#15803d; }
.sp-tiles, .sp-build{ display:flex; align-items:center; justify-content:center; gap:6px; flex-wrap:wrap; } .sp-tiles i, .sp-build i{ font-style:normal; color:var(--muted); font-weight:800; }
.sp-t{ display:flex; flex-direction:column; align-items:center; min-width:64px; padding:6px 10px; border-radius:12px; } .sp-t small{ font-size:10.5px; text-transform:uppercase; letter-spacing:.04em; opacity:.8; } .sp-t b{ font-size:20px; }
.sp-t.init{ background:#dbeafe; color:#1e40af; } .sp-t.rhyme{ background:#dcfce7; color:#166534; } .sp-t.tone{ background:#fee2e2; color:#b91c1c; }
.sp-chant{ display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:4px; font-size:16px; font-weight:700; color:#6d28d9; } .sp-chant i{ font-style:normal; color:var(--muted); }
.sp-c{ padding:2px 6px; border-radius:8px; transition:background .15s; } .sp-c.on{ background:#ede9fe; }
.sp-slot{ min-width:58px; padding:8px 10px; text-align:center; border-radius:12px; border:2px dashed var(--line); font-size:22px; font-weight:800; color:var(--muted); } .sp-slot.f{ border-style:solid; border-color:#a78bfa; color:var(--ink); }
.sp-row{ display:flex; flex-direction:column; gap:6px; } .sp-row-l{ font-size:12px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); }
.sp-row-o{ display:grid; grid-template-columns:repeat(4, 1fr); gap:6px; } .sp-row:nth-of-type(5) .sp-row-o, .sp-row-o:has(> .sp-o:nth-child(5)){ grid-template-columns:repeat(6, 1fr); }
.sp-o{ display:flex; flex-direction:column; align-items:center; gap:1px; padding:8px 4px; border-radius:12px; border:1.5px solid var(--line); background:var(--card, #fff); font:inherit; cursor:pointer; color:var(--ink); min-height:48px; justify-content:center; }
.sp-o b{ font-size:19px; } .sp-o small{ font-size:10.5px; color:var(--muted); }
.sp-o.picked{ border-color:#7c3aed; background:#f5f3ff; } .sp-o.correct{ border-color:#16a34a; background:#dcfce7; } .sp-o.wrong{ border-color:#dc2626; background:#fee2e2; } .sp-o:disabled{ cursor:default; }
.sp-res{ display:flex; flex-direction:column; gap:8px; align-items:stretch; } .sp-res:empty{ display:none; }
@media (max-width:420px){ .sp-row-o:has(> .sp-o:nth-child(5)){ grid-template-columns:repeat(3, 1fr); } }
body.dark-mode .sp-intro{ background:linear-gradient(135deg, rgba(124,58,237,.12), rgba(219,39,119,.08)); border-color:rgba(167,139,250,.25); }
body.dark-mode .sp-t.init{ background:rgba(59,130,246,.18); color:#93c5fd; } body.dark-mode .sp-t.rhyme{ background:rgba(34,197,94,.15); color:#86efac; } body.dark-mode .sp-t.tone{ background:rgba(239,68,68,.15); color:#fca5a5; }
body.dark-mode .sp-o.picked, body.dark-mode .sp-hear, body.dark-mode .sp-c.on, body.dark-mode .sp-lv-n{ background:rgba(124,58,237,.18); color:#c4b5fd; }
body.dark-mode .sp-o.correct{ background:rgba(22,163,74,.18); } body.dark-mode .sp-o.wrong{ background:rgba(220,38,38,.18); } body.dark-mode .sp-chant{ color:#c4b5fd; }
body.dark-mode .sp-ex span{ color:#c4b5fd; } /* v224: the intro example was #7c3aed on the dark card (2.6:1) */
/* v205: small "🔊 EN" pill next to an English meaning (vcSayBtn) */
.vc-say-lang{ display:inline-flex; align-items:center; gap:3px; margin:2px 0 2px 4px; padding:5px 12px; min-height:32px; min-width:56px; justify-content:center; border-radius:999px; border:1px solid var(--line, #d8e2dc); background:var(--card, #fff); color:var(--cover, #0f7a5c); font:600 12.5px/1.2 var(--font, inherit); cursor:pointer; vertical-align:middle; white-space:nowrap; }
.vc-say-lang:hover{ border-color:currentColor; }
.vc-say-lang.speaking, .vc-say-lang[disabled]{ opacity:.6; }
/* v206: admin — progress through the lists */
.vc-ac-prog{ grid-column:1 / -1; margin-top:8px; padding:10px 12px; border-radius:14px; background:var(--soft, rgba(15,122,92,.06)); display:flex; flex-direction:column; gap:6px; }
.vc-ac-prog-h{ font-weight:800; font-size:13px; }
.vc-ac-pr-t{ font-size:13px; } .vc-ac-pr small, .vc-ac-pr-s{ font-size:12px; color:var(--muted, #667); display:block; }
.vc-ac-pr-bar{ height:7px; border-radius:99px; background:var(--line, #dde5e0); overflow:hidden; margin:4px 0 3px; }
.vc-ac-pr-bar i{ display:block; height:100%; background:var(--cover, #0f7a5c); border-radius:99px; min-width:2px; }
.vc-idiom-more{ width:100%; margin-top:6px; min-height:44px; }
/* v206: on phones every screen gets room below its last button, so nothing sits under the round Rooms button */
@media (max-width:1023px){ section[role="tabpanel"]{ padding-bottom:56px; } }
/* v206: phone flashcards — extra tools behind ⋯ Tools (240-fc-tools.js) */
.fc-more-btn{ display:none; }
@media (max-width:1023px){
  body:not(.focus-mode) .fc-more-btn{ display:inline-flex; order:99; }
  html:not(:has(#vcTour.show)) body:not(.focus-mode) #cardTools:not(.fc-open) > .speak-btn:not(#flashSpeak):not(.fc-more-btn){ display:none !important; }
  html:not(:has(#vcTour.show)) body:not(.focus-mode) #tab-learn:not(.fc-open) .fc-extra{ display:none !important; }
}
/* v207: Study together › 🧱 Grammar — the pattern at a glance */
.study-gram-card{ margin:-4px 0 10px; padding:10px 12px; border-radius:12px; background:var(--soft, rgba(15,122,92,.07)); border:1px solid var(--line, #dfe6e2); }
.study-gram-card .sgc-t{ font-weight:800; font-size:14px; }
.study-gram-card .sgc-pat{ margin-top:4px; font-family:ui-monospace, Menlo, monospace; font-size:13px; color:var(--cover, #0f7a5c); white-space:pre-wrap; }
.study-gram-card .sgc-note{ margin-top:4px; font-size:12.5px; color:var(--muted, #667); max-height:5.4em; overflow:auto; }
/* v208: ⠿ grip to drag the call's control bar (242-move-bar.js) */
.lb-grip{ flex:0 0 auto; align-self:center; width:28px; min-height:44px; border:0; border-radius:10px; background:rgba(255,255,255,.12); color:rgba(255,255,255,.85); font-size:18px; line-height:1; cursor:grab; touch-action:none; user-select:none; -webkit-user-select:none; padding:0; }
.lb-grip:hover{ background:rgba(255,255,255,.22); }
.live-bottombar.lb-dragging{ transition:none; opacity:.92; }
.live-bottombar.lb-dragging .lb-grip{ cursor:grabbing; background:rgba(255,255,255,.3); }
.live-bottombar.lb-moved{ box-shadow:0 10px 30px rgba(0,0,0,.35); border-radius:18px; background:rgba(20,24,22,.78); }
/* v209: Study together — the grammar structure strip */
.study-gram-strip{ margin:0 0 8px; padding:9px 11px; border-radius:12px; background:var(--soft, rgba(15,122,92,.07)); border:1px solid var(--line, #dfe6e2); font-size:13px; display:flex; flex-direction:column; gap:6px; }
.study-gram-strip .sgs-head{ display:flex; align-items:center; justify-content:space-between; gap:8px; }
.study-gram-strip .sgs-lbl{ font-weight:800; }
.study-gram-strip .sgs-link{ border:0; background:none; color:var(--cover, #0f7a5c); font:600 12px var(--font, inherit); cursor:pointer; padding:4px 0; white-space:nowrap; }
.study-gram-strip .sgs-pat{ font-family:ui-monospace, Menlo, monospace; font-size:14px; font-weight:700; color:var(--cover, #0f7a5c); white-space:pre-wrap; }
.study-gram-strip .sgs-note{ font-size:12.5px; color:var(--muted, #556); max-height:7em; overflow:auto; }
.study-gram-strip .sgs-row{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.study-gram-strip .sgs-tip{ flex:1 1 100%; color:var(--muted, #556); font-size:12.5px; }
.study-gram-strip .sgs-btn{ min-height:34px; padding:5px 12px; border-radius:999px; border:1px solid var(--line, #d8e2dc); background:var(--card, #fff); color:var(--ink, #1c1917); font:600 12.5px var(--font, inherit); cursor:pointer; }
.study-gram-strip .sgs-btn.on{ background:var(--cover, #0f7a5c); border-color:var(--cover, #0f7a5c); color:#fff; }
.study-gram-strip .sgs-turn{ padding:8px 10px; border-radius:10px; background:rgba(255,193,7,.16); border:1px solid rgba(217,160,0,.45); }
.study-gram-strip .sgs-turn code{ font-size:12.5px; }
.study-gram-strip .sgs-eg{ display:block; margin-top:3px; color:var(--muted, #556); }
.study-gram-strip .sgs-blocks{ display:flex; flex-wrap:wrap; align-items:center; gap:4px; }
.study-gram-strip .sgs-blocks i{ font-style:normal; color:var(--muted, #889); }
.study-gram-strip .sgs-lbl2{ font-size:11px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:var(--muted, #667); margin-right:4px; }
.study-gram-strip .sgs-chip{ padding:3px 9px; border-radius:8px; background:var(--card, #fff); border:1px solid var(--line, #d8e2dc); font-weight:700; }
mark.sgk{ background:rgba(255,193,7,.38); color:inherit; border-radius:4px; padding:0 2px; }
body.dark-mode .study-gram-strip .sgs-btn, body.dark-mode .study-gram-strip .sgs-chip{ background:#1f2523; color:#e7e5e4; border-color:#3a4340; }
/* v211: Tone Trainer — add English to a word/sentence that has none */
.vc-tone-enbtn{ margin-left:6px; min-height:30px; padding:3px 10px; border-radius:999px; border:1px solid var(--line, #d8e2dc); background:var(--card, #fff); color:var(--cover, #0f7a5c); font:600 12.5px var(--font, inherit); font-style:normal; cursor:pointer; }
.vc-tone-enedit{ display:flex; gap:6px; align-items:center; width:100%; font-style:normal; }
.vc-tone-enedit input{ flex:1; min-width:0; margin:0; }
.vc-tone-enedit .check-btn, .vc-tone-enedit .skip-btn{ margin:0; min-height:40px; padding:6px 12px; }
/* v212: the confirm / alert / prompt / picker sheets sat flush on the bottom edge, so on a computer the buttons could be
   cut off (taskbar, zoom, browser bars). On wider screens they're a centred dialog with room around it; always scrollable. */
#confirmSheet, #promptSheet, #pickSheet{ max-height:calc(100dvh - 24px); overflow:auto; box-sizing:border-box; }
@media (min-width:700px){
  #confirmOverlay, #promptOverlay, #pickOverlay{ align-items:center; padding:24px; box-sizing:border-box; }
  #confirmSheet, #promptSheet, #pickSheet{ border-radius:20px !important; padding-bottom:20px !important; box-shadow:0 24px 60px rgba(0,0,0,.35); max-height:calc(100dvh - 48px); }
}
/* v212: Tone Ear opens from a clear button inside the Tone Trainer */
.vc-tone-earrow .vc-tone-earbtn{ display:flex; align-items:center; gap:10px; width:100%; min-height:52px; margin:6px 0 2px; padding:8px 14px; border-radius:14px; border:1.5px solid rgba(217,160,0,.55); background:linear-gradient(135deg, rgba(255,193,7,.16), rgba(255,193,7,.06)); color:var(--ink, #1c1917); font:inherit; text-align:left; cursor:pointer; }
.vc-tone-earbtn:hover{ border-color:#d9a000; background:rgba(255,193,7,.22); }
.vc-tone-earbtn .vte-ic{ font-size:24px; line-height:1; }
.vc-tone-earbtn .vte-t{ flex:1; display:flex; flex-direction:column; min-width:0; }
.vc-tone-earbtn .vte-t b{ font-size:14.5px; }
.vc-tone-earbtn .vte-t small{ font-size:12px; color:var(--muted, #667); }
.vc-tone-earbtn .vte-go{ font-size:22px; color:#b8860b; }
body.dark-mode .vc-tone-earbtn{ color:#e7e5e4; }
/* v212: on phones the ⠿ grip is a small tab above the bar, so it doesn't push Leave off the edge */
@media (max-width:699px){
  .live-bottombar .lb-grip{ position:absolute; left:12px; top:-24px; transform:none; width:56px; min-height:0; height:24px; font-size:14px; border-radius:8px 8px 0 0; background:rgba(20,24,22,.7); z-index:2; }
}
/* v217: 📱 texting shortcuts in Idioms & Slang */
.vc-abbr b{ font-family:ui-monospace, Menlo, monospace; font-size:1.25em; padding:1px 8px; border-radius:8px; background:rgba(15,122,92,.1); color:var(--cover, #0f7a5c); margin-right:4px; }
.vc-abbr span{ font-weight:600; }

/* v296 · floating chat: visible resize corners (bottom-right + top-left), ⤢ big reading size */
@media (min-width:760px){
  .dm-thread-view.floating{ width:340px; height:460px; }
  .dm-thread-view.floating .study-resize-handle{ display:block; z-index:2; }
  .dm-thread-view.floating .dm-rs-tl{ left:2px; top:2px; right:auto; bottom:auto; cursor:nwse-resize; transform:rotate(180deg); }
  .dm-thread-view.floating.dm-big .dm-log{ font-size:16px; }
  .dm-thread-view.floating.dm-big .dm-log .chat-bubble{ max-width:78%; }
  .dm-thread-view.floating.dm-big #dmInput{ font-size:16px; min-height:44px; }
}
#dmFloatBigBtn{ display:none; }
.dm-thread-view.floating #dmFloatBigBtn{ display:inline-flex; align-items:center; justify-content:center; }
@media (max-width:759px){ .dm-thread-view.floating #dmFloatBigBtn, .dm-thread-view.floating .dm-rs-tl{ display:none !important; } }
