:root{
  --ink:#1a1a1a; --muted:#6b6b6b; --line:#e6e6e6; --bg:#fbfbfa; --card:#fff;
  --accent:#ff4700; --ok:#1f9d55; --close:#c98a00; --off:#b23b3b;
  --radius:12px; --pad:16px; --maxw:760px;
}
*{box-sizing:border-box}
/* 17px at an untouched browser (16px × 106.25%), and a quarter larger in a
   browser its owner set to 20px — a fixed 17px threw that setting away
   (Vitaly, 2026-09-16). A student's own step (crosscutting/reading.py) is
   written the same way, inline on <html>, by base.html. */
html{font-size:106.25%}
body{margin:0;background:var(--bg);color:var(--ink);
  /* Calibri first (Vitaly, 2026-08-15: "will read clearly and be more compact").
     It ships with Windows and with Office on a Mac, so this honours the
     preference where the font exists — it cannot be served: Calibri is
     proprietary and self-hosting it would be a licence breach. Every other
     device keeps the native system face, which is what the app has always used.
     ONE face for every student means self-hosting an open one (Exo 2 is
     SIL-OFL) — that is a change to every screen and its own decision. */
  font-family:Calibri,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  line-height:1.5;-webkit-font-smoothing:antialiased}
main{max-width:var(--maxw);margin:0 auto;padding:var(--pad)}
h1{font-size:1.6rem;margin:.4em 0 .3em}
h2{font-size:1.2rem;margin:1.4em 0 .4em;color:#333}
h3{margin:1.4em 0 .3em}
a{color:inherit}
.muted{color:var(--muted)} .small{font-size:.85rem}
.back{display:inline-block;color:var(--muted);text-decoration:none;font-size:1.3rem;margin:.2em 0}

/* nav */
.nav{display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  padding:10px var(--pad);background:var(--card);border-bottom:1px solid var(--line)}
.brand{font-weight:700;font-size:1.15rem;text-decoration:none;letter-spacing:.5px}
.nav .links{margin-left:auto;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.nav .links a{text-decoration:none;color:#444}
.nav .links a:hover{color:var(--accent)}
.nav .links a.navicon{display:inline-flex;align-items:center;color:var(--muted);padding:3px 5px;border-radius:8px}
.lang{display:inline-flex;gap:2px;border:1px solid var(--line);border-radius:8px;overflow:hidden}
.lang button{border:0;background:#fff;color:var(--muted);padding:3px 8px;cursor:pointer;font-size:.8rem}
.lang button.on{background:var(--ink);color:#fff}
.lang.big button{padding:8px 16px;font-size:1rem}
/* Nav language picker — translate-icon menu (compact; replaces the segmented control in the bar) */
.langpick{position:relative}
.langpick summary{display:inline-flex;align-items:center;gap:5px;cursor:pointer;color:var(--muted);padding:3px 5px;border-radius:8px;list-style:none}
.langpick summary::-webkit-details-marker{display:none}
.langpick summary::marker{content:""}
.langpick[open] summary,.langpick summary:hover{color:var(--accent)}
.langpick-menu{position:absolute;right:0;top:calc(100% + 6px);z-index:30;display:flex;flex-direction:column;min-width:96px;
  background:var(--card);border:1px solid var(--line);border-radius:10px;box-shadow:0 10px 28px rgba(0,0,0,.12);padding:4px}
.langpick-menu button{border:0;background:transparent;color:var(--ink);padding:8px 12px;cursor:pointer;font-size:.85rem;text-align:left;border-radius:6px}
.langpick-menu button:hover{background:var(--bg)}
.langpick-menu button.on{background:var(--ink);color:#fff}
.langpick-langs{display:flex;flex-direction:column}
/* Text size row under the languages: four A's, each at its own px size
   (inline, from reading.STEPS), baseline-aligned so they read as one word
   growing rather than four buttons of different heights. */
.langpick-sizes{display:flex;align-items:baseline;justify-content:space-between;gap:2px;
  margin-top:4px;padding-top:4px;border-top:1px solid var(--line)}
.langpick-sizes button{flex:1;text-align:center;padding:4px 6px;line-height:1;font-weight:600;
  font-family:inherit}

/* «Якою мовою до вас звертатися?» — the one card written in three languages at
   once, because it is the one card that cannot know its reader's. Shown in the
   shell over whatever page they opened, only while students.l1 is unset. */
.l1ask{max-width:34rem;margin:10px auto 0;padding:14px 16px;background:var(--card);
  border:1px solid var(--line);border-radius:14px}
.l1ask-q{margin:0 0 10px;font-size:.95rem;line-height:1.5}
.l1ask-q span{opacity:.7;font-size:.88rem}
.l1ask-row{display:flex;flex-wrap:wrap;gap:8px}
.l1ask-row button{border:1px solid var(--line);background:transparent;color:var(--ink);
  padding:9px 16px;border-radius:10px;cursor:pointer;font-size:.9rem;font-weight:500}
.l1ask-row button:hover{background:var(--ink);color:#fff;border-color:var(--ink)}

/* cards / grid */
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px;margin-top:1em}
/* Library — language + type filter chips, and the work tiles (course/movie/series/book) */
.libbar{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 12px}
.libchip{display:inline-flex;align-items:center;gap:5px;padding:5px 12px;border:1px solid var(--line);border-radius:999px;
  text-decoration:none;color:var(--ink);font-size:.85rem;background:var(--card)}
.libchip:hover{border-color:var(--accent);color:var(--accent)}
.libchip.on{background:var(--ink);color:#fff;border-color:var(--ink)}
.libchip-n{font-size:.72rem;opacity:.55}
.libselect{padding:7px 32px 7px 12px;border:1px solid var(--line);border-radius:10px;background:var(--card);
  color:var(--ink);font-size:.9rem;cursor:pointer;min-width:200px;appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b6b6b' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 11px center}
.libselect:hover{border-color:var(--accent)}
.libchip-upload{color:var(--accent);border-color:var(--accent);margin-left:auto}
.libsearch{padding:7px 12px;border:1px solid var(--line);border-radius:10px;background:var(--card);
  color:var(--ink);font-size:.9rem;flex:1;min-width:160px}
.libsearch:hover,.libsearch:focus{border-color:var(--accent);outline:none}
.worktile{position:relative;border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
.worktile:hover{border-color:var(--accent)}
.worktile-link{display:flex;flex-direction:column;gap:6px;padding:14px;padding-right:46px;text-decoration:none;color:var(--ink)}
/* kept for the habitat + drill-course tiles, where it marks the pack/language.
   The library grid dropped its type badge — it ate row width for nothing. */
.worktile-type{align-self:flex-start;font-size:.66rem;text-transform:uppercase;letter-spacing:.04em;
  padding:2px 8px;border-radius:6px;background:var(--bg);color:var(--muted)}
.worktile-title{font-weight:600;line-height:1.25}
.worktile-byline{font-size:.78rem;color:var(--muted);font-style:italic}
.worktile-meta{font-size:.8rem;color:var(--muted)}
.worktile.lib-hidden{display:none}
.work-add{position:absolute;top:10px;right:10px;width:28px;height:28px;border-radius:50%;
  border:1px solid var(--line);background:var(--card);color:var(--muted);cursor:pointer;
  font-size:1rem;line-height:1;display:flex;align-items:center;justify-content:center;padding:0}
/* glyph is CSS-driven for the library ＋/✓ toggle only. The Focus/Background
   remove buttons carry their own × in markup, so they opt out via
   [data-remove] — otherwise both stack and render ✓× (and ×× on hover). */
.work-add:not([data-remove])::before{content:'＋'}
.work-add:hover{border-color:var(--accent);color:var(--accent)}
.work-add.on{background:var(--accent);color:#fff;border-color:var(--accent)}
.work-add.on:not([data-remove])::before{content:'✓'}
.work-add.on:not([data-remove]):hover::before{content:'×'}
/* remove is a secondary, destructive action — it sits on every committed card,
   so it stays an outline at rest instead of a filled slab, and fills only on
   hover to confirm it is about to act. */
.work-add[data-remove]{background:var(--card);color:var(--accent);border-color:var(--accent)}
.work-add[data-remove]:hover{background:var(--accent);color:#fff}
/* list view (toggle) — one work per row */
.grid.as-list{grid-template-columns:1fr;gap:8px}
.grid.as-list .worktile-link{flex-direction:row;align-items:center;gap:12px;padding:10px 46px 10px 14px}
.grid.as-list .worktile-title{flex:1}
.grid.as-list .worktile-meta{flex-shrink:0}
.grid.as-list .work-add{top:50%;transform:translateY(-50%)}
.card{display:block;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px;text-decoration:none;transition:border-color .15s,transform .1s}
.card:hover{border-color:var(--accent);transform:translateY(-1px)}
.card-title{font-weight:600}
.card-sub{color:var(--muted);font-size:.85rem;margin-top:4px}

/* protocols picker */
.protocols{display:flex;gap:10px;flex-wrap:wrap;margin:1em 0}
.proto{flex:1 1 180px;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:14px;text-decoration:none}
.proto:hover{border-color:var(--accent)}
.proto b{display:block}
.proto span{color:var(--muted);font-size:.85rem}

/* segment list */
.segments{list-style:none;padding:0;margin:1em 0}
.segments li{display:flex;align-items:center;gap:12px;padding:10px 12px;background:var(--card);
  border:1px solid var(--line);border-radius:10px;margin-bottom:6px}
.seg-text{flex:1}
.seg-go{text-decoration:none;color:var(--accent);font-size:1.1rem}
.strength{display:inline-block;width:54px;height:7px;background:#eee;border-radius:5px;overflow:hidden}
.strength-fill{display:block;height:100%;background:var(--close)}
.strength.known .strength-fill{background:var(--ok)}

/* practice */
.practice{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:22px;margin-top:.6em}
.proto-name{color:var(--accent);font-weight:600;text-transform:uppercase;letter-spacing:1px;font-size:.8rem}
.target{min-height:64px;display:flex;align-items:center;justify-content:center;text-align:center;
  margin:18px 0;padding:14px;border-radius:10px;background:#faf7f4;transition:opacity .5s}
.target.hidden{opacity:0}
.phrase{font-size:1.5rem;font-weight:500}
.cue-big{font-size:1.2rem;color:var(--muted)}
.hint{color:var(--muted);font-size:.85rem;text-align:center;margin-top:-8px}
.reproduce{display:flex;flex-direction:column;gap:8px;margin-top:14px}
.reproduce label{font-size:.85rem;color:var(--muted)}
textarea{font:inherit;padding:10px;border:1px solid var(--line);border-radius:8px;resize:vertical;width:100%}
button[type=submit]{align-self:flex-start;background:var(--ink);color:#fff;border:0;border-radius:8px;
  padding:9px 20px;font-size:1rem;cursor:pointer}
button[type=submit]:hover{background:var(--accent)}

/* feedback */
.feedback{margin-top:18px;padding:16px;border-radius:10px;border-left:4px solid var(--muted);background:#faf9f8}
.fb-matched{border-color:var(--ok)} .fb-close{border-color:var(--close)} .fb-off{border-color:var(--off)}
.fb-msg{font-size:1.1rem;margin:.2em 0 .6em}
/* 2026-08-22 — words first, the number quiet. The transformation message leads;
   the verdict word and percentage sit under it at body size, in muted grey, for
   anyone who wants them. Transformation over tracking, per the method. */
.fb-msg{font-size:1.15rem;line-height:1.42;margin:.1em 0 .6em}
.fb-prompts{margin:.2em 0 .7em;padding-left:1.1em;color:var(--muted);font-size:.95rem}
.fb-prompts li{margin:0 0 .25em}
.fb-score.quiet{font-size:.9rem;color:var(--muted);margin:.5em 0 .2em}
.fb-score .fb-verdict{color:var(--muted)}
.fb-score .fb-pct{font-variant-numeric:tabular-nums;opacity:.7;margin-left:.35em}

/* The game's name, where the student can see it. */
.game-name{font-size:.95rem;color:var(--muted);margin:.35em 0 .1em;letter-spacing:.01em}

/* Kept, quietened: a run of days is worth noticing, not announcing. */
.quiet-stat .streak-num,.quiet-stat .n{font-size:1rem !important;font-weight:500;
  color:var(--muted)}
.quiet-stat .streak-label,.quiet-stat .l{font-size:.78rem;color:var(--muted)}
.fb-stage{text-align:center;margin:14px 0 6px}
.fb-stage-line{font-weight:500;margin:0 0 3px}
.fb-stage-sub{margin:0}
.fb-reflect .reflect-label{font-size:.75rem;text-transform:uppercase;letter-spacing:1px;color:var(--muted)}
.fb-reflect ul{margin:.3em 0;padding-left:1.1em;color:#444}
.fb-reflect li{margin:.2em 0}
.fb-missing{margin:.6em 0 0}
.fb-missing span{display:inline-block;background:#fff;border:1px dashed var(--line);border-radius:6px;
  padding:2px 8px;margin:2px;color:var(--muted);font-size:.85rem}
.fb-actions{margin-top:12px;display:flex;gap:8px}
.btn{display:inline-block;text-decoration:none;border:1px solid var(--line);border-radius:8px;
  padding:8px 16px;background:#fff;color:#333}
.btn.primary{background:var(--accent);color:#fff;border-color:var(--accent)}
.btn.danger{background:#fff;color:var(--off);border-color:var(--off)}

/* coach */
.students{display:flex;gap:10px;flex-wrap:wrap;margin:.6em 0}
.student-card{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:10px 14px}
.student-card b{display:block} .student-card .l2{color:var(--muted);font-size:.8rem;margin-right:8px}
.student-card .known{color:var(--ok);font-size:.8rem}
table{border-collapse:collapse;width:100%;background:var(--card);border:1px solid var(--line);border-radius:10px;overflow:hidden;font-size:.9rem}
th,td{text-align:left;padding:8px 10px;border-bottom:1px solid var(--line);vertical-align:top}
th{font-size:.7rem;text-transform:uppercase;letter-spacing:.5px;color:var(--muted)}
td.mode{font-size:.7rem;color:var(--muted)} td.phr{color:#333} td.repro{color:var(--muted)}
.pill{display:inline-block;padding:2px 9px;border-radius:20px;font-size:.75rem;color:#fff;text-transform:lowercase}
.pill.matched{background:var(--ok)} .pill.close{background:var(--close)} .pill.off{background:var(--off)}

/* health */
.counts{display:flex;gap:14px;flex-wrap:wrap;margin:1em 0}
.count{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:8px 14px}
.count b{font-size:1.3rem;margin-right:6px}
.star{color:#ccc} .star.on{color:var(--accent)}
.va-audio.disabled{color:#bbb}
.reqs tr.s5 td{color:var(--off)} .reqs tr.s2 td{color:#333}

/* ── practice screen (v2 layout) ───────────────────────────────────────── */
.pr{max-width:580px;margin:0 auto}
/* One row if at all possible (the timer + ? moved to the top nav); on a screen
   too narrow even after the ≤560px tightening, it scrolls rather than wraps. */
.abc-row{display:flex;align-items:center;gap:6px;flex-wrap:nowrap;overflow-x:auto;padding:6px 0}
.abc-back{font-size:1.3rem;text-decoration:none;color:var(--muted);padding:0 4px}
.abc-pill{display:inline-flex;align-items:center;justify-content:center;min-width:34px;height:34px;padding:0 11px;
  border:1px solid var(--line);border-radius:9px;background:#fff;color:#333;text-decoration:none;cursor:pointer;font-weight:600;font-size:.9rem}
.abc-pill.is-active{background:#2f6df6;border-color:#2f6df6;color:#fff}
.abc-pill.chunk{font-family:ui-monospace,monospace;color:var(--muted)}
.abc-pill.chunk.is-long{color:var(--accent);border-color:var(--accent)}
.subpills{display:inline-flex;gap:6px;margin:0 2px}
.subpill{width:34px;height:34px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;
  text-decoration:none;border:2px solid var(--line);background:#fff;color:#555;font-weight:700;font-size:.85rem}
.fam-B .subpill.s1{border-color:#e0322f;color:#e0322f} .fam-B .subpill.s1.on{background:#e0322f;color:#fff}
.fam-B .subpill.s2{border-color:#2f6df6;color:#2f6df6} .fam-B .subpill.s2.on{background:#2f6df6;color:#fff}
.fam-B .subpill.s3{border-color:#1f9d55;color:#1f9d55} .fam-B .subpill.s3.on{background:#1f9d55;color:#fff}
.subpill.on{background:var(--ink);color:#fff;border-color:var(--ink)}
.abc-spacer{flex:1}
.activity-timer{font-size:.82rem;color:var(--muted);background:#f0efec;border-radius:14px;padding:5px 12px;white-space:nowrap;text-decoration:none;font-variant-numeric:tabular-nums}
.abc-pill.help{color:var(--muted);font-weight:700}
.abc-pill.help.is-active{background:var(--ink);border-color:var(--ink);color:#fff}
/* The section explainer [?] is drawn by the shell but waits, unseen, until
   section_help.js seats it in the title row — .abc-pill's display would
   otherwise beat the browser's own [hidden] rule and flash it by the logo. */
.section-help[hidden]{display:none}
/* Video overlay — shared by the Structures ? and any other page-level
   help-video. Portrait screen-recording videos keep their native aspect
   ratio (object-fit:contain) so nothing is cropped or stretched. */
.video-overlay{position:fixed;inset:0;z-index:80;display:flex;align-items:center;justify-content:center;
  background:rgba(0,0,0,.82);padding:16px}
/* Card is just a positioning wrapper — the video sizes itself from its
   width/height attributes (intrinsic aspect), capped by max-width/max-height
   to fit the viewport. No math, no aspect-ratio hacks. */
.video-overlay-card{position:relative;display:inline-flex;align-items:center;justify-content:center}
.video-overlay-x{position:absolute;top:-14px;right:-14px;width:36px;height:36px;border-radius:50%;
  border:none;background:#fff;color:#333;font-size:1rem;cursor:pointer;box-shadow:0 2px 10px rgba(0,0,0,.4);z-index:1}
.video-overlay-video{max-width:min(92vw, 520px);max-height:90vh;width:auto;height:auto;object-fit:contain;background:#000;border-radius:10px;display:block}
.mode-help{margin:.4em 0 .8em;padding:10px 12px;background:#f7f6f2;border:1px solid var(--line);border-radius:10px}
.mode-help[hidden]{display:none !important}
.mode-help .instruction{margin:0 0 .6em}
.mode-help .instruction:last-child{margin-bottom:0}
.mode-help .explainer-video{display:block;width:100%;height:auto;max-height:60vh;border-radius:8px;background:#000}
.instruction{color:#333;font-size:.98rem;line-height:1.4}
.instruction .ph{font-size:.62rem;color:var(--muted);border:1px solid var(--line);border-radius:5px;padding:1px 5px}
.progress-stack{display:flex;flex-direction:column;gap:3px;margin:.2em 0 .7em}
.sent-bar{--ph:20px;position:relative;height:5px;background:#eee;border-radius:4px;margin-top:calc(var(--ph) * 0.8)}
.sent-fill{height:100%;background:#bbb;border-radius:4px}
.playhead{position:absolute;top:50%;width:var(--ph);height:var(--ph);transform-origin:center;
  transform:translate(-50%,calc(var(--ph) * -1.207)) rotate(-45deg);
  background:transparent;border:2px solid var(--accent);border-radius:50% 50% 50% 0;cursor:grab;
  touch-action:none;transition:left .08s}
.sent-bar.scrubbing .playhead{cursor:grabbing;transition:none;box-shadow:0 0 0 3px rgba(255,71,0,.18)}
.ph-tip{position:absolute;bottom:calc(var(--ph) * 1.5 + 8px);transform:translateX(-50%);background:var(--ink);color:#fff;
  font-size:.72rem;font-weight:600;padding:3px 9px;border-radius:7px;white-space:nowrap;pointer-events:none;z-index:2}
/* B-mode session goal: band start→target + draggable flag; green when k = N */
.goal-band{position:absolute;top:-2px;height:9px;background:rgba(47,109,246,.22);border-radius:5px;pointer-events:none}
.goal-band.met{background:rgba(31,157,85,.40)}
.goal-flag{position:absolute;top:50%;width:12px;height:12px;transform:translate(-50%,-50%) rotate(45deg);
  background:#2f6df6;border-radius:3px;cursor:grab;touch-action:none;z-index:1}
.goal-flag:active{cursor:grabbing}
.goal-chip{align-self:flex-end;font-size:.74rem;color:var(--muted);margin-top:1px}
.goal-chip.met{color:var(--ok);font-weight:600}
.game-bar{height:4px;border-radius:3px;opacity:.55}
.game-bar.g1{background:#e0322f} .game-bar.g2{background:#2f6df6} .game-bar.g3{background:#1f9d55}
.media-box{position:relative;width:100%;min-height:124px;background:linear-gradient(135deg,#fff,#fbf1ec);
  border:1px solid var(--line);border-radius:12px;cursor:pointer;display:flex;align-items:center;
  justify-content:center;transition:border-color .15s}
.media-box:hover{border-color:var(--accent)}
.media-box.playing{border-color:var(--accent)}
.media-play{display:flex;align-items:center;justify-content:center;width:60px;height:60px;border-radius:50%;
  background:var(--accent);color:#fff;font-size:1.5rem;padding-left:4px;box-shadow:0 2px 12px rgba(255,71,0,.28)}
.media-box .source-media{display:none}
/* video sizes to its OWN aspect ratio (Friends is ~5:4, not 16:9) so there's no
   letterbox/pillarbox; full container width, height follows. */
.media-box.has-video{padding:0;background:#000;min-height:0;overflow:hidden}
.media-box.has-video .source-media{display:block;position:static;width:100%;height:auto;max-height:60vh;object-fit:contain}
.media-box.has-video .media-play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);transition:opacity .15s,transform .1s;background:rgba(0,0,0,.55);box-shadow:0 2px 14px rgba(0,0,0,.4)}
.media-box.has-video .media-play:hover{transform:translate(-50%,-50%) scale(1.07)}
/* while playing the overlay hides, but reappears as a Pause glyph on hover */
.media-box.playing .media-play{opacity:0;pointer-events:none}
.media-box.has-video.playing:hover .media-play{opacity:.92;pointer-events:auto}
/* Oracle (B3) keeps the source locked until the student has spoken. The lock is the
   mode, not a fault — so say so, instead of leaving a dead ▶ over a black frame for
   the student to read as a broken episode. practice.js already flips data-locked. */
.media-lock{display:none}
.media-box[data-locked="1"]{cursor:default}
.media-box[data-locked="1"]:hover{border-color:var(--line)}
.media-box[data-locked="1"] .media-play{display:none}
.media-box[data-locked="1"] .media-lock{display:flex;align-items:center;gap:8px;max-width:88%;
  padding:9px 15px;border-radius:999px;background:rgba(0,0,0,.58);color:#fff;
  font-size:.88rem;line-height:1.3;text-align:left}
.media-box.has-video[data-locked="1"] .media-lock{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}
/* C-mode video + its controls, pinned together at the top while she works the
   ladder below (2026-09-25): «video is a must at all times» (Vitaly) — a long
   card (C5's five options + a note) must never scroll the picture out of
   view, phone or desktop. Same sticky pattern as #aam-media. */
#cview .media-pin{position:sticky;top:0;z-index:6;background:var(--bg);padding-bottom:2px}
/* C-mode playback controls (2026-09-16): one row under the media — ‹ ⟲10 ▶ 10⟳ ›,
   then elapsed · bar · total. Touch targets 40px; the bar takes the rest. */
.media-ctl{display:flex;align-items:center;gap:6px;margin:.5em 0 0;flex-wrap:wrap}
.mc-btn{display:inline-flex;align-items:center;justify-content:center;gap:1px;min-width:40px;height:40px;
  padding:0 6px;border:1px solid var(--line);border-radius:10px;background:var(--bg,#fff);color:inherit;
  cursor:pointer;font:inherit;font-size:.78rem;font-weight:600;line-height:1}
.mc-btn:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
.mc-btn:disabled{opacity:.35;cursor:default}
.mc-btn.mc-play{background:var(--accent);border-color:var(--accent);color:#fff}
.mc-btn.mc-play:hover:not(:disabled){color:#fff;filter:brightness(1.06)}
.mc-n{font-size:.72rem}
.mc-time{font-variant-numeric:tabular-nums;font-size:.85rem;color:var(--muted,#666);min-width:3.2em;text-align:center}
.mc-seek{flex:1 1 120px;min-width:80px;height:40px;margin:0;accent-color:var(--accent);cursor:pointer}
.mc-seek:disabled{cursor:default;opacity:.5}
/* [CC] — subtitles on/off (C3–C5); filled when on, like a real player's CC */
.mc-btn.mc-cc{letter-spacing:.04em;margin-left:auto}
.mc-btn[hidden]{display:none}   /* [CC] on a rung with no text (a650): the class's inline-flex would otherwise beat the browser's [hidden] */
.mc-btn.mc-cc[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:#fff}
.opus-compat-warn{margin:.5em 0 0;line-height:1.4}
.scene-row{display:flex;justify-content:space-between;align-items:center;margin:.5em 0;font-weight:600}
.scene{color:#333} .scene-menu{color:#bbb;letter-spacing:2px}
.subs-area{position:relative;text-align:center;padding:22px 50px;border:1px solid var(--line);border-radius:12px;background:#fff;min-height:60px;display:flex;flex-direction:column;justify-content:center;gap:6px}
.subs-area .u-btn{position:absolute;left:12px;top:12px;width:34px;height:34px;border:1px solid var(--line);border-radius:8px;background:#fff;cursor:pointer;font-weight:600}
.subs-area .star-btn{position:absolute;right:12px;top:12px;border:0;background:none;font-size:1.4rem;color:#ccc;cursor:pointer}
.subs-area .star-btn.on{color:var(--accent)}
.subs-text{font-size:1.5rem;font-weight:500;margin:0}
.prev-cue{margin:.1em 0 .5em;padding:.45em .8em;border-left:3px solid var(--line);border-radius:0 8px 8px 0;background:#faf7f5;color:var(--muted);font-size:1.02rem;font-style:italic;text-align:left}
.prev-cue-label{display:block;font-size:.62rem;font-style:normal;letter-spacing:.04em;text-transform:uppercase;opacity:.75;margin-bottom:1px}
.subs-gloss{color:var(--muted);font-size:.9rem;margin:0}
.cc-btn{align-self:center;border:1px solid var(--line);border-radius:8px;background:#fff;color:var(--muted);padding:4px 12px;cursor:pointer}
.transport{display:flex;align-items:center;justify-content:center;gap:12px;margin:18px 0 2px;flex-wrap:wrap}
.transport .ctrl{display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);background:#fff;cursor:pointer;color:var(--ink)}
.ctrl.nav{width:54px;height:54px;border-radius:50%;font-size:1.3rem;text-decoration:none}
.ctrl.play{width:62px;height:62px;border-radius:50%;font-size:1.6rem}
.ctrl.nav.off{opacity:.3;pointer-events:none}
.ctrl.speed{height:54px;min-width:54px;border-radius:27px;padding:0 16px;font-weight:700}
.ctrl.delay{height:54px;min-width:82px;border-radius:27px;padding:0 14px;gap:5px;justify-content:center;
  box-sizing:border-box;font-variant-numeric:tabular-nums}
.rec-compound{display:inline-flex;align-items:center;border:2px solid var(--accent);border-radius:32px;overflow:hidden}
.rec-btn{border:0;background:#fff;cursor:pointer;padding:11px 18px;display:flex;align-items:center;gap:6px}
.rec-btn .rec-mic{color:#e0322f;display:inline-flex;align-items:center}
.rec-btn.recording{background:#ffe9e0}
/* While recording, the ONE button must read STOP. A tinted background alone left
   the mic glyph saying "tap to record" mid-recording, so students tapped it a
   second time expecting to start and instead ended the take. Swap the glyph for
   a stop square off .recording — the class every recorder on every screen
   already toggles — so there is no second button and no per-screen JS to keep in
   sync. `> *` hides the inline <svg>; font-size:0 hides the text glyph the
   pronounce screen uses instead of one. Deliberately NOT scoped to .rec-btn:
   the stories screen's record control is a .sbtn carrying the same .rec-mic. */
.recording .rec-mic{font-size:0;line-height:0}
.recording .rec-mic > *{display:none}
.recording .rec-mic::before{content:"";display:inline-block;
  width:16px;height:16px;border-radius:3px;background:currentColor;
  animation:ax-pulse 1.1s ease-in-out infinite}
/* …and it PULSES. A square that just sits there reads as "the button broke"
   (the same finding as .ax-action.on below, Vitaly 2026-08-17) — in the
   session-389 replay (2026-09-14) he asked for the B-mode Rec to become a
   visibly running StopRec, a pulsing red square. Same keyframes as the
   .ax-action control so every recorder breathes at one rhythm. */
@media (prefers-reduced-motion:reduce){
  .recording .rec-mic::before{animation:none;opacity:.75}
}
.rec-btn.rec-locked{cursor:not-allowed;opacity:.4}
.rec-btn.rec-locked .rec-mic{color:#bbb}
.rec-div{width:1px;align-self:stretch;background:var(--line)}
.play-attempt{border:0;background:#fff;cursor:pointer;padding:11px 16px;color:var(--ink)}
.play-attempt:disabled{opacity:.3;cursor:default}
.rec-status{text-align:center;min-height:1.2em;margin-top:6px}
.heard{margin:.2em 0 .6em;font-size:1.05rem}
.diff{margin:.2em 0 .6em;line-height:2}
.dw-match{color:var(--ok)} .dw-missing{color:var(--off);text-decoration:line-through;opacity:.7} .dw-extra{color:var(--muted);font-style:italic}

/* ── student shell (hub-and-spoke; v2 layout in va's design) ──────────────── */
.topbar{display:flex;align-items:center;gap:12px;margin:.2em 0 1em}
.topbar h1{flex:1;margin:0;font-size:1.5rem}
.topbar-back{color:var(--muted);text-decoration:none;font-size:1.4rem;line-height:1;width:32px}
.topbar-action{color:var(--accent);text-decoration:none;font-weight:600;font-size:.95rem;
  border:1px solid var(--line);border-radius:20px;padding:6px 12px;line-height:1}
.cta{color:var(--muted);margin:-.6em 0 1.2em}
.section-title{color:var(--muted);font-size:.74rem;text-transform:uppercase;letter-spacing:.07em;
  margin:1.5em 0 .5em;font-weight:600}

/* hub spokes */
.hub{display:flex;flex-direction:column;gap:12px}
.spoke{display:flex;align-items:center;gap:16px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius);padding:16px 18px;text-decoration:none;color:inherit;
  transition:border-color .15s,transform .1s}
.spoke:hover{border-color:var(--accent);transform:translateY(-1px)}
.spoke-icon{width:30px;height:30px;flex-shrink:0;color:var(--muted)}
.spoke-body{flex:1;min-width:0}
.spoke-title{font-weight:600}
.spoke-sub{color:var(--muted);font-size:.85rem;margin-top:3px}
.spoke-count{flex-shrink:0;color:var(--muted);font-size:.8rem;font-variant-numeric:tabular-nums}

/* soft cards (generic v2-card analog) */
.scard{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px;margin-bottom:12px}
.scard-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:6px}
.scard-title{font-weight:600;font-size:1.05rem;margin:0}
.rep-open{color:inherit;text-decoration:none;border-bottom:1px solid var(--line,#e2e8f0)}
.rep-open-line{display:inline-block;margin:2px 0 6px;color:var(--accent,#ff4d00);text-decoration:none}
.scard-meta{color:var(--muted);font-size:.85rem}
/* a whole card as one clickable link (Focus tiles, course-detail module rows) */
a.scard{display:block;text-decoration:none;color:inherit;transition:border-color .15s}
a.scard:hover{border-color:var(--accent)}

/* streak strip */
.streak{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:8px}
.streak-num{font-size:2rem;font-weight:600;font-variant-numeric:tabular-nums;line-height:1.1}
.streak-num small{font-size:1rem;color:var(--muted);font-weight:400}
.streak-label{color:var(--muted);font-size:.8rem}
.streak-goal{text-align:right}
.streak-bar{height:7px;background:#eee;border-radius:5px;overflow:hidden;margin-bottom:1.2em}
.streak-bar-fill{height:100%;background:var(--accent)}

/* list rows (episodes, settings, queues) */
.row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 0;
  border-bottom:1px solid var(--line);text-decoration:none;color:inherit}
.row:last-child{border-bottom:0}
.row-label{display:flex;align-items:center;gap:9px}
.row-meta{color:var(--muted);font-size:.85rem;font-variant-numeric:tabular-nums}
.row-dot{width:8px;height:8px;border-radius:50%;background:var(--line);flex-shrink:0}
.row-dot.new{background:var(--accent)} .row-dot.progress{background:var(--close)} .row-dot.done{background:var(--ok)}

/* buttons + pillows */
.sbtn{display:inline-block;border:1px solid var(--line);border-radius:22px;background:#fff;color:var(--ink);
  padding:8px 16px;cursor:pointer;text-decoration:none;font:inherit;font-size:.9rem}
.sbtn.primary{background:var(--accent);border-color:var(--accent);color:#fff}
.sbtn.ghost{color:var(--muted)}
.sbtn.full{display:block;width:100%;text-align:center;padding:12px}
.sbtn.sm{padding:6px 12px;font-size:.85rem}
.sbtn:disabled{opacity:.4;cursor:default}
/* A hidden button is not drawn. The recorders' Стоп / Перезаписати / Надіслати
   їй showed in every state — the class's inline-block beat the browser's own
   [hidden] rule, exactly as .mc-btn did (a650) — and a Стоп that does nothing
   was «zero usability» (Vitaly, 2026-09-18, a663). */
.sbtn[hidden]{display:none}   /* after every .sbtn variant, so .full cannot win it back */
.pillow-row{display:flex;flex-wrap:wrap;gap:8px}
.pillow{border:1px solid var(--line);border-radius:20px;background:#fff;color:var(--ink);
  padding:7px 14px;cursor:pointer;font:inherit;font-size:.88rem}
.pillow.on{background:var(--ink);color:#fff;border-color:var(--ink)}

/* settings rows + fields */
.set-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 0;
  border-bottom:1px solid var(--line)}
.set-row:last-child{border-bottom:0}
.set-row select{font:inherit;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:#fff;color:var(--ink)}
.field{font:inherit;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:#fff;color:var(--ink);width:100%}

/* stats tiles */
.tiles{display:flex;gap:12px;margin:.6em 0 0}
.tile{flex:1;text-align:center;background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius);padding:14px}
.tile-num{font-size:1.6rem;font-weight:600;font-variant-numeric:tabular-nums}
.tile-num small{font-size:.8rem;color:var(--muted);font-weight:400}
.tile-label{color:var(--muted);font-size:.78rem;margin-top:2px}

/* login */
.login-card{max-width:380px;margin:3rem auto;text-align:center}
.login-card h1{font-size:1.6rem;margin-bottom:.1em;letter-spacing:.5px}
.login-sub{color:var(--muted);margin:.1em 0 1.4em}
.userlist{display:flex;flex-direction:column;gap:10px;margin:1em 0}
.userbtn{display:flex;flex-direction:column;gap:2px;border:1px solid var(--line);border-radius:var(--radius);
  background:#fff;padding:12px 16px;cursor:pointer;font:inherit;text-align:left;width:100%}
.userbtn:hover{border-color:var(--accent)}
.userbtn b{font-size:1.05rem}
.userbtn span{color:var(--muted);font-size:.82rem;text-transform:capitalize}
.userbtn.coach{border-left:3px solid var(--accent)}

/* notes + stubs */
.note{padding:8px 12px;border-radius:8px;font-size:.9rem}
.note.ok{background:#eafaf0;color:var(--ok)}
.stub-note{display:inline-block;font-size:.66rem;color:var(--close);border:1px dashed var(--close);
  border-radius:6px;padding:1px 6px;margin-left:4px;vertical-align:middle;text-transform:lowercase;letter-spacing:.03em}

/* delete card */
.delete-card{border:1px solid #f0c9c9;background:#fdf6f6;border-radius:var(--radius);padding:16px;margin-bottom:12px}
.delete-card h3{margin:.1em 0 .4em;color:var(--off)}
.warn{color:var(--off);font-weight:600}

/* questionnaire (/s/a) */
.qnav{display:flex;justify-content:space-between;align-items:center;gap:10px;margin:1.6em 0}
.qskip{margin:1.2em 0 .4em;text-align:center}
.qskip-btn{display:inline-block;padding:9px 18px;border:1px solid #d23b3b;border-radius:22px;background:#fff;color:#d23b3b;font-size:.85rem;font-family:inherit;cursor:pointer;text-decoration:none;opacity:.8}
.qskip-btn:hover{opacity:1}
.qopt{display:block;padding:7px 0;cursor:pointer}
.qopt input{margin-right:8px}

/* comprehension (C — pick the meaning) */
.comp-phrase{display:flex;align-items:center;gap:14px;justify-content:center;margin:1.4em 0}
.comp-phrase .ctrl.play{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;
  border:1px solid var(--line);background:#fff;color:var(--ink);padding:0;box-sizing:border-box}
.comp-target{font-size:1.5rem;font-weight:500}

/* ── A (Analyzer) full-text lookup view ─────────────────────────────────── */
/* A-mode video: full-bleed + sticky so it stays pinned while the transcript
   auto-scrolls under it (subs + video visible together, esp. on a phone). */
#aam-media{position:sticky;top:0;z-index:6;width:100%;max-width:none;margin:0 0 10px;
  border-radius:0;background:#000;min-height:0;padding:0}
#aam-media.has-video .source-media{position:static;display:block;width:100%;height:auto;max-height:56vh;object-fit:contain}
#aam-media .media-play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}
.aam-layer{margin-top:6px}
.aam-segment{position:relative;display:flex;flex-wrap:wrap;align-items:flex-start;gap:10px;padding:9px 4px;border-bottom:1px solid var(--line);scroll-margin-top:42vh}
.aam-segment.aam-current{background:#fbf1ec;border-radius:8px;box-shadow:inset 3px 0 0 var(--accent)}
.aam-play{flex-shrink:0;width:30px;height:30px;border-radius:50%;border:1px solid var(--line);background:#fff;color:var(--accent);cursor:pointer;font-size:.78rem}
.aam-sent{flex:1;margin:0;font-size:1.15rem;line-height:1.75}
.aam-star,.aam-eye{flex-shrink:0;border:0;background:none;font-size:1.3rem;color:#ccc;cursor:pointer;line-height:1.2}
.aam-star.on{color:var(--accent)}
.aam-eye .eye-ic{fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round}
.aam-eye .eye-slash{display:block}
.aam-segment.eye-open .aam-eye{color:var(--accent)}
.aam-segment.eye-open .aam-eye .eye-slash{display:none}
/* Right-edge stack: ★ on top, the [T]-armed per-line translate pill UNDER it
   (Vitaly 2026-08-11: "make it appear under the star, not to the right of it"). */
.aam-side{flex-shrink:0;display:flex;flex-direction:column;align-items:center;gap:6px}
/* Per-line translate control. Hidden until [T] arms the layer (.t-armed); then
   one small pill per line (the target-lang code) reveals that line's gloss. */
.aam-tr-btn{flex-shrink:0;display:none;border:1px solid var(--line);background:#fff;color:var(--muted);cursor:pointer;font-size:.66rem;font-weight:700;letter-spacing:.03em;line-height:1;padding:5px 7px;border-radius:11px;text-transform:uppercase}
#aam-layer.t-armed .aam-tr-btn{display:inline-flex;align-items:center}
.aam-tr-btn.on{color:var(--accent);border-color:var(--accent);background:#fbf1ec}
.lookup-word{cursor:pointer;border-bottom:1px dotted #c4c4c4;padding:0 1px;touch-action:pan-y;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}
/* A held finger on iOS starts text selection and the callout, and Safari then
   cancels the press (pointercancel) — the word never registers. Words are
   buttons here, not text to copy. .is-held: the long press has registered. */
.lookup-word.is-held{background:#e8eefc;border-radius:3px}
.lookup-word:hover{background:#fdf0e9}
.lookup-word.is-active{background:#2f6df6;color:#fff;border-radius:3px;border-bottom-color:transparent}
/* karaoke: the word currently being spoken (weighted time-slice within the line) */
.lookup-word.aam-word-on{background:var(--accent);color:#fff;border-radius:3px;border-bottom-color:transparent;transition:background .08s}
/* A3 «Звірка», masked (Vitaly 2026-08-27: "highlighting placeholders of words
   dynamically" — listen first, words stay invisible, the karaoke bar is the only
   thing on screen until the eye opens a line). Paint-only: nothing here may change
   a box (padding/margin/font-size/border-width), or opening the eye would re-wrap
   the line under a moving auto-scroll target mid-playback. */
/* The line's text is in the paragraph itself since 2026-09-17 (the coach's
   frozen frame shows what she read); before the script wraps it into word
   spans — and for good in a frame that runs no script — the paragraph is the
   mask: invisible ink on the grey bar, exactly what the spans become. */
#aam-layer.masked .aam-segment:not(.eye-open) .aam-sent{color:transparent;
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
#aam-layer.masked .aam-segment.eye-open .aam-sent{color:inherit;-webkit-user-select:auto;user-select:auto}
#aam-layer.masked .lookup-word{color:transparent;background:#e2e2e2;border-radius:3px;
  border-bottom-color:transparent;transition:background .08s;
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
#aam-layer.masked .lookup-word:hover{background:#d4d4d4}
#aam-layer.masked .lookup-word.aam-word-on{background:var(--accent)}
#aam-layer.masked .aam-segment.eye-open .lookup-word{color:inherit;background:none;
  border-bottom-color:#c4c4c4;-webkit-user-select:auto;user-select:auto}
#aam-layer.masked .aam-segment.eye-open .lookup-word.aam-word-on{background:var(--accent);color:#fff;border-bottom-color:transparent}
/* Reserve the L1 pill's box while the line is closed — display:none would make
   the row grow on reveal and shove every line below it mid-playback. */
#aam-layer.masked .aam-segment:not(.eye-open) .aam-tr-btn{visibility:hidden}
#aam-layer.masked .aam-segment:not(.eye-open) .aam-tr{display:none}
/* A YouTube-backed source: the player IS the media (yt_watch.js drives the chunk
   through it), so the old audio box would be an empty second player with a dead
   play button on it. The element stays in the DOM — it carries the chunk's span,
   which everything reads — it just stops being furniture. */
.media-box.is-yt{display:none}
.yt-box{position:relative;margin:0 0 10px;border-radius:12px;overflow:hidden;background:#000}
.yt-frame{position:relative;width:100%;aspect-ratio:16/9}
.yt-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
/* collocations — the popover's second tab. Nothing is marked in the student's own
   text: the matching finds real phrases and listed word pairs in roughly equal
   measure (config.lookup_collocations), and underlining half a sentence on that
   basis is exactly the loud, wrong thing. The tab is quiet and costs a tap. */
.lp-tabs{display:flex;gap:6px;margin:0 22px .5em 0;border-bottom:1px solid var(--line)}
.lp-tab{border:0;background:none;font:inherit;font-size:.82rem;color:var(--muted);
  padding:3px 2px 5px;margin-bottom:-1px;border-bottom:2px solid transparent;cursor:pointer;
  max-width:48%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lp-tab:hover{color:var(--ink)}
.lp-tab.is-on{color:var(--accent);border-bottom-color:var(--accent);font-weight:600}
.lp-pane[hidden]{display:none}
.lp-phrase-tag{display:inline-block;font-size:.7rem;color:var(--muted);border:1px solid var(--line);
  border-radius:999px;padding:1px 7px;white-space:nowrap;margin-bottom:.35em}
/* Opening «інші значення» can add several dictionaries' worth of senses, so the
   popover scrolls inside itself rather than running off the screen. */
.lookup-popover{position:fixed;z-index:50;background:#fff;border:1px solid var(--line);border-radius:12px;
  box-shadow:0 6px 28px rgba(0,0,0,.18);padding:14px 16px;max-height:min(70vh,520px);overflow-y:auto}
.lp-close{position:absolute;top:5px;right:9px;border:0;background:none;font-size:1.2rem;color:var(--muted);cursor:pointer;line-height:1}
.lp-lemma{font-weight:700;font-size:1.1rem;margin-right:18px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.lp-add{font-size:.72rem;font-weight:600;border:1px solid var(--accent);color:var(--accent);background:#fff;border-radius:14px;padding:2px 9px;cursor:pointer;white-space:nowrap}
.lp-ipa{color:var(--muted);font-size:.85rem;margin:2px 0 6px}
.lp-sense{margin:5px 0;line-height:1.45}
/* The sense that fits THIS sentence. It is first in the list already; the accent
   marks it so the student's eye lands on it before the alternatives. */
.lp-sense.lead{font-weight:700;background:#fff4ef;border-left:3px solid var(--accent);
  padding:5px 9px;margin:6px -5px;border-radius:5px}
.lp-sense i{color:var(--muted);font-weight:400}
.lp-ex{color:var(--muted);font-size:.85rem;margin:1px 0 1px 10px}
.lp-none{color:var(--muted);margin-top:6px}
/* Other meanings — every dictionary option stays reachable, one tap away, so the
   contextual pick never hides a meaning the student was looking for. */
.lp-more{margin-top:9px;border-top:1px solid var(--line);padding-top:7px}
.lp-more summary{cursor:pointer;color:var(--muted);font-size:.85rem;list-style:none}
.lp-more summary::-webkit-details-marker{display:none}
.lp-more summary::before{content:"▸ "}
.lp-more[open] summary::before{content:"▾ "}
.lp-alt{margin-top:9px}
.lp-alt-hw{font-size:.78rem;font-weight:600;color:var(--muted)}
/* A-mode word states — iOS parity (Vitaly 2026-07-06 "va v3 web app does
   not have correct A-mode wiring"). Short-press toggles is-known; long-press
   opens the lookup popover; the X modifier hides the opposite side per mode.

   Base is-known: green (unchanged; long-standing web signal). In A1 the emphasis
   is on known words (they're the reward — you know them). In A2 the emphasis
   flips — the unknown words become the target, so they get the accent color
   and known words fade back. */
.lookup-word.is-known{color:#1f9d55;border-bottom-color:transparent}
/* Pre-existing bug, fixed in passing while in this file for the A3 eye work:
   equal specificity + source order let a known word being spoken right now
   render green text on the karaoke accent background (unreadable), in the
   already-live A1/A2/AX highlight. Named here instead of relied on, since the
   next person to touch either rule in isolation would silently reopen it. */
.lookup-word.is-known.aam-word-on{color:#fff}
/* A2 mode: known words recede, unknown ones stand out in blue (iOS blue = the
   "focus on what you don't know yet" register). Skip words (punctuation, ASR
   noise, proper nouns) never render as "unknown" — they aren't in the pool. */
.aam-layer.mode-a2 .lookup-word.is-known{opacity:.25}
.aam-layer.mode-a2 .lookup-word:not(.is-known):not([data-skip]){color:#2f6df6}
/* The [X] modifier is gone (Vitaly 2026-08-17: "[X] will be gone as well"). What
   it did by hand, A2 now does by being A2: the words you marked known recede and
   the rest stand out, which is the whole reason you would have reached for it. */
/* Legacy .only-new (pre-mode-a2 rename) — kept so a browser that landed on an
   older cached HTML still recedes the known words while it upgrades. Same
   opacity value; safe to keep, gets pruned in a follow-up. */
.aam-layer.only-new .lookup-word.is-known{opacity:.25}
/* AX «На слух» — text hidden; reveal a line by hovering or playing it (.revealed) */
.aam-layer.aam-by-ear .aam-sent{filter:blur(5px);transition:filter .12s;cursor:pointer}
.aam-layer.aam-by-ear .aam-segment:hover .aam-sent,
.aam-layer.aam-by-ear .aam-segment.revealed .aam-sent{filter:none}
/* ── A2 «Здогадки» ────────────────────────────────────────────────────────────
   In A2 a tap means "guess this", so the words must LOOK different from the A1
   read: a dashed accent underline on everything still to guess. A word already
   guessed goes quiet — its meaning is out and its dictionary is unlocked, so
   there is nothing left to commit there. */
.aam-layer.mode-a2 .lookup-word:not(.is-known):not([data-skip]){border-bottom:1px dashed var(--accent);cursor:help}
.aam-layer.mode-a2 .lookup-word[data-skip]{border-bottom-color:transparent;cursor:default}
.aam-layer.mode-a2 .lookup-word[data-guessed]{border-bottom-style:solid;opacity:.5;color:var(--muted)}
/* The rung's result, one quiet line above the text: "you know 34 of 120 words
   here" / "guessed 8 of 86". A count, never a grade (method rule). */
.aam-tally{color:var(--muted);font-size:.85rem;margin:.1em 0 .5em;min-height:1.2em}
/* One transient line ("press and hold to guess"), so a tap that deliberately does
   nothing never reads as a broken button. */
.aam-toast{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);z-index:60;
  background:rgba(24,24,24,.92);color:#fff;font-size:.9rem;padding:9px 15px;border-radius:20px;
  box-shadow:0 4px 18px rgba(0,0,0,.25);opacity:1;transition:opacity .35s;
  pointer-events:none;max-width:88vw;text-align:center}
.aam-toast.out{opacity:0}
/* The sheet: a bottom sheet under the thumb on a phone, a centred card on desktop.
   Same card language as the lookup popover — it is the same gesture, one step earlier. */
.guess-sheet{position:fixed;inset:0;z-index:70;background:rgba(20,20,20,.45);
  display:flex;align-items:flex-end;justify-content:center}
.guess-sheet[hidden]{display:none}
.gs-card{position:relative;background:#fff;width:100%;max-width:460px;border-radius:16px 16px 0 0;
  padding:18px 18px 14px;box-shadow:0 -6px 28px rgba(0,0,0,.2);max-height:88vh;overflow-y:auto}
@media (min-width:640px){
  .guess-sheet{align-items:center}
  .gs-card{border-radius:16px;padding:20px}
}
.gs-close{position:absolute;top:6px;right:11px;border:0;background:none;font-size:1.4rem;
  color:var(--muted);cursor:pointer;line-height:1}
.gs-word{font-weight:700;font-size:1.35rem;margin-right:22px;word-break:break-word}
.gs-line{color:var(--muted);font-size:.9rem;line-height:1.45;margin:4px 0 14px}
.gs-fields{display:flex;flex-direction:column;gap:8px}
/* Wide enough for one long word without scrolling inside the box, and set at
   reading size — this is the student's own answer, not a form field. */
.gs-field{width:100%;box-sizing:border-box;font:inherit;font-size:1.1rem;padding:11px 13px;
  border:1px solid var(--line);border-radius:11px;background:#fff;color:var(--ink)}
.gs-field:focus{outline:none;border-color:var(--accent)}
.gs-field[readonly]{background:#f7f7f7;color:var(--muted)}
.gs-actions{display:flex;align-items:center;gap:10px;margin-top:12px}
.gs-actions[hidden]{display:none}
/* One mic for the word, not one per field (Vitaly 2026-08-17). */
.gs-mic{flex-shrink:0;width:42px;height:42px;border-radius:50%;border:1px solid var(--line);
  background:#fff;color:var(--muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
.gs-mic.recording{background:var(--accent);border-color:var(--accent);color:#fff}
.gs-status{flex:1;color:var(--muted);font-size:.85rem}
.gs-check{border:1px solid var(--accent);background:var(--accent);color:#fff;font:inherit;
  font-weight:600;padding:10px 20px;border-radius:22px;cursor:pointer}
.gs-check:disabled{opacity:.5;cursor:default}
/* Results — the % is feedback on THIS guess, per row and small on purpose. It is not
   a grade on the student or on the mode (method rule: no scores on the A ladder). */
.gs-row{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;padding:8px 0;border-bottom:1px solid var(--line)}
.gs-guess{font-size:1.05rem}
.gs-score{font-weight:700;font-variant-numeric:tabular-nums;color:var(--muted)}
.gs-score.hi{color:#1f9d55}
.gs-score.mid{color:var(--accent)}
.gs-note{color:var(--muted);font-size:.85rem;flex-basis:100%}
.gs-note-block{margin:8px 0 0}
.gs-answer{margin-top:12px;background:#fff4ef;border-left:3px solid var(--accent);
  padding:9px 12px;border-radius:6px;font-size:1.05rem}
.gs-answer-k{color:var(--muted);font-size:.85rem}
.gs-done{margin-top:14px;width:100%;border:1px solid var(--line);background:#fff;color:var(--ink);
  font:inherit;font-weight:600;padding:11px;border-radius:22px;cursor:pointer}
.gs-hint{color:var(--muted);font-size:.85rem;line-height:1.4;margin:14px 0 0;text-align:center}
/* A-mode modifier pills (T/X/G) live in the shared .abc-row now, styled as .abc-pill
   for consistency with A/B/C/P. Engaged state = accent fill (distinct from the blue
   .is-active "current mode"); a_mode.js toggles .on. */
.abc-pill.mod.on{background:var(--accent);border-color:var(--accent);color:#fff}
/* Per-line L1 translation, revealed by a line's translate control. flex-basis
   100% drops it onto its own row under .aam-sent; muted italic + indent (past
   the play button) keep the source line the primary read. */
.aam-tr{flex-basis:100%;margin:2px 0 0 40px;color:var(--muted);font-size:.95rem;line-height:1.45;font-style:italic}
.lp-acts{display:inline-flex;gap:6px;flex-wrap:wrap;align-items:center}
/* the ★ on the card's headword line (lookup_popover.js) — VAKeep's star, sized
   to sit beside a 1.1rem headword without a 32px hit box pushing it off the line */
.lp-lemma .kp-star{min-width:26px;min-height:26px;font-size:1.05rem;padding:0 2px}
.lp-known{font-size:.72rem;font-weight:600;border:1px solid var(--line);color:var(--muted);background:#fff;border-radius:14px;padding:2px 9px;cursor:pointer;white-space:nowrap}
.lp-known.on{border-color:#1f9d55;color:#1f9d55}
.comp-options{display:flex;flex-direction:column;gap:10px;max-width:520px;margin:0 auto}
.comp-opt{border:1px solid var(--line);border-radius:12px;background:#fff;color:var(--ink);
  padding:14px 16px;cursor:pointer;font:inherit;font-size:1.05rem;text-align:left;transition:border-color .12s}
.comp-opt:hover:not(:disabled){border-color:var(--accent)}
.comp-opt:disabled{cursor:default}
.comp-opt.right{border-color:var(--ok);background:#eafaf0}
.comp-opt.wrong{border-color:var(--off);background:#fbeaea}

/* ── comprehension (C1–C5) — in-screen ladder under the practice video ── */
.comp-ladder{max-width:560px;margin:16px auto 0}
.comp-card{margin-bottom:6px}
.comp-done{text-align:center;padding:18px 0}
.comp-done .comp-question{margin-bottom:14px}
.comp-question{font-size:1.15rem;font-weight:500;margin:0 0 14px}
.comp-verdict{font-weight:600;margin:12px 0 4px}
.comp-verdict.ok{color:var(--ok)}
.comp-verdict.no{color:var(--off)}
.comp-expl{color:var(--muted);margin:0;font-size:.95rem}
.comp-next-row{margin-top:14px;text-align:right}
/* «Далі» is hidden until an answer — .sbtn's own display used to beat the attribute */
.comp-next-row [hidden]{display:none}
/* depth meter — the L1→L5 zoom ladder; dots open up to the unlocked depth */
.comp-depth{display:flex;align-items:center;gap:6px;justify-content:center;margin-bottom:14px}
.cd-dot{width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;
  font-size:.72rem;border:1px solid var(--line);color:var(--muted);background:#fff}
.cd-dot.open{border-color:var(--accent);color:var(--accent)}
.cd-dot.cur{background:var(--accent);color:#fff;border-color:var(--accent)}
.cd-label{margin-left:6px;font-size:.82rem;color:var(--muted)}
/* a locked (not-yet-unlocked) C sub-pill */
.subpill.locked{opacity:.4;cursor:default;pointer-events:none;border-style:dashed}
/* unlock toast */
.c-toast{position:fixed;left:50%;bottom:24px;transform:translate(-50%,12px);z-index:60;
  background:var(--ink);color:#fff;padding:9px 16px;border-radius:999px;font-size:.9rem;
  box-shadow:0 4px 18px rgba(0,0,0,.25);opacity:0;transition:opacity .25s,transform .25s;pointer-events:none}
.c-toast.show{opacity:1;transform:translate(-50%,0)}

/* Connection blinked (static/netblink.js). Same pill language as .c-toast — this is
   information, not an alarm, and the app's voice stays calm. Tappable, unlike the
   other toasts, because it asks the student to do something and they may want it
   out of the way first. */
.net-toast{position:fixed;left:50%;bottom:24px;transform:translate(-50%,12px);z-index:90;
  background:var(--ink);color:#fff;padding:10px 18px;border-radius:999px;font-size:.9rem;
  box-shadow:0 4px 18px rgba(0,0,0,.25);opacity:0;transition:opacity .25s,transform .25s;
  pointer-events:none;max-width:88vw;text-align:center;cursor:pointer}
.net-toast.show{opacity:1;transform:translate(-50%,0);pointer-events:auto}
.comp-chip{display:inline-block;margin:2px 0 14px;padding:6px 12px;border:1px solid var(--line);
  border-radius:999px;text-decoration:none;color:var(--ink);font-size:.9rem}
.comp-chip:hover{border-color:var(--accent)}

/* ── decks (/s/d — your own examples) ── */
.deck-actions{display:flex;gap:8px;margin-top:10px;flex-wrap:wrap}
.deck-actions .sbtn{flex:1;min-width:90px;text-align:center}
.deck-actions #deck-rec{flex:0 0 auto;min-width:48px;font-size:1.1rem}
.deck-drill-rec{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.deck-drill-rec .rec-btn{border:1px solid var(--line);border-radius:22px;flex:0 0 auto}
.deck-drill-rec .rec-btn.recording{border-color:var(--off)}
.deck-type{display:flex;gap:8px;flex:1;min-width:200px}
.deck-type .field{flex:1}

/* ── background passive player (/s/bg) ── */
.bg-track{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;
  text-align:left;border:0;background:none;cursor:pointer;font:inherit}
.bg-track.on{color:var(--accent)}
.bg-play-dot{font-size:.7rem;margin-right:8px;color:var(--accent)}
.bg-player{position:fixed;left:0;right:0;bottom:0;background:var(--card);border-top:1px solid var(--line);
  padding:10px 16px;display:flex;flex-direction:column;gap:8px;box-shadow:0 -2px 12px rgba(0,0,0,.06);z-index:20}
.bg-player[hidden]{display:none}   /* class display:flex would otherwise defeat [hidden] */
/* the picture, above the controls and edge to edge; capped so the shelf behind it
   stays visible — this is a listening screen that happens to show a video, not a cinema */
/* width, not flex-basis: basis 100% measures the padded content box, so the picture
   came up 32px short and the now-playing line squeezed in beside it instead of below */
.bg-stage{order:-1;width:calc(100% + 32px);margin:-10px -16px 0;background:#000;line-height:0}
.bg-stage[hidden]{display:none}
.bg-stage video{display:block;width:100%;max-height:34vh;object-fit:contain;background:#000}
.bg-now{min-width:0}
.bg-phrase{font-size:1.05rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bg-controls{display:flex;flex-direction:column;gap:8px;width:100%}
/* Play/Pause + Bookmark: the two controls a driver needs, equal-size square
   targets side by side (Vitaly, 2026-09-25: "make two square buttons: Play/Pause
   + Bookmark then smaller Skip Track and Skip Title") — never a bare glyph. */
.bg-controls-main{display:flex;gap:12px;width:100%;justify-content:center}
.bg-pbtn--sq{flex:0 0 96px;width:96px;height:96px;border-radius:16px;border:1px solid var(--line);
  background:var(--card);color:var(--ink);display:inline-flex;flex-direction:column;align-items:center;
  justify-content:center;gap:4px;padding:8px;font:inherit;font-weight:700;font-size:.86rem;cursor:pointer}
.bg-controls-main #bg-toggle{background:var(--accent);border-color:var(--accent);color:#fff;
  box-shadow:0 2px 8px rgba(255,71,0,.35)}
.bg-btn-ic{font-size:1.7rem;line-height:1;height:30px;display:flex;align-items:center}
.bg-btn-ic svg,svg.bg-btn-ic{width:30px;height:30px;display:block;flex:none}
.bg-note{margin:0;text-align:center;font-size:.82rem;color:var(--muted);min-height:1.1em}
.bg-note[hidden]{display:none}
.bg-controls-sub{display:flex;align-items:flex-start;justify-content:center;gap:6px;flex-wrap:wrap}
.bg-controls-sub .bg-pbtn{display:inline-flex;flex-direction:column;align-items:center;gap:2px;min-width:64px;min-height:48px}
.bg-sub-tx{font-size:.7rem;font-weight:600;color:var(--muted)}
.bg-pbtn{border:0;background:none;cursor:pointer;font-size:1.3rem;color:var(--ink);padding:6px 10px;line-height:1}
.bg-pbtn:disabled,.bg-pbtn--sq:disabled{opacity:.4;cursor:default}
.bg-speed{font-size:.9rem;font-weight:700;min-width:44px}

/* ── stories: per-idea breakdown (ideas/moves) ─────────────────────────── */
.ideas{margin:.6em 0 .2em}
.ideas-title{font-size:.72rem;text-transform:uppercase;letter-spacing:1px;color:var(--muted);margin-bottom:8px}
.idea{border:1px solid var(--line);border-left:3px solid var(--ok);border-radius:10px;padding:10px 12px;margin-bottom:8px;background:#fff}
.idea-fix{border-left-color:var(--off)}
.idea-head{display:flex;gap:8px;align-items:baseline}
.idea-mark{font-weight:700;flex-shrink:0}
.idea-ok .idea-mark{color:var(--ok)}
.idea-fix .idea-mark{color:var(--off)}
.idea-orig{line-height:1.45}
.idea-fix .idea-orig{color:var(--muted);text-decoration:line-through;text-decoration-color:var(--line)}
/* word-level diff: pinpoint the exact mistake instead of striking the whole line */
.idea-orig.has-diff{color:var(--ink);text-decoration:none}
.w-bad{background:#f7d9d4;color:#8c2d20;border-radius:3px;padding:0 2px;text-decoration:line-through;text-decoration-color:#c98a8a}
.w-new{background:#dcefe4;color:#0f6e4a;border-radius:3px;padding:0 2px}
.idea-corr{margin:.35em 0 0 22px;font-weight:600;color:var(--ink)}
.idea-corr::before{content:"\2192 ";color:var(--off)}
.idea-diag{margin:.3em 0 0 22px;font-size:.82rem;color:var(--muted)}
.idea-alts-label{margin:.6em 0 .3em 22px;font-size:.7rem;text-transform:uppercase;letter-spacing:.5px;color:var(--muted)}
/* Category rim colors — applied as a left border on the alt row / pick-opt */
:root{
  --cat-simple:     #0f7b8a;
  --cat-natural:    #1F9D55;
  --cat-creative:   #FF4700;
  --cat-emotional:  #b0418c;
  --cat-sophisticated: #5b53b0;
}
/* Suggestion = bordered rounded card; the category tag notches its top-left border. */
.idea-alt{position:relative;margin:.95em 0 .35em 12px;padding:.5em .7em .45em;font-size:.92rem;
  border:1px solid var(--line);border-radius:9px;background:var(--card)}
/* Tag = small corner badge — sits on the top border, offset so the rounded corner breathes. */
.alt-tag{position:absolute;top:-.62em;left:11px;font-size:.6rem;text-transform:uppercase;letter-spacing:.3px;
  font-weight:700;line-height:1.3;padding:0 5px;border-radius:4px;background:var(--card)}
.alt-simple{color:#0f7b8a}
.alt-natural{color:#1F9D55}
.alt-creative{color:#FF4700}
.alt-emotional{color:#b0418c}
.alt-sophisticated{color:#5b53b0}
.alt-text{line-height:1.4}
.alt-own{color:var(--ok)}
.alt-fix{color:var(--off)}
/* Activation section icons (hub-style) + the card-head left group they sit in. */
.scard-head .sh-l{display:flex;align-items:center;gap:12px;min-width:0}
.sec-ic{width:30px;height:30px;flex-shrink:0;color:var(--muted)}
/* Tool cards mirror the hub spoke: big icon left, title+sub stacked to its right.
   .scard.scard-spoke (0,2,0) must out-specify a.scard{display:block} (0,1,1). */
.scard.scard-spoke{display:flex;align-items:center;gap:16px}
.sec-body{flex:1;min-width:0}
/* Focus mode tiles: a <details> per mode, the summary is the spoke row, the
   list of works folds out under it. Marker hidden; the chevron turns when open. */
.focus-mode>summary{display:flex;align-items:center;gap:16px;cursor:pointer;list-style:none}
.focus-mode>summary::-webkit-details-marker{display:none}
.fm-chev{display:inline-block;transition:transform .15s}
.focus-mode[open] .fm-chev{transform:rotate(180deg)}
.fm-list{margin-top:12px;border-top:1px solid var(--line)}
.fm-work{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 2px;
  border-bottom:1px solid var(--line);text-decoration:none;color:inherit}
.fm-work:last-child{border-bottom:0;padding-bottom:2px}
.fm-work-title{font-weight:600;min-width:0}
.fm-add .fm-work-title{color:var(--accent)}
/* Check-phrase & How-to-say headers: same spoke row (icon + title/sub) above the input. */
.ax-head{display:flex;align-items:center;gap:16px;margin-bottom:14px}
/* Delete-recording control under a story attempt's audio. */
.rec-del{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);background:#fff;
  color:var(--muted);border-radius:8px;padding:4px 10px;font-size:.78rem;cursor:pointer}
.rec-del:hover{color:var(--off);border-color:var(--off)}
.rec-del:disabled{opacity:.5;cursor:default}
/* Star favourite: one path — outline (stroke) when off, filled when on, via currentColor. */
.star-btn .star-ic,.aam-star .star-ic{fill:none;stroke:currentColor;stroke-width:1.6;stroke-linejoin:round}
.star-btn.on .star-ic,.aam-star.on .star-ic{fill:currentColor;stroke:none}

/* ── stories detail: metric grid · improvement · idea-picker · compose ─── */
.metric-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:2px;background:var(--line);
  border:1px solid var(--line);border-radius:10px;overflow:hidden;margin:.2em 0 .6em}
.metric{display:flex;flex-direction:column;align-items:center;gap:2px;padding:10px 6px;background:var(--card)}
.metric-val{font-size:1.35rem;font-weight:700;font-variant-numeric:tabular-nums;line-height:1}
.metric-val.warn{color:var(--close)}
.metric-label{font-size:.66rem;text-transform:uppercase;letter-spacing:.5px;color:var(--muted)}
.imp-grid{display:flex;flex-wrap:wrap;gap:8px 18px}
.imp-stat{display:flex;flex-direction:column;gap:1px}
.imp-label{font-size:.68rem;text-transform:uppercase;letter-spacing:.5px;color:var(--muted)}
.imp-val{font-weight:600;font-variant-numeric:tabular-nums}
.imp-arrow{color:var(--muted);font-weight:400}
.story-attempt.latest{border-color:var(--accent)}
details.story-tx>summary,details.ideas-ro>summary{cursor:pointer;color:var(--accent);font-size:.85rem;
  font-weight:600;list-style:none;padding:.2em 0}
details.story-tx>summary::-webkit-details-marker,details.ideas-ro>summary::-webkit-details-marker{display:none}
details.story-tx>summary::before,details.ideas-ro>summary::before{content:"\25B8 ";color:var(--muted)}
details.story-tx[open]>summary::before,details.ideas-ro[open]>summary::before{content:"\25BE "}

/* interactive picker */
.idea-picker{margin:.6em 0 .2em}
.pick-card{border:1px solid var(--line);border-left:3px solid var(--ok);border-radius:10px;
  padding:10px 12px;margin-bottom:8px;background:#fff}
.pick-card.idea-fix{border-left-color:var(--off)}
.pick-options{display:flex;flex-direction:column;gap:4px;margin-top:8px}
.pick-opt{display:flex;align-items:baseline;gap:8px;padding:7px 9px;border:1px solid var(--line);
  border-left:3px solid transparent;border-radius:8px;cursor:pointer;font-size:.92rem;background:var(--bg)}
.pick-opt:hover{border-color:var(--accent)}
.pick-opt input{margin:0;flex-shrink:0;align-self:center;accent-color:var(--accent)}
.pick-opt:has(input:checked){border-color:var(--accent);background:#fff7f4}
/* Category rim on interactive picker options */
.pick-opt:has(.alt-simple){border-left-color:var(--cat-simple)}
.pick-opt:has(.alt-natural){border-left-color:var(--cat-natural)}
.pick-opt:has(.alt-creative){border-left-color:var(--cat-creative)}
.pick-opt:has(.alt-emotional){border-left-color:var(--cat-emotional)}
.pick-opt:has(.alt-sophisticated){border-left-color:var(--cat-sophisticated)}
.opt-text{line-height:1.4}
.pick-compose{margin-top:12px}
.composed-card{border:1px solid var(--ok);border-radius:10px;padding:12px;background:#f6fbf7}
.composed-preview{line-height:1.55;margin-top:6px;font-size:.98rem}
.composed-actions{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}

/* ── coach: who-knows-what knowledge grid ──────────────────────────────── */
.know-grid{width:100%;border-collapse:collapse;border:none;border-radius:0;background:transparent;font-size:.9rem}
.know-grid th{text-align:left;padding:8px 10px;border-bottom:2px solid var(--line);
  font-size:.7rem;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);font-weight:600}
.know-grid td{padding:9px 10px;border-bottom:1px solid var(--line);vertical-align:middle}
.know-grid tr:last-child td{border-bottom:none}
.know-grid th.know-col,.know-grid .know-cell{text-align:center;width:72px}
.know-phrase{line-height:1.4}
.know-yes{color:var(--ok);font-weight:700}
.know-no{color:#ccc;font-weight:700;font-size:1.1rem}
.advice-tag{font-size:.66rem;text-transform:uppercase;letter-spacing:.4px;font-weight:700;padding:2px 9px;
  border-radius:999px;border:1px solid var(--line);flex-shrink:0;white-space:nowrap}
.advice-not_started{color:var(--muted);background:#f3f3f2}
.advice-struggling{color:var(--off);border-color:#f0c8c8;background:#fdf3f3}
.advice-not_consolidating{color:var(--close);border-color:#eadcc0;background:#fdf8ee}
.advice-on_track{color:var(--ok);border-color:#bfe3c9;background:#f3fbf5}

/* ── activation: inline check-phrase (field + single mic→send action button) ── */
.ax-card{padding:14px}
.ax-check{display:flex;gap:8px;align-items:stretch;margin:0}
/* new unified layout: .ax-input is the field, .ax-action is the single button */
.ax-input{flex:1;height:50px;padding:0 15px;border:1px solid var(--line);border-radius:12px;
  font:inherit;background:var(--card);color:var(--ink);box-sizing:border-box;min-width:0}
.ax-input:focus{outline:none;border-color:var(--accent)}
.ax-action{flex-shrink:0;width:50px;border:1px solid var(--line);border-radius:12px;
  background:var(--card);color:var(--accent);cursor:pointer;
  display:flex;align-items:center;justify-content:center;padding:0;transition:background .15s,color .15s}
.ax-action:hover{border-color:var(--accent)}
.ax-action[data-mode="send"]{background:var(--accent);color:#fff;border-color:var(--accent)}
.ax-action.on,.ax-action.recording{background:var(--accent);color:#fff;border-color:var(--accent);animation:ax-pulse 1s infinite}
/* The single button shows exactly ONE glyph: mic while the field is empty, send
   once it holds text. data-mode is the ONLY mechanism — the same attribute that
   paints the button — so the glyph and the fill can never disagree.
   Do NOT go back to toggling the `hidden` attribute from JS here. `hidden` is an
   IDL property of HTMLElement; inline <svg> is an SVGElement, which gets dataset
   and tabIndex from the HTMLOrSVGElement mixin but NOT hidden. `icon.hidden = x`
   therefore sets a dead JS expando and never touches the attribute — so the send
   icon kept the `hidden` it was authored with and the mic never got one. That is
   the whole bug: the button turned orange (data-mode did apply) while still
   showing the mic. The 2026-07-08 note blaming Safari for "ignoring hidden on
   inline SVG" was a misdiagnosis — nothing ever asked it to. trainer.js dodged it
   independently with .style.display; CSS off data-mode is the version to keep. */
.ax-action[data-mode="send"] .ax-icon-mic{display:none}
.ax-action[data-mode="mic"]  .ax-icon-send{display:none}
/* A written line in Sandwich steps 1–2 has no button at all (2026-09-18). */
/* …and while it is recording it shows neither: it is a STOP square. Same reason
   as .rec-btn.recording above — the mic glyph mid-recording invites the tap that
   ends the take. Kept in CSS off .recording for the same reason the mic/send
   swap is: one mechanism, glyph and fill can never disagree. */
.ax-action.on .ax-icon,.ax-action.recording .ax-icon{display:none}
.ax-action.on::before,.ax-action.recording::before{content:"";display:block;
  width:15px;height:15px;border-radius:3px;background:currentColor;
  animation:ax-pulse 1.1s ease-in-out infinite}
/* A square that only changes colour reads as "the button broke", so the take
   never gets stopped and nothing is ever transcribed (Vitaly 2026-08-17). It
   stays a STOP square rather than reverting to a mic — the shape says what the
   next tap does — but it now visibly runs. */
@media (prefers-reduced-motion:reduce){
  .ax-action.on::before,.ax-action.recording::before{animation:none;opacity:.75}
}
/* .ax-field / .ax-submit / .ax-rec removed 2026-08-01 — they only ever styled
   Structures' second button, which is now the same single .ax-action control. */
@keyframes ax-pulse{50%{opacity:.55}}
.ax-result:empty{display:none}
.ax-result:not(:empty){border-top:1px solid var(--line);margin-top:12px;padding-top:10px}
/* S1 game scoreboard (a711) — total, streak, multiplier; one row, wraps on a phone. */
.s1g{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:0 0 8px}
.s1g-stat{display:flex;align-items:baseline;gap:5px}
.s1g-num{font-size:1.35rem;font-weight:700;font-variant-numeric:tabular-nums}
.s1g-mult{color:var(--accent)}
.s1g-lbl{font-size:.8rem;opacity:.7}
.s1g-new{margin-left:auto}
.s1g-next{margin:0 0 8px}
.s1g-next:empty{display:none}
.s1g-sit{border-left:3px solid var(--accent);padding:4px 0 4px 10px;margin:0 0 10px}
.s1g-sit-lbl{font-weight:700}
.s1g-sit-said{margin:.25em 0 0;font-style:italic}
.s1g-pts{font-weight:700;margin:0 0 .35em}
.s1g-pts.up{color:var(--accent)}
@keyframes s1g-pop{40%{transform:scale(1.25)}}
.s1g-num.pop{animation:s1g-pop .45s ease-out}
@media (prefers-reduced-motion:reduce){.s1g-num.pop{animation:none}}
/* Activation-mode per-student history block (under check + say-it cards). */
.hist-block{border-top:1px solid var(--line);margin-top:12px;padding-top:8px}
.hist-summary{cursor:pointer;color:var(--muted);font-size:.9rem;list-style:none;padding:2px 0}
.hist-summary::-webkit-details-marker{display:none}
.hist-summary::before{content:"▸ ";display:inline-block;transition:transform .1s}
details[open]>.hist-summary::before{transform:rotate(90deg)}
.hist-list{list-style:none;margin:6px 0 0;padding:0}
.hist-row{border-top:1px solid var(--line);padding:6px 0}
.hist-row:first-child{border-top:none}
.hist-row summary{cursor:pointer;list-style:none;display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.hist-row summary::-webkit-details-marker{display:none}
.hist-row .hist-ts{flex-shrink:0}
.hist-row .hist-src{font-weight:500}
.hist-row .hist-src-play{background:none;border:none;padding:0 2px;cursor:pointer;font-size:.8rem;color:var(--muted)}
.hist-row .hist-src-play:hover{color:var(--accent)}
/* Play YOUR OWN recording back. Deliberately not .hist-src-play: that one speaks
   the text with TTS (a model voice), this one is the student's actual voice, and
   two identical ▶ in one row would be a coin toss. The accent ring is the same
   affordance the recorder button uses, so "this is me" reads at a glance. */
.hist-row .hist-play{flex-shrink:0;background:none;cursor:pointer;font-size:.7rem;line-height:1;
  width:22px;height:22px;border-radius:50%;border:1px solid var(--accent);color:var(--accent);
  padding:0;display:inline-flex;align-items:center;justify-content:center}
.hist-row .hist-play:hover{background:var(--accent);color:#fff}
.hist-row .hist-play.playing{background:var(--accent);color:#fff}
/* Discard just the audio. Sits at the end of the row, quiet until hovered — the
   student is removing their voice, not the attempt. */
.hist-row .hist-rec-del{margin-left:auto;background:none;border:none;padding:0 2px;cursor:pointer;
  font-size:.9rem;line-height:1;color:var(--muted);opacity:.5}
.hist-row .hist-rec-del:hover{opacity:1;color:var(--close)}
/* "How to say" card — L2 pulldown sits between the input and the mic/send action. */
.si-l2{height:50px;padding:0 10px;border:1px solid var(--line);border-radius:12px;
  background:var(--card);color:var(--fg);font-weight:600;font-size:.95rem;cursor:pointer}
.si-l2:focus{outline:none;border-color:var(--accent)}
.si-sub{font-size:.82rem}
.si-list{list-style:decimal;padding-left:1.3em;margin:.2em 0}
.si-row{margin:.5em 0}
.si-l2t{font-size:1rem;line-height:1.35}
.si-tag{margin-left:.3em}
.si-note{margin-top:.15em}
/* thumb feedback buttons — same shape as .speak so the row's action cluster
   reads as one control group; :disabled state locks after send. */
.si-fb{flex-shrink:0;width:26px;height:26px;border-radius:50%;border:1px solid var(--line);
  background:var(--card);color:var(--fg);cursor:pointer;font-size:.75rem;line-height:1;
  margin-left:.25em;padding:0;opacity:.55}
.si-fb:hover:not(:disabled){opacity:1;border-color:var(--accent)}
.si-fb.on{opacity:1;background:var(--accent);color:#fff;border-color:var(--accent)}
.si-fb:disabled{cursor:default}
.si-fb-note{margin-top:.15em;font-size:.85em;color:var(--muted)}
.si-fb-note b{color:var(--fg)}
/* auto-save confirmation — pinned to the top so it's never scrolled above the fold */
.saved-toast{position:fixed;top:10px;left:50%;transform:translateX(-50%);z-index:60;
  background:var(--ok);color:#fff;padding:8px 18px;border-radius:999px;font-weight:600;
  box-shadow:0 6px 20px rgba(0,0,0,.22)}
.saved-toast[hidden]{display:none}
/* structures: language tiles → level-grouped accordions */
.struct-tiles{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:.4em 0}
.struct-tile{display:flex;flex-direction:column;justify-content:space-between;min-height:84px;
  padding:14px;border:1px solid var(--line);border-radius:var(--radius);background:var(--card);
  text-decoration:none;color:inherit}
.struct-tile:hover{border-color:var(--accent)}
.struct-tile-label{font-weight:600;font-size:1.02rem;line-height:1.25}
.struct-tile-meta{color:var(--muted);font-size:.82rem;margin-top:8px;font-variant-numeric:tabular-nums}
.struct-group{border-bottom:1px solid var(--line)}
.struct-group-sum{cursor:pointer;font-weight:600;padding:12px 2px;list-style:revert}
.brand-logo{height:1.4rem;display:block}  /* +33% — still under the 20px menu icons, so the nav's height is unchanged */
.brand{flex-shrink:0}
.brand-mark{display:none}   /* «vi», the phone's logo — see the top-row block at the end */
.struct-row{display:flex;align-items:center;gap:8px}
.struct-link{flex:1;text-decoration:none;color:inherit}
.struct-star{flex-shrink:0;border:0;background:none;cursor:pointer;font-size:1.25rem;color:#cfcfcf;
  padding:4px 8px;line-height:1;transition:opacity .2s}
.struct-star:hover{color:var(--accent)}
.struct-star.on{color:var(--accent)}
/* ── structure chips (inline under correction / alternatives / say-it variants) */
/* rs-star kept for star button shared by chips and structure list rows */
.rs-star{border:0;background:none;cursor:pointer;font-size:1rem;color:#cfcfcf;
  padding:2px 4px;min-width:32px;min-height:32px;line-height:1;
  transition:color .15s;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center}
.rs-star:hover{color:var(--accent)}
.rs-star.on{color:var(--accent)}
/* kp-star — the star on a SENTENCE (a correction, an alternative, an option);
   same look as the chip star so one glyph means one thing everywhere (a418) */
.kp-star{border:0;background:none;cursor:pointer;font-size:1rem;color:#cfcfcf;
  padding:2px 4px;min-width:32px;min-height:32px;line-height:1;vertical-align:middle;
  transition:color .15s;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center}
.kp-star:hover{color:var(--accent)}
.kp-star.on{color:var(--accent)}
/* chip container */
.sc-chips{display:flex;flex-wrap:wrap;gap:6px;margin:.4em 0 .2em}
/* Stories: chips wait behind the [S] pill (story_detail.html) */
.story-attempt .sc-chips{display:none}
body.story-structs-on .story-attempt .sc-chips{display:flex;margin:0 0 .4em 1.6em}
/* individual chip — pill shape */
.sc-chip{display:inline-flex;align-items:center;gap:2px;
  background:var(--card,#f5f5f5);border:1px solid var(--line,#e0e0e0);
  border-radius:999px;padding:2px 2px 2px 8px;font-size:.78rem;line-height:1.4;
  white-space:nowrap}
.sc-chip-title{color:var(--ink);font-weight:500}
.sc-chip-level{color:var(--muted,#888);margin-left:3px}
/* deprecated bottom-list rules — kept as no-ops so any cached HTML stays harmless */
.rs-list{list-style:decimal;padding-left:1.4em;margin:.2em 0 0}
.rs-row{display:flex;align-items:baseline;gap:4px;margin:.35em 0;flex-wrap:wrap}
.rs-title{color:var(--ink);font-size:.92rem}
.rs-level{margin-left:.2em}

/* ── Classic drill (/s/n) — guided speaking curriculum ───────────────────────── */
.drill-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px;margin-top:12px}
.drill-card{display:flex;flex-direction:column;gap:3px;padding:11px 12px;background:var(--card);
  border:1px solid var(--line);border-left:4px solid var(--line);border-radius:var(--radius);
  text-decoration:none;color:inherit;transition:box-shadow .15s,transform .05s}
.drill-card:hover{box-shadow:0 2px 10px rgba(0,0,0,.06)}
.drill-card:active{transform:translateY(1px)}
.drill-card.empty{opacity:.5}
.drill-card.complete{border-left-color:var(--ok)}
/* layer ramp — atoms → linking (a curriculum depth cue, not a score) */
.drill-card.layer-1{border-left-color:#9bbcd6}
.drill-card.layer-2{border-left-color:#5e9bd1}
.drill-card.layer-3{border-left-color:#d2691e}
.drill-card.layer-4{border-left-color:#b25fb2}
.drill-card.layer-5{border-left-color:#8a6d3b}
.drill-card-no{font-size:.72rem;color:var(--muted);letter-spacing:.04em}
.drill-card-name{font-weight:600;font-size:.95rem;line-height:1.2}
.drill-card-name-ua{font-size:.8rem;color:var(--muted);line-height:1.2}
.drill-mix{display:flex;height:4px;border-radius:2px;overflow:hidden;margin:5px 0 2px;background:var(--line)}
.drill-mix .m{display:block}
.drill-mix .m.c{background:#c98a00}.drill-mix .m.s{background:#d2691e}
.drill-mix .m.fr{background:#4a90d9}.drill-mix .m.f{background:#1f9d55}
.drill-card-meta{font-size:.74rem;color:var(--muted)}

/* task view */
.drill-topbar{gap:8px}
.drill-lesson-no{font-size:.78rem;color:var(--muted);letter-spacing:.04em;flex-shrink:0}
.stage-strip{display:flex;align-items:center;gap:5px;margin-left:auto}
.stage-cell{display:flex;align-items:center;justify-content:center;min-width:22px;height:22px;
  border-radius:6px;font-size:.72rem;color:#fff;text-decoration:none;opacity:.55;padding:0 4px}
.stage-cell.touched{opacity:.8}
.stage-cell.active{opacity:1;gap:3px;padding:2px 5px}
.stage-cell.off{opacity:.25;background:var(--line)!important;color:var(--muted)}
.stage-controlled{background:#c98a00}.stage-semi{background:#d2691e}
.stage-freer{background:#4a90d9}.stage-free{background:#1f9d55}
.stage-cell .edge{color:#fff;text-decoration:none;font-size:.95rem;line-height:1;padding:0 2px;opacity:.85}
.stage-cell .edge.off{opacity:.3;cursor:default}
.stage-cell .bars{display:flex;gap:2px}
.stage-cell .bars .bar{width:7px;height:9px;border-radius:2px;background:rgba(255,255,255,.45)}
.stage-cell .bars .bar.status-viewed{background:rgba(255,255,255,.7)}
.stage-cell .bars .bar.status-done{background:#fff}
.stage-cell .bars .bar.status-wrong{background:rgba(0,0,0,.3)}
.stage-cell .bars .bar.current{outline:1.5px solid #fff;outline-offset:1px}

.drill-task{max-width:var(--maxw);margin:0 auto}
/* Scene card — restored de-preview treatment: bordered card with a soft cream
   fill so it reads as "here's the scenario" rather than a muted footer note. */
.drill-scene{font-size:1rem;color:#5a4a2a;background:#faf6ec;border:1px solid #ebe2c8;
  border-radius:var(--radius);padding:14px 16px;margin:10px 0 18px;line-height:1.4}
.drill-exchange{display:flex;flex-direction:column;gap:14px;margin-bottom:16px}
.drill-row{display:flex;gap:14px;align-items:center}
.drill-row-text{flex:1;line-height:1.35}
.drill-role{display:block;font-size:.74rem;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}
.drill-row.prompt .l2{font-size:1.15rem;font-weight:600}
.drill-row.cue{align-items:flex-start}
.drill-row.cue .drill-row-text{font-size:.95rem}
.drill-cue-icon{font-size:1.6rem;line-height:1.2;flex-shrink:0;width:44px;text-align:center}
/* Exchange play button — restored 44px circular control from de-preview so the
   student can tap it easily on a phone. Smaller .speak (30px) is kept for the
   reveal block below where multiple alternatives share a tight row. */
.drill-row .speak{width:44px;height:44px;font-size:1.1rem;border-width:2px;border-color:var(--accent);color:var(--accent)}
.drill-row .speak:hover{background:var(--accent);color:#fff}
.speak{flex-shrink:0;width:30px;height:30px;border-radius:50%;border:1px solid var(--line);
  background:var(--card);color:var(--accent);cursor:pointer;font-size:.8rem;line-height:1}
.speak:hover{background:#fff5f0;border-color:var(--accent)}
.drill-vocab{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:14px}
/* Produce row — restored de-preview layout: prominent circular record button
   (48px) on the left, "or type" input on the right, both aligned so the
   record is unmissable as the primary action. */
.drill-produce{display:flex;gap:14px;align-items:center;flex-wrap:wrap;margin-top:6px}
.drill-produce .rec-btn{width:56px;height:56px;border-radius:50%;padding:0;border:2px solid var(--accent);
  background:#fff;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.drill-produce .rec-btn .rec-mic{color:var(--accent)}
.drill-produce .rec-btn.recording{background:#ffe9e0;border-color:var(--off)}
.drill-produce .rec-btn.recording .rec-mic{color:var(--off)}
.drill-produce .rec-time{position:absolute;transform:translateY(28px);font-size:.7rem;color:var(--off)}
.drill-type{display:flex;gap:6px;flex:1;min-width:180px}
.drill-type .field{flex:1}
.drill-reveal-btn{margin-top:12px;background:none;border:1px dashed var(--line);border-radius:var(--radius);
  color:var(--muted);padding:7px 12px;cursor:pointer;font-size:.85rem}
.drill-reveal-btn:hover{border-color:var(--accent);color:var(--accent)}
.drill-answer{margin-top:12px;padding:12px 14px;background:#f4f8f5;border:1px solid #d8ebe0;border-radius:var(--radius)}
.drill-model{display:flex;gap:9px;align-items:center;margin-bottom:4px}
.drill-model .l2.strong{font-weight:700;font-size:1.05rem}
.drill-alts{margin-top:8px;padding-top:8px;border-top:1px solid #d8ebe0}
.drill-alts-label{display:block;font-size:.74rem;color:var(--muted);margin-bottom:4px}
.drill-model.alt .l2{color:#3a6b4f}
.drill-foot{display:flex;align-items:center;justify-content:space-between;margin-top:18px}
.drill-done-btn{background:var(--ok);color:#fff;border:0;border-radius:var(--radius);
  padding:9px 18px;cursor:pointer;font-size:.9rem;font-weight:600}
.drill-done-btn:hover{filter:brightness(1.05)}
.drill-skip{color:var(--muted);text-decoration:none;font-size:.85rem;opacity:.8}
.drill-skip:hover{opacity:1;color:var(--accent)}

/* ── Coach manage (/c/m) — roster + course assignment ────────────────────────── */
.manage-add{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.manage-add .field{flex:1;min-width:140px}
.manage-courses{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0}
.chip-rm{display:inline}
.chip-x{border:0;background:none;cursor:pointer;color:var(--muted);font-size:1rem;line-height:1;padding:0 0 0 5px}
.chip-x:hover{color:var(--off)}
.manage-assign{display:flex;gap:6px;margin-top:8px}
.manage-assign .field{flex:1}

/* ── AI assistant (/s/h) — bounded support helper ────────────────────────────── */
.assistant-ask{display:flex;flex-direction:column;gap:8px}
.assistant-ask .field{width:100%;resize:vertical;font-family:inherit}
.assistant-ask-foot{display:flex;align-items:center;justify-content:space-between;gap:8px}
.assistant-notice{background:#fff7ec;border:1px solid #f0d9b5;border-radius:var(--radius);
  padding:8px 12px;font-size:.85rem;color:#8a6d3b;margin-bottom:10px}
.assistant-qa{display:flex;flex-direction:column;gap:5px}
.assistant-q{font-weight:600}
.assistant-a{white-space:pre-wrap;line-height:1.45}
.assistant-nudge{font-size:.85rem;color:var(--accent);opacity:.9}

/* ── analyzer popover: morphology line (spaCy UD features) ───────────────────── */
.lp-morph{display:flex;flex-wrap:wrap;gap:4px;margin:5px 0 3px}
.lp-morph-f{font-size:.7rem;background:#eef2f5;color:#4a5b6b;border-radius:4px;padding:1px 6px;cursor:help}

/* Structure examples — situation (context cue) small + faint, phrase prominent (v2 parity). */
.struct-examples{display:flex;flex-direction:column;gap:12px}
.struct-ex-row{display:flex;flex-direction:column;gap:2px}
.struct-ex-situation{font-size:.78rem;color:var(--muted);font-style:italic}
.struct-ex-situation-tr{font-size:.74rem;color:var(--muted);opacity:.85;margin-top:-1px;font-style:italic}
.struct-ex-phrase{font-size:1rem;font-weight:600;color:var(--ink)}
/* phrase-tr = L1 rendering of the target phrase. Same size/weight as the source
   so the eye reads it as an equal partner (not a subtitle); accent colour + a
   2px left rule makes it visually distinct from the situation caption above. */
.struct-ex-phrase-tr{font-size:1rem;font-weight:600;color:var(--accent);
  margin:2px 0 0 1.05em;padding-left:.6em;border-left:2px solid var(--accent);opacity:.95}
.struct-title-tr{font-size:.92rem;color:var(--muted);opacity:.85;margin:.15em 0 0;font-style:italic}
/* [T] toggle — translations hidden until #struct-page carries .t-armed */
#struct-page .struct-tr{display:none}
#struct-page.t-armed .struct-tr{display:block}
#struct-t-toggle.on{background:var(--accent);color:#fff}

/* ── Mobile responsive shell (≤560px) — phone-first tightening ───────────── */
@media (max-width: 560px) {
  :root { --pad: 12px; }
  html { font-size: 16px; }
  /* A-mode video bleeds to the screen edges on a phone (no side padding) */
  #aam-media { width: 100vw; margin: 0 calc(50% - 50vw) 10px; }
  .nav { padding: 9px 12px; gap: 10px; }
  .nav .links { gap: 12px; }
  .nav .activity-timer { padding: 3px 8px; font-size: .76rem; }
  /* pill row: closer together on a phone so the rungs keep to one row */
  .abc-row { gap: 4px; }
  .abc-pill { min-width: 30px; padding: 0 8px; }
  .subpills { gap: 4px; margin: 0 1px; }
  .subpill { width: 30px; height: 30px; }
  h1 { font-size: 1.35rem; }
  .topbar h1 { font-size: 1.25rem; }
  /* practice transport: tighter so the control row fits a phone; record wraps below */
  .transport { gap: 8px; margin: 14px 0 2px; }
  .ctrl.nav { width: 46px; height: 46px; font-size: 1.15rem; }
  .ctrl.play { width: 54px; height: 54px; font-size: 1.4rem; }
  .ctrl.speed { height: 46px; min-width: 46px; padding: 0 12px; }
  .ctrl.delay { height: 46px; min-width: 68px; padding: 0 10px; }
  .rec-btn, .play-attempt { padding: 10px 14px; }
  .subs-area { padding: 18px 42px; }
  .subs-text { font-size: 1.3rem; }
  .prev-cue { font-size: .95rem; }
  .comp-question { font-size: 1.05rem; }
  .aam-sent { font-size: 1.08rem; line-height: 1.6; }
  /* wide grids reflow to 2-up on a phone */
  .metric-grid { grid-template-columns: repeat(2, 1fr); }
  .deck-actions .sbtn { min-width: 0; }
}

/* Guesser (G · Вгадайка) + the Q/G companion toggle on the C view */
/* [CC] subtitles in Comprehension (C3–C5, 2026-09-17): the line under the playhead
   over the picture; words tappable → the dictionary card; a chunk the dictionary
   knows is underlined as ONE unit (first/last word round the ends). On an audio-only
   work the box has no picture, so the line sits in the box as plain text. */
.media-box .c-subs{position:absolute;left:0;right:0;bottom:30px;z-index:2;padding:26px 14px 6px;text-align:center;
  font-size:1.08rem;line-height:1.45;color:#fff;cursor:default;
  background:linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.72) 45%);text-shadow:0 1px 2px rgba(0,0,0,.85)}
.media-box .c-subs[hidden]{display:none}
.media-box:not(.has-video) .c-subs{position:static;color:var(--ink);background:none;text-shadow:none;padding:4px 10px 8px}
/* the scrubbing bar on the picture's lower edge (2026-09-17), under the subtitles */
.media-box .mc-bar{position:absolute;left:0;right:0;bottom:0;z-index:3;display:flex;align-items:center;gap:8px;
  padding:2px 10px 4px;background:linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.6));cursor:default}
.media-box .mc-bar .mc-time{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.85)}
.media-box .mc-bar .mc-seek{height:26px}
.media-box:not(.has-video){padding-bottom:30px}
.media-box:not(.has-video) .mc-bar{background:none}
.media-box:not(.has-video) .mc-bar .mc-time{color:var(--muted);text-shadow:none}
.c-subs .lookup-word{border-bottom:1px dotted rgba(255,255,255,.55);color:inherit;padding:0 1px}
.c-subs .lookup-word:hover{background:rgba(255,255,255,.18)}
.media-box:not(.has-video) .c-subs .lookup-word{border-bottom-color:#c4c4c4}
.media-box:not(.has-video) .c-subs .lookup-word:hover{background:#fdf0e9}
.c-subs .lookup-word.in-chunk{border-bottom:2px solid var(--accent);padding-bottom:1px;background:rgba(255,71,0,.14)}
.c-subs .lookup-word.chunk-start{border-top-left-radius:4px;border-bottom-left-radius:4px;padding-left:3px}
.c-subs .lookup-word.chunk-end{border-top-right-radius:4px;border-bottom-right-radius:4px;padding-right:3px}
.c-subs .lookup-word.is-active{background:#2f6df6;color:#fff;border-radius:3px}
/* C5 — tap a word, hide its chunk, guess from context (a505, 2026-09-24).
   Plain-text line in the ladder card (not over the picture, unlike [CC]) — a
   known chunk is underlined the same way [CC] already does, so the visual
   language is one thing across C3–C5, not two. */
.c5-line{font-size:1.1rem;line-height:1.6;margin:4px 0 12px}
.c5-line .lookup-word{border-bottom:1px dotted #c4c4c4;padding:0 1px;cursor:pointer}
.c5-line .lookup-word:hover{background:#fdf0e9}
.c5-line .lookup-word.in-chunk{border-bottom:2px solid var(--accent);padding-bottom:1px;background:rgba(255,71,0,.14)}
.c5-line .lookup-word.chunk-start{border-top-left-radius:4px;border-bottom-left-radius:4px;padding-left:3px}
.c5-line .lookup-word.chunk-end{border-top-right-radius:4px;border-bottom-right-radius:4px;padding-right:3px}
.c5-line .lookup-word.c5-blank{border-bottom-style:solid;color:var(--muted);cursor:default;pointer-events:none}
.c5-hint{color:var(--muted);font-size:.92rem}
/* «Поясни» (a844) — a small pill in the picture's top-right corner, clear of the
   subtitle line along the bottom (on stage it sat ON the line and hid words);
   c_mode.js shows it only while subs are on at C3-C5 and a line is up. */
.media-box .mc-explain{position:absolute;right:10px;top:10px;z-index:3;border:1px solid rgba(255,255,255,.55);
  background:rgba(0,0,0,.45);color:#fff;border-radius:999px;padding:4px 12px;font:inherit;font-size:.82rem;cursor:pointer}
.media-box .mc-explain:hover{background:rgba(0,0,0,.65)}
.media-box .mc-explain[hidden]{display:none}
.media-box:not(.has-video) .mc-explain{position:static;display:inline-block;margin:2px 0 8px;
  border-color:var(--line);background:#fff;color:var(--ink)}
/* the panel it opens — under the player, above the ladder */
.c-explain-panel{max-width:560px;margin:10px auto 16px;padding:12px 30px 12px 14px;
  border:1px solid var(--line);border-radius:10px;background:#fff;position:relative}
.c-explain-panel[hidden]{display:none}
.c-explain-close{position:absolute;top:5px;right:9px;border:0;background:none;font-size:1.2rem;color:var(--muted);cursor:pointer;line-height:1}
.c-explain-body{line-height:1.5;min-height:1.4em}
.c-explain-loading,.c-explain-fail{color:var(--muted);margin:0}
.c-explain-fail{color:var(--off)}
.c-explain-answer{margin:0}
.c-explain-ask{display:flex;gap:8px;margin-top:10px}
.c-explain-ask input{flex:1;min-width:0;padding:7px 10px;border:1px solid var(--line);border-radius:8px;font:inherit}
.g-title{font-weight:600}
.g-sentence{font-size:1.2rem;line-height:1.7}
.g-sentence u{color:var(--ok);text-decoration:none;border-bottom:2px solid var(--ok);font-weight:600}

/* Pronunciation lab (P · Вимова) */
.pron-phrase{font-size:1.5rem;font-weight:500;text-align:center;margin:1em 0 .4em}
.pron-line{font-size:1.25rem;line-height:1.7;text-align:center;margin:.4em 0}
.pron-line .pron-ok{color:var(--ink)}
.pron-line .pron-bad{background:#ffe9b3;border-bottom:2px solid var(--close);border-radius:5px;padding:0 3px}
.pron-note{text-align:center;font-weight:600;color:var(--close);margin:.3em 0}
.pron-note.pron-clean{color:var(--ok)}
.pron-line .pron-sound{border-bottom:2px dotted var(--close);cursor:pointer}
.pron-line .pron-sound.on{background:#fff3cf;border-radius:5px;padding:0 3px}
.pron-slip{border-left:3px solid var(--close);padding:.2em .7em;margin:.5em 0}
.pron-slip p{margin:.2em 0}
.pron-tune-box{margin:.8em 0 .4em}
.pron-h4{margin:.4em 0 .2em;font-size:.8rem;letter-spacing:.08em;color:var(--muted);text-transform:uppercase}
.pron-tune{display:block;width:100%;margin:.2em 0}
.pron-tune-lines{padding-left:1.2em;margin:.3em 0}
.pron-tune-lines li{margin:.15em 0}
.pron-remedy{margin:.8em 0 .2em}
.pview .rec-btn.recording{background:#ffe9e0;border-color:var(--off)}

/* UnChew (U) — adaptive verdict toggle + panel */
.u-btn.on{background:var(--accent);color:#fff;border-color:var(--accent)}
.fb-unchew{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:10px 0 0;padding:8px 12px;
  border-radius:10px;background:#faf7f4;border:1px solid var(--line)}
.fb-unchew.ok{border-color:var(--ok);background:#eafaf0}
.fb-unchew .uc-stage{font-weight:600;font-variant-numeric:tabular-nums}
.fb-unchew .uc-nudge{color:var(--muted);font-size:.9rem}

/* ── U overlay (UnChew · Жуйка) — 4-stage per-sentence pronunciation dive ───── */
body.uo-locked{overflow:hidden}
.uo-backdrop{position:fixed;inset:0;background:rgba(15,17,21,.55);z-index:60}
.uo-sheet{position:fixed;z-index:61;left:50%;top:50%;transform:translate(-50%,-50%);
  width:min(560px,94vw);max-height:92vh;overflow:auto;background:var(--card);color:var(--ink);
  border-radius:16px;box-shadow:0 18px 60px rgba(0,0,0,.4);padding:18px 18px 22px}
@media (max-width:560px){.uo-sheet{top:auto;bottom:0;transform:translateX(-50%);width:100vw;
  border-radius:16px 16px 0 0;max-height:88vh}}
.uo-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}
.uo-title{font-weight:700;font-size:1.05rem}
.uo-x{border:0;background:transparent;font-size:1.2rem;cursor:pointer;color:var(--muted);padding:4px 8px}
.uo-sentence{font-size:1.15rem;line-height:1.45;margin:.2em 0 .8em}
.uo-tabs{display:flex;gap:6px;margin-bottom:12px;flex-wrap:wrap}
.uo-tab{flex:1;min-width:64px;border:1px solid var(--line);background:#fff;border-radius:9px;
  padding:7px 6px;font-size:.82rem;cursor:pointer;color:var(--muted);font-weight:600}
.uo-tab.is-on{background:var(--accent);color:#fff;border-color:var(--accent)}
.uo-pane{display:block}
.uo-pane[hidden]{display:none}   /* a743: without this every step showed at once */
.uo-hint{color:var(--muted);font-size:.9rem;line-height:1.4;margin:.4em 0 .7em}
.uo-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:.4em 0}
.uo-play,.uo-rec{border:1px solid var(--line);background:#fff;border-radius:10px;padding:10px 16px;
  font-size:1rem;font-weight:600;cursor:pointer;color:var(--ink)}
.uo-play{background:var(--accent);color:#fff;border-color:var(--accent)}
.uo-rec.is-recording{background:var(--off);color:#fff;border-color:var(--off)}
.uo-mine{background:#fff;color:var(--ink)}
.uo-speeds{display:flex;gap:6px}
.uo-sp{border:1px solid var(--line);background:#fff;border-radius:8px;padding:6px 10px;font-size:.85rem;cursor:pointer}
.uo-sp.is-on{background:var(--ink);color:#fff;border-color:var(--ink)}
.uo-time{font-variant-numeric:tabular-nums;color:var(--muted)}
.uo-track{height:8px;background:var(--line);border-radius:6px;overflow:hidden;margin:.5em 0}
.uo-fill{height:100%;width:0;background:var(--accent);transition:width .1s linear}
.uo-pace{background:var(--ok)}
.uo-bars{display:flex;gap:6px;margin:.6em 0}
.uo-bar{flex:1;height:14px;border-radius:4px;background:var(--line)}
.uo-bar.is-on{background:var(--ok)}
.uo-tab.is-done::after{content:" ✓"}
/* a748: one tile per take — grey while being checked, then ✓ / ✗ with why */
.uo-takes{display:flex;flex-wrap:wrap;gap:6px;margin:.3em 0 .2em}
.uo-take{font-size:.8rem;padding:3px 8px;border-radius:999px;border:1px solid var(--line);
  color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
.uo-take.is-wait{animation:uo-wait 1.2s ease-in-out infinite}
.uo-take.is-ok{background:var(--ok);border-color:var(--ok);color:#fff}
.uo-take.is-no{border-color:var(--off);color:var(--off)}
.uo-take.is-set{border-color:var(--ink);color:var(--ink)}
@keyframes uo-wait{50%{opacity:.45}}
.uo-count{flex:0 0 auto;align-self:center;color:var(--muted);font-size:.85rem;font-variant-numeric:tabular-nums}
/* a743: the green zone is where the take must end; the dark line is the clock. */
.uo-ztrack{position:relative;height:14px}
.uo-zone{position:absolute;top:0;bottom:0;left:0;width:0;background:rgba(31,157,85,.35)}
.uo-ztrack .uo-pace{position:absolute;left:0;top:5px;height:4px;background:var(--ink);border-radius:2px}
.uo-k{transition:color .08s}
.uo-k.is-lit{color:var(--accent);font-weight:600}
.uo-window{margin:.3em 0}
.uo-nudge{color:var(--close);font-size:.95rem;min-height:1.2em;margin:.5em 0 0}
.uo-pillows{display:flex;gap:8px;margin:.3em 0}
.uo-pill{flex:1;border:1px solid var(--line);background:#fff;border-radius:10px;padding:10px 0;
  font-size:1.05rem;font-weight:700;cursor:pointer}
.uo-pill.is-on{background:var(--accent);color:#fff;border-color:var(--accent)}
.uo-note{margin:.4em 0 0}
@keyframes uo-shake{10%,90%{transform:translateX(-1px)}30%,70%{transform:translateX(2px)}50%{transform:translateX(-3px)}}
.uo-shake{animation:uo-shake .4s}

/* A part of the line, said on its own (a490): the words she has said and been
   graded on stay coloured inside the line — done (green) / close (amber). The
   status line offers ↺ back to the top while she is paused mid-line. */
.subs-text .lookup-word.part-done{background:#dff3e7;color:var(--ok);border-radius:3px;border-bottom-color:transparent}
.subs-text .lookup-word.part-close{background:#fbf0d3;color:var(--close);border-radius:3px;border-bottom-color:transparent}
.subs-text .lookup-word.part-done.is-active,.subs-text .lookup-word.part-close.is-active{background:#2f6df6;color:#fff}
.rec-status .part-restart{border:0;background:none;padding:0;font:inherit;color:var(--accent);cursor:pointer}
.fb-part .fb-score .fb-verdict{color:var(--ink)}
/* Mode B coaching nudge — non-blocking overlay (B1>B2>B3 + the loop instruction) */
.bg-overlay{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;
  background:rgba(0,0,0,.45);padding:1rem}
.bg-card{position:relative;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  max-width:24rem;width:100%;padding:1.1rem 1.2rem;box-shadow:0 10px 28px rgba(0,0,0,.18)}
.bg-x{position:absolute;top:.5rem;right:.6rem;background:none;border:0;cursor:pointer;color:var(--muted);font-size:1rem;line-height:1}
.bg-steps{display:flex;align-items:center;gap:.4rem;margin:.2rem 0 .8rem}
.bg-step{font-size:.8rem;font-weight:600;color:var(--muted);padding:2px 10px;border:1px solid var(--line);border-radius:999px}
.bg-step.on{color:#fff;background:var(--accent);border-color:var(--accent)}
.bg-sep{color:var(--muted)}
.bg-text{font-size:.9rem;line-height:1.6;color:var(--ink);margin:0 0 1rem}
.bg-actions{display:flex;gap:.5rem}
.bg-go,.bg-stay{flex:1;text-align:center;padding:.55rem .8rem;border-radius:.6rem;font-size:.9rem;cursor:pointer;text-decoration:none}
.bg-go{background:var(--accent);color:#fff;border:0}
.bg-stay{background:none;border:1px solid var(--line);color:var(--ink)}

/* Policy pages (/privacy + /terms) — long-form legal copy. Constrain width,
   comfortable line-height, gentle heading hierarchy, sticky footer feel. */
.policy{max-width:720px;margin:24px auto 64px;padding:0 20px;line-height:1.65;color:var(--ink)}
.policy .policy-meta{color:var(--muted);font-size:.85rem;margin:0 0 20px}
.policy h1{font-size:2rem;line-height:1.15;margin:0 0 24px;color:var(--ink)}
.policy h2{font-size:1.3rem;line-height:1.2;margin:36px 0 12px;color:var(--ink)}
.policy h3{font-size:1.05rem;margin:22px 0 8px;color:var(--ink)}
.policy p,.policy ul,.policy ol{margin:0 0 16px}
.policy ul,.policy ol{padding-left:24px}
.policy li{margin:0 0 6px}
.policy code{background:#f2f1ee;border-radius:4px;padding:1px 5px;font-size:.9rem}

/* ── daily self-report wizard (/s/report) — flagged VA_DAILY_REPORT ─────────── */
.rep-dots{display:flex;gap:6px;justify-content:center;margin:0 0 1.2em}
.rep-dot{width:8px;height:8px;border-radius:50%;background:var(--line)}
.rep-dot.on{background:var(--accent)}
.rep-step textarea.field{width:100%;resize:vertical;font-family:inherit}
.policy a{color:var(--accent)}

/* ── trainer (/s/t) — conversational AI speaking trainer ─────────────────── */
.trainer-topbar{gap:12px}
/* On a phone the bar is ← · title · language on one row and the help picker with
   its [+] on the next. Held on one row it measured 603px wide on a 356px phone,
   and a phone's browser answers a page wider than itself by zooming the whole
   page out — the "desktop view on my phone" a student reported (a745, 2026-09-23). */
@media (max-width:560px){
  .trainer-topbar{flex-wrap:wrap;row-gap:8px}
  .trainer-l2pick{order:1;margin-left:auto}
  .trainer-assist{order:2;margin:0}
  .trainer-plus{order:3;margin:0 auto 0 0}
}
.trainer-title{font-weight:600;font-size:1.15rem}
.trainer-l2pick{display:inline-flex;align-items:center}
.trainer-l2pick select{font:inherit;font-size:.85rem;padding:4px 8px;border:1px solid var(--line);border-radius:8px;background:#fff;color:var(--ink);cursor:pointer}
.trainer{display:grid;grid-template-columns:220px 1fr;gap:18px;min-height:70vh}
@media (max-width:640px){.trainer{grid-template-columns:1fr}.trainer-sessions{max-height:180px}}
.trainer-sessions{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:10px;display:flex;flex-direction:column;overflow:auto}
.trainer-sess-head{display:flex;align-items:center;justify-content:space-between;padding:4px 6px 10px;font-weight:600;color:var(--muted);font-size:.8rem;letter-spacing:.06em;text-transform:uppercase}
.trainer-sess-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}
.tr-sess{display:flex;align-items:center;border-radius:8px;padding:2px 4px}
.tr-sess.active{background:#f2f1ee}
.tr-sess-open{flex:1;min-width:0;border:0;background:transparent;text-align:left;cursor:pointer;padding:6px 6px;font:inherit;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tr-sess-actions{display:flex;gap:2px;opacity:0;transition:opacity .12s}
.tr-sess:hover .tr-sess-actions,.tr-sess.active .tr-sess-actions{opacity:1}
.tr-sess-rn,.tr-sess-rm{border:0;background:transparent;color:var(--muted);cursor:pointer;padding:2px 6px;border-radius:6px;font-size:.9rem}
.tr-sess-rn:hover,.tr-sess-rm:hover{background:#fff;color:var(--ink)}
.tr-sess-empty{padding:10px 6px}
.trainer-chat{display:flex;flex-direction:column;gap:10px;min-height:0}
.trainer-log{flex:1;min-height:340px;max-height:60vh;overflow-y:auto;background:var(--card);border:1px solid var(--line);border-radius:12px;padding:14px;display:flex;flex-direction:column;gap:10px}
.tr-bubble{display:flex;align-items:flex-start;gap:8px;max-width:85%;padding:10px 14px;border-radius:14px;line-height:1.4}
.tr-bubble.tr-student{align-self:flex-end;background:#eef4ff;border-bottom-right-radius:4px}
.tr-bubble.tr-ai{align-self:flex-start;background:#fff;border:1px solid var(--line);border-bottom-left-radius:4px}
.tr-bubble .speak{border:0;background:transparent;cursor:pointer;color:var(--muted);font-size:.9rem;padding:0;flex-shrink:0;line-height:1}
.tr-bubble .speak:hover{color:var(--accent)}
.tr-txt{white-space:pre-wrap}
.tr-recast{align-self:flex-end;font-size:.85rem;color:var(--muted);padding:2px 8px;max-width:85%;text-align:right}
.tr-recast-corr{color:var(--accent);font-weight:500}
/* ── things to talk about — the strip an empty conversation opens on ── */
.tr-starters{align-self:stretch;display:flex;flex-direction:column;gap:8px;margin:auto 0}
.tr-starters-head{margin:0 0 2px;color:var(--muted);font-size:.8rem;letter-spacing:.06em;text-transform:uppercase;font-weight:600}
.tr-starter{display:flex;flex-direction:column;gap:2px;text-align:left;font:inherit;cursor:pointer;background:#fff;border:1px solid var(--line);border-radius:12px;padding:10px 14px;line-height:1.4;transition:border-color .12s,background .12s}
.tr-starter:hover{border-color:var(--accent);background:#fffaf7}
.tr-starter-label{color:var(--muted);font-size:.8rem}
.tr-starter-q{color:var(--ink)}
.tr-starters-more{align-self:flex-start;margin-top:2px}
/* ── trainer structure reference (Full assist only) ── */
.tr-struct-ref{display:inline-flex;align-items:center;gap:4px;margin-top:4px;padding:1px 4px 1px 10px;border:1px solid var(--line);border-radius:999px;background:var(--card);font-size:.8rem;line-height:1.5}
.tr-struct-frame{color:var(--ink);font-weight:500}
.tr-struct-ref .struct-star{font-size:1.05rem}
.tr-scaffold{align-self:stretch;background:#fbf7ea;border:1px solid #ecdfaa;border-left:3px solid var(--accent);border-radius:10px;padding:10px 14px;font-size:.9rem;display:flex;flex-direction:column;gap:8px}
.tr-sc-row{line-height:1.4}
.tr-sc-row b{color:var(--accent);margin-right:6px;font-weight:600}
.tr-sc-word{display:inline-block;margin:2px 4px 2px 0;padding:2px 8px;border-radius:12px;background:#fff;border:1px solid #ecdfaa;font-size:.85rem}
/* Assist picker + [+] are centred as a PAIR: the auto margin sits on the left
   of the picker and the right of [+], so adding the button didn't shove the
   whole group off-centre (VIT-152). */
.trainer-assist{display:inline-flex;align-items:center;gap:6px;flex-shrink:0;margin:0 0 0 auto}
.trainer-plus{margin:0 auto 0 6px;flex-shrink:0;width:26px;height:26px;padding:0;border:1px solid var(--line);border-radius:50%;background:#fff;color:var(--muted);cursor:pointer;font-size:1rem;line-height:1;font-weight:600;user-select:none;transition:background .12s,border-color .12s,color .12s}
.trainer-plus:hover{border-color:var(--muted)}
.trainer-plus.on{background:var(--accent);border-color:var(--accent);color:#fff}
.trainer-assist-label{color:var(--muted);font-size:.7rem;letter-spacing:.05em;text-transform:uppercase;font-weight:600;margin-right:2px}
.assist-seg{position:relative;padding:3px 10px;border:1px solid var(--line);background:#fff;cursor:pointer;font-size:.8rem;user-select:none;transition:background .12s,border-color .12s,color .12s}
.assist-seg input{position:absolute;opacity:0;pointer-events:none;width:0;height:0}
.assist-seg:first-of-type{border-radius:14px 0 0 14px}
.assist-seg:last-of-type{border-radius:0 14px 14px 0}
.assist-seg:not(:first-of-type){margin-left:-1px}
.assist-seg:hover{border-color:var(--muted);z-index:1}
.assist-seg:has(input:checked),.assist-seg.on{background:var(--accent);border-color:var(--accent);color:#fff;z-index:2}
.trainer-produce{display:flex;gap:8px;align-items:stretch;margin:0}


/* ── assigned structures — coach board chips + per-student picker ── */
.asg-struct{margin-top:14px;border-top:1px solid var(--line);padding-top:10px}
.asg-struct-head{display:flex;align-items:center;gap:10px;margin-bottom:6px}
.asg-chips{display:flex;gap:8px;flex-wrap:wrap}
.asg-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 6px 4px 10px;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
.asg-chip-t{font-weight:600;font-size:.92rem}
.asg-chip-n{font-variant-numeric:tabular-nums;font-size:.82rem;color:var(--accent);
  padding:1px 6px;border-radius:999px;background:rgba(255,71,0,.08)}
.asg-chip-n.zero{color:var(--muted);background:transparent}
.asg-chip-x{border:0;background:none;color:var(--muted);cursor:pointer;font-size:.85rem;padding:0 2px}
.asg-chip-x:hover{color:var(--close)}
.asg-langs{display:flex;gap:8px;margin:.4em 0 10px}
.asg-search{width:100%;padding:9px 12px;border:1px solid var(--line);
  border-radius:var(--radius);background:var(--card);margin:.2em 0 12px}
.asg-group{margin-bottom:14px}
.asg-group-h{font-size:.8rem;text-transform:uppercase;letter-spacing:.04em;
  color:var(--muted);margin-bottom:6px}
.asg-rows{display:flex;flex-direction:column;gap:4px}
.asg-row-b{display:flex;align-items:center;gap:8px;width:100%;text-align:left;
  padding:8px 12px;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--card);cursor:pointer;font:inherit;color:inherit}
.asg-row-b:hover{border-color:var(--muted)}
.asg-row-b.active{border-color:var(--accent)}
.asg-row-t{flex:1}
.asg-row-m{color:var(--muted);font-weight:600}
.asg-row-b.active .asg-row-m{color:var(--accent)}

/* ── structures landing — what the coach assigned ── */
.struct-assigned{margin:.4em 0 16px;padding:12px 14px;border:1px solid var(--accent);
  border-radius:var(--radius);background:var(--card)}
.struct-assigned-h{font-weight:600;margin-bottom:2px}
.struct-assigned-row{display:flex;align-items:baseline;gap:10px;padding:8px 0;
  border-top:1px solid var(--line);text-decoration:none;color:inherit}
.struct-assigned-t{flex:1;font-weight:600}
.struct-assigned-n{font-size:.82rem;color:var(--muted);font-variant-numeric:tabular-nums}

/* ── coach: the sentences behind the count ── */
.asg-chip-before{font-size:.78rem;color:var(--muted)}
.asg-chip-see{border:0;background:none;color:var(--accent);cursor:pointer;
  font:inherit;font-size:.8rem;text-decoration:underline;padding:0 2px}
.asg-ex{width:100%}
.ex-none{margin:6px 0 0}
.ex-list{list-style:none;margin:8px 0 0;padding:0;display:flex;flex-direction:column;gap:6px}
.ex-row{border-left:2px solid var(--ok,#16a34a);padding:6px 0 6px 10px}
/* A sentence that missed the pattern is the one to look at, so it is marked —
   not hidden, and not scored. */
.ex-row.miss{border-left-color:var(--close,#b91c1c)}
.ex-text{font-size:.95rem;line-height:1.35}
.ex-marks{display:flex;gap:8px;flex-wrap:wrap;align-items:baseline;margin-top:2px}
.ex-mark{font-size:.72rem;padding:1px 6px;border-radius:999px;background:var(--bg)}
.ex-mark.ok{color:var(--ok,#16a34a)}
.ex-mark.no{color:var(--close,#b91c1c)}
.ex-mark.unknown,.ex-mark.quiet{color:var(--muted)}
.ex-when{font-size:.72rem;color:var(--muted);margin-left:auto}
.ex-corr{font-size:.85rem;color:var(--ink);margin-top:2px}
.ex-expl{font-size:.8rem;color:var(--muted);margin-top:1px}

/* Word banks on a declension card's structure page (VIT-385 follow-up). A card
   is a machine: these are the pools its sentences are built from, printed the
   way the card prints them. Wrapping chips, not a list — the point is to scan
   a bank and pick, not to read it top to bottom. */
.card-pool{margin:.6rem 0}
.card-pool-name{font-size:.72rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--muted);margin-bottom:.3rem}
.card-pool-items{display:flex;flex-wrap:wrap;gap:5px}
.card-pool-word{display:inline-block;padding:3px 9px;border-radius:999px;
  background:rgba(128,128,128,.12);font-size:.86rem;line-height:1.35}
/* Sentences drawn from the banks sit slightly back from the authored example,
   which is the one with a scene behind it. */
.struct-ex-drawn{opacity:.82}
.cta-link{display:inline-block;margin-top:.7rem;font-size:.9rem;text-decoration:none;
  color:var(--accent);font-weight:600}

/* A bank word is two targets: the word opens its meaning, the number is the
   student's own "I used this" tally (observations, never a score). */
.card-pool-word{display:inline-flex;align-items:stretch;border-radius:999px;overflow:hidden;
  background:rgba(128,128,128,.12)}
.card-pool-word .cpw-word{border:0;background:transparent;color:inherit;cursor:pointer;
  font:inherit;font-size:.86rem;line-height:1.35;padding:3px 7px 3px 9px}
.card-pool-word .cpw-n{border:0;border-left:1px solid rgba(128,128,128,.25);cursor:pointer;
  background:transparent;color:var(--muted);font:inherit;font-size:.72rem;padding:3px 8px;
  font-variant-numeric:tabular-nums;min-width:26px}
.card-pool-word .cpw-n.on{color:var(--accent);font-weight:700}
/* The sentences the banks above produce. Read top to bottom, unlike the pools,
   so a plain list with room between the lines — the pattern repeats in every one
   of them and the eye needs the gap to see the fillers move. */
.card-sentences{list-style:none;margin:.2rem 0 0;padding:0}
.card-sentences li{padding:.28rem 0;line-height:1.45;border-bottom:1px solid var(--line)}
.card-sentences li:last-child{border-bottom:0}
.cpw-pop{position:absolute;z-index:40;max-width:250px;padding:8px 11px;border-radius:10px;
  background:var(--card);border:1px solid var(--line);box-shadow:0 6px 20px rgba(0,0,0,.13);
  font-size:.86rem;line-height:1.4}

/* ── exams (/s/exam — CILS prepare drill + train simulation) ────────────────
   The exam screens shipped with no styles at all: three answers ran together
   as one inline paragraph, the A/B/C letters sat inside the sentence, and a
   verdict was plain black text. On a phone that reads as a wall, which is how
   a student ends up tapping the same option twice and reporting the exam as
   broken (VIT-467). Same tokens as the rest of the app — no new palette. */
.exam-mcq-options{display:flex;flex-direction:column;gap:8px;margin:10px 0}
.exam-mcq-label{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;
  background:var(--card);border:1px solid var(--line);border-radius:10px;cursor:pointer;
  line-height:1.4}
.exam-mcq-label:has(input:checked){border-color:var(--accent);
  box-shadow:inset 0 0 0 1px var(--accent)}
.exam-mcq-radio{margin-top:.28em;flex-shrink:0}
.exam-mcq-letter{font-weight:700;color:var(--muted);flex-shrink:0;min-width:1.1em}
.exam-item-prompt{font-weight:600;margin:.2em 0 .4em}
.exam-passage{line-height:1.6}
.exam-passage p{margin:0 0 .6em}
/* Right and wrong have to read at a glance, and colour alone must not be the
   whole signal — the words say it too. */
.exam-item-verdict{padding:9px 12px;border-radius:10px;font-weight:600;
  background:rgba(128,128,128,.10)}
.exam-item-verdict.verdict-correct{background:rgba(31,157,85,.12);color:var(--ok)}
.exam-item-verdict.verdict-wrong{background:rgba(178,59,59,.12);color:var(--off)}
.exam-item-verdict.verdict-unavailable{color:var(--muted)}
.exam-matching-labels li{line-height:1.45;padding:6px 0;border-bottom:1px solid var(--line)}
.exam-matching-labels li:last-child{border-bottom:0}
.exam-matching-text{line-height:1.4}
.exam-item-image{display:block;width:100%;max-width:520px;height:auto;
  border-radius:10px;border:1px solid var(--line);margin:10px 0}

/* ── Сендвіч (/s/sw) — three steps, one active button ────────────────────────
   Each step is a heading and its rows; every row is the shared .ax-check control
   (input + one action button that is a mic while empty and a paper plane once it
   holds two words). Sending a row hardens it into plain text; the next field is
   already there, because it appeared the moment the previous one held two words.
   Visibility is driven off data-mode and classes, never off `hidden` alone —
   .ax-action and the flex boxes below carry display:flex, which the attribute
   cannot outrank; that is exactly why the old «Далі» never went away. */
.sw-card{padding-top:.6rem}
.sw-step{margin-top:1rem}
.sw-step:first-child{margin-top:.2rem}
.sw-h{margin:0 0 .45rem;font-size:.95rem;line-height:1.35;font-weight:600}
/* Step 3 is the other language: it sits in its own tinted block so the change
   of step is seen before it is read. */
.sw-step[data-step="3"]{background:rgba(128,128,128,.08);border-radius:12px;padding:.7rem .8rem .6rem}
.sw-row{padding:.25rem 0}
/* The rewordings are numbered, so «three formulations» is something they can
   count — the thought above being the first. */
.sw-step[data-step="2"] .sw-step-rows{counter-reset:sw}
.sw-step[data-step="2"] .sw-row{position:relative;padding-left:1.5rem}
.sw-step[data-step="2"] .sw-row::before{counter-increment:sw;content:counter(sw) ".";
  position:absolute;left:.1rem;top:.25rem;line-height:38px;color:var(--muted);font-size:.9rem}
.sw-said{margin:0;padding:2px 0;line-height:1.45}
.sw-status{display:block;margin-top:.3rem;color:var(--muted);font-size:.83rem;line-height:1.35}
.sw-status:empty{display:none}
.sw-action.on{color:var(--accent)}
/* The plane belongs to the LAST filled line only: a filled line above it has no
   control at all (one active button — Vitaly, 2026-09-12). */
.sw-row.is-behind .sw-action{display:none}

/* The tries stack up as a numbered list above the open field — seeing attempt 1
   while making attempt 3 is where a student notices their own second one
   carried it. */
.sw-tries{margin:0 0 .5rem;padding-left:1.35rem}
.sw-tries[hidden],.sw-tries:empty{display:none}
.sw-try{padding:.18rem 0;line-height:1.45}
.sw-again{border:0;border-radius:10px;padding:8px 16px;cursor:pointer;
  background:var(--accent);color:#fff;font:inherit;font-size:.9rem;font-weight:600}
/* «Перевір мене» is a quiet link under the tries, on purpose: trying again is
   the exercise (the empty field is right there), and being told what was wrong
   is the thing you reach for after. */
.sw-show{border:0;background:transparent;padding:6px 0 0;cursor:pointer;
  color:var(--accent);font:inherit;font-size:.9rem;text-decoration:underline}
.sw-show[hidden]{display:none}
.sw-show[disabled]{opacity:.5;cursor:default;text-decoration:none}

.sw-result:empty{display:none}
.sw-result{margin-top:.8rem;padding-top:.8rem;border-top:1px solid var(--line)}
.sw-verdict + .sw-verdict{margin-top:.8rem;padding-top:.8rem;border-top:1px solid var(--line)}
.sw-v-head{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem}
.sw-v-said{line-height:1.45}
/* One number, and it answers one question: did the thought arrive. The bands are
   read-at-a-glance colour, never a grade — there is no pass mark here. */
.sw-carried{font-size:1.05rem;font-weight:700;font-variant-numeric:tabular-nums;flex:0 0 auto}
.sw-carried.hi{color:#2e9e5b}
.sw-k{color:var(--muted)}
.sw-fix,.sw-note,.sw-from{margin:.35rem 0 0;font-size:.88rem;line-height:1.45}
/* The mirror held up to the rewordings — first in the result, and given room,
   because it is what the student actually made. */
.sw-range{margin:0 0 .8rem;font-size:.95rem;line-height:1.45}
/* The joy line: what this exercise is FOR. Quiet, but at the top, where the
   student reads it before they read anything that looks like a mark. */
.sw-joy{margin:-.4rem 0 1rem;color:var(--muted);font-size:.9rem;line-height:1.45}
.sw-audio{display:block;width:100%;margin-top:.6rem}
.sw-after{display:flex;align-items:center;gap:.9rem;margin-top:.9rem;flex-wrap:wrap}
/* The ready phrasings are a quiet link, not a button: the student has just done
   the work, and the point is that they no longer need them first. */
.sw-ways{color:var(--accent);font-size:.9rem;text-decoration:none;font-weight:600}
.sw-h-thought{font-weight:600;line-height:1.4}
.sw-h-said{display:flex;align-items:baseline;gap:.5rem;margin-top:.2rem;
  color:var(--muted);font-size:.9rem;line-height:1.4}
.sw-h-said .sw-carried{font-size:.95rem}

/* ── Сендвіч · where a sandwich starts: three tabs ─────────────────────────
   Own thought (default), Études, Challenge (Vitaly, 2026-09-25). A tab with
   nothing to offer is hidden by the script; a pick is one tap. */
.sw-tabs{display:flex;gap:4px;padding:3px;margin:.1rem 0 .9rem;border-radius:12px;
  background:var(--line)}
.sw-tab{flex:1 1 0;min-width:0;border:0;border-radius:9px;padding:8px 6px;cursor:pointer;
  background:transparent;color:var(--muted);font:inherit;font-size:.92rem;font-weight:560}
.sw-tab.is-on{background:var(--card);color:inherit;box-shadow:0 1px 2px rgba(0,0,0,.08)}
.sw-tab[hidden]{display:none}
.sw-pick{display:flex;flex-direction:column;gap:8px;margin-bottom:.9rem}
.sw-pick[hidden]{display:none}
.sw-pick-note{margin:0 0 2px;font-size:.88rem;color:var(--muted)}
.sw-pick-item{display:flex;flex-direction:column;gap:4px;text-align:left;
  border:1px solid var(--line);border-radius:10px;padding:10px 12px;background:var(--card);
  color:inherit;font:inherit;cursor:pointer}
.sw-pick-item:hover{border-color:var(--accent)}
.sw-pick-scene{font-size:.95rem;line-height:1.4}
.sw-pick-say{font-size:1rem;line-height:1.4;font-weight:600}
.sw-chosen{margin-bottom:.8rem}
.sw-chosen[hidden]{display:none}
.sw-chosen-k{margin:0 0 3px;font-size:.85rem;color:var(--muted)}
.sw-chosen-scene{margin:0;font-size:1.02rem;line-height:1.45}

/* History rows reuse .hist-row from the check + say-it cards; only the body
   inside a row is this exercise's own. */
.sw-h-try{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem;
  margin-top:.35rem;line-height:1.45}
.sw-h-said-t{min-width:0}

/* ── session replay (coach, VIT-832) ─────────────────────────────────────────
   The player the coach re-lives a practice session in. The one thing the visual
   design has to carry: a PAUSE IS A THING ON THE SCREEN, not an absence. Grey
   is the loudest colour on the track, and a silence counts up in front of him
   at full size while it lasts. A player that made the gaps small would destroy
   exactly what this exists to show. */
.rp-fake{border:1px solid var(--accent);border-radius:var(--radius);
  background:#fff6f2;padding:12px 14px;margin:0 0 16px}
.rp-fake b{display:block;font-size:.78rem;letter-spacing:.09em;text-transform:uppercase;
  color:var(--accent)}
.rp-fake p{margin:.35em 0 0;font-size:.9rem;color:#5a4a44}

/* THE STAGE IS HER SCREEN AND NOTHING ELSE. Vitaly, 2026-09-14: «kill some
   unnecessary blank space below the app viewport and show the timeline
   directly under it». The box used to carry 14px of padding, a 230px floor
   and the words box under the frame; the track now follows the frame with
   6px between them. */
.rp-stage{position:relative;padding:0;overflow:hidden}
.rp-track{margin-top:6px}
/* FIXED IN ONE PLACE (Vitaly, 2026-09-14). The words live in a box of one
   height under the timeline: the phrase gets two lines, the action one, the
   detail one, the sound notice one — and anything longer is clipped rather
   than allowed to move anything around it. */
.rp-words{height:9.2rem;overflow:hidden;margin-top:4px}
.rp-screen{font-size:.85rem;margin-bottom:6px;height:3.4rem;overflow:hidden}
.rp-now{display:flex;align-items:baseline;gap:10px;flex-wrap:nowrap;height:1.7rem;overflow:hidden}
.rp-now b{font-size:1.15rem;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rp-side{font-size:.72rem;letter-spacing:.07em;text-transform:uppercase;
  border:1px solid var(--line);border-radius:20px;padding:2px 9px;white-space:nowrap}
.rp-side-student{color:var(--accent);border-color:var(--accent)}
.rp-side-app{color:var(--muted)}
.rp-detail{margin-top:6px;font-size:.95rem;height:1.4rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* Her tap, put where it landed. There is no screenshot behind it — nothing is
   captured — so the ring sits on the named screen, not on a faked picture. */
.rp-tap{position:absolute;width:0;height:0;pointer-events:none}
/* A tap is a moment, and it has to be seen at 8x. Vitaly, 2026-09-12: «I see
   the screen, no tap» — the ring was 34px and gone in a second. Bigger, thicker,
   and it lingers; the second ring inside it is the touch itself. */
.rp-tap i{position:absolute;left:-26px;top:-26px;width:52px;height:52px;border-radius:50%;
  border:3px solid var(--accent);opacity:0;box-shadow:0 0 0 3px rgba(255,255,255,.9)}
.rp-tap i::after{content:"";position:absolute;left:14px;top:14px;width:18px;height:18px;
  border-radius:50%;background:var(--accent);opacity:.85}
.rp-tap span{position:absolute;left:30px;top:-10px;font-size:.85rem;font-weight:600;
  color:#fff;background:var(--accent);padding:2px 7px;border-radius:6px;white-space:nowrap;
  opacity:0}
.rp-tap.go i{animation:rp-ping 4s ease-out}
.rp-tap.go span{animation:rp-tag 4s ease-out}
@keyframes rp-ping{
  0%{transform:scale(.4);opacity:1} 35%{transform:scale(1.15);opacity:1} 100%{transform:scale(1.6);opacity:0}}
@keyframes rp-tag{0%{opacity:1} 70%{opacity:1} 100%{opacity:0}}

/* The pause: one line in the fixed box under her screen (2026-09-14), never
   an overlay. It counts up while she waited; the right arrow skips it. */
.rp-gapbox{display:flex;align-items:baseline;gap:8px;height:1.5rem;overflow:hidden}
.rp-gapbox-k{font-size:.72rem;letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}
.rp-gapbox-n{font-size:1.05rem;font-variant-numeric:tabular-nums}

.rp-controls{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:8px 0 0}
.rp-clock{font-variant-numeric:tabular-nums;font-size:.92rem;margin-left:auto}
.rp-rates{display:flex;gap:4px}
.rp-rates .sbtn.on{border-color:var(--accent);color:var(--accent)}
.signs .sign-row{display:flex;gap:10px;align-items:baseline;padding:5px 0;border-top:1px solid #f2f2f2;flex-wrap:wrap}
.signs .sign-k{flex:0 0 46%;color:var(--muted)}
.signs .sign-v{font-variant-numeric:tabular-nums}
.signs .sign-prev{font-size:.85rem;font-variant-numeric:tabular-nums}
.focus-row{white-space:nowrap}
.focus-row .focus-f{color:var(--accent)}
.focus-row .focus-b{color:var(--muted)}
.rp-hide{display:inline-flex;align-items:center;gap:6px;font-size:.85rem;color:var(--muted);cursor:pointer;
  flex-basis:100%;margin-top:2px}
.rp-hide input{accent-color:var(--accent);margin:0}

.rp-track{position:relative;height:30px;border:1px solid var(--line);border-radius:6px;
  background:var(--card);overflow:hidden;cursor:pointer}
.rp-seg{position:absolute;top:0;bottom:0}
.rp-seg-gap{background:#ececec}
.rp-seg-long{background:#dcdcdc}
.rp-seg-student{background:rgba(255,71,0,.20)}
.rp-seg-app{background:rgba(107,107,107,.16)}
.rp-tick{position:absolute;top:4px;bottom:4px;width:3px;margin-left:-1px;padding:0;border:0;
  border-radius:2px;background:var(--muted);cursor:pointer}
.rp-tick-student{background:var(--accent)}
/* Not session time (2026-09-11): a stretch of choosing, folded to one mark.
   A hollow tick — nothing was played there, and the bar says so. */
.rp-tick-outside{background:var(--card);border:1px solid var(--muted);width:5px;margin-left:-2px}
.rp-tick:hover{top:0;bottom:0}
.rp-head{position:absolute;top:0;bottom:0;width:2px;margin-left:-1px;background:var(--ink);
  pointer-events:none}

.rp-facts{display:flex;gap:18px;flex-wrap:wrap;margin:10px 0 4px;font-size:.9rem}
.rp-facts b{font-variant-numeric:tabular-nums}
.rp-golong{color:var(--accent);text-decoration:none;border-bottom:1px dotted var(--accent)}

.rp-list{list-style:none;margin:0;padding:0;max-height:60vh;overflow-y:auto;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
.rp-row{display:flex;gap:10px;align-items:baseline;padding:7px 12px;cursor:pointer;
  border-top:1px solid #f2f2f2}
.rp-list>li:first-child{border-top:0}
.rp-row:hover{background:#fafafa}
.rp-row.on{background:#fff3ee}
.rp-t{font-variant-numeric:tabular-nums;color:var(--muted);font-size:.82rem;
  min-width:52px;flex:0 0 auto}
.rp-k{font-size:.7rem;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);
  min-width:72px;flex:0 0 auto}
.rp-row-student .rp-k{color:var(--accent)}
.rp-row-outside{background:#fbfbfa;border-top:1px dashed var(--line)}
.rp-l{flex:1;min-width:0}
.rp-d{display:block;font-size:.85rem}
.rp-ov{font-size:.75rem;color:var(--close);white-space:nowrap}

/* The pause row. Deliberately not a thin divider: it is the finding. */
.rp-pause{display:flex;align-items:center;gap:10px;padding:6px 12px;
  border-top:1px dashed var(--line);background:#fbfbfa}
.rp-pause-n{font-variant-numeric:tabular-nums;font-size:.85rem;color:var(--muted)}
.rp-pause-long{background:#f4f4f4}
.rp-pause-long .rp-pause-n{color:var(--ink);font-size:1rem;font-weight:600}
.rp-pause-tag{font-size:.7rem;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}

/* "She declined", "she was never asked", "that is our own account" — finished
   states with a sentence in them, never an empty box or a spinner. */
.rp-refused{border:1px solid var(--line);border-radius:var(--radius);background:var(--card);
  padding:22px;margin-top:8px}
.rp-refused-who{font-size:.85rem;margin-bottom:6px}
.rp-refused-say{font-size:1.1rem;line-height:1.5;margin:0 0 12px}
.rp-refused-seam{font-size:.9rem;border-top:1px solid var(--line);padding-top:12px}

.rp-try{display:flex;gap:8px;flex-wrap:wrap;margin:8px 0 24px}
.rp-try input{flex:1;min-width:160px;padding:9px 12px;border:1px solid var(--line);
  border-radius:22px;background:var(--card);color:inherit;font:inherit}

/* ── assign-as-her ────────────────────────────────────────────────────────
   Two things live in this block and only one of them is for the student.

   THE MARK (.marked / .mark-badge) is HERS. It says "this is the task you were
   given" on the tile, the work and the module that contain it — the whole chain
   down from the hub, because the first thing a new student meets is five
   abstract tiles with no instruction and a task behind an unmarked tile has not
   been assigned in any sense she can act on. It is the brand accent, not a new
   colour, and it is a label with a word in it, not a bare dot: a coloured edge
   with no word is decoration, and she has to be able to read what it means.

   THE BAR (.asg-*) is HIS, and appears only while he is standing inside her
   Lab. Deliberately loud and pinned to the top of every one of her pages: being
   unsure whose screen you are on is the one failure this mode can produce. */
.marked{border-color:var(--accent)!important;box-shadow:inset 3px 0 0 var(--accent)}
.mark-badge{
  display:inline-block;vertical-align:middle;margin-left:.4em;
  font-size:.68rem;font-weight:600;letter-spacing:.02em;line-height:1.6;
  padding:0 .55em;border-radius:999px;
  background:var(--accent);color:#fff;white-space:nowrap;
}

.asg-bar{
  max-width:var(--maxw);margin:0 auto;padding:10px var(--pad) 12px;
  border-bottom:2px solid var(--accent);background:#fff6f2;
}
.asg-who{display:flex;align-items:center;flex-wrap:wrap;gap:10px;font-size:.9rem}
.asg-eye{font-size:1rem}
.asg-name b{font-weight:650}
.asg-count{color:var(--muted);font-size:.82rem}
/* her plan, on his bar (a042) — only rendered when she is on one */
.asg-plan{color:var(--muted);font-size:.82rem;flex-basis:100%}
.asg-exit{margin-left:auto}
.asg-exit button,.asg-held button{
  border:1px solid var(--line);background:#fff;border-radius:8px;
  padding:3px 10px;font:inherit;font-size:.82rem;cursor:pointer;color:var(--ink);
}
.asg-exit button:hover,.asg-held button:hover{border-color:var(--accent);color:var(--accent)}
.asg-note{margin:8px 0 0;font-size:.86rem;color:var(--off)}
.asg-note.ok{color:var(--ok)}
.asg-none{margin:8px 0 0;font-size:.84rem;color:var(--muted)}
.asg-held{list-style:none;margin:8px 0 0;padding:0;display:flex;
  flex-direction:column;gap:5px}
.asg-held li{display:flex;align-items:center;flex-wrap:wrap;gap:8px;font-size:.85rem}
.asg-held form{margin-left:auto}
.asg-dir{font-size:.72rem;font-weight:600;padding:1px .6em;border-radius:999px;
  background:#e7f6ec;color:#1b7f3b}
.asg-dir-activation{background:#fdeee6;color:#a33a08}
.asg-flag{font-size:.72rem;color:var(--muted)}
.asg-title{font-weight:550}
.asg-proto{color:var(--muted);font-size:.8rem}

/* The control itself, on the card of the thing being assigned. Collapsed by
   default so her screen still looks like her screen while he walks it. */
.asg-form{margin:-6px 2px 12px;font-size:.86rem}
.asg-form>summary{cursor:pointer;color:var(--accent);font-weight:550;
  padding:4px 2px;list-style:none}
.asg-form>summary::-webkit-details-marker{display:none}
.asg-form>summary::before{content:"＋ ";font-weight:400}
.asg-form form{display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  border:1px solid var(--accent);border-radius:var(--radius);
  padding:10px 12px;background:#fff}
.asg-form-what{flex:1 0 100%;margin:0;font-weight:600}
.asg-radio,.asg-check{display:inline-flex;align-items:center;gap:5px;cursor:pointer}
.asg-text{flex:1 1 220px;min-width:0;border:1px solid var(--line);
  border-radius:9px;padding:6px 10px;font:inherit;font-size:.86rem}
.asg-go{border:0;border-radius:9px;background:var(--accent);color:#fff;
  padding:6px 16px;font:inherit;font-size:.86rem;font-weight:550;cursor:pointer}

/* The way in, from the daily table. */
.dt-asher{border:1px solid var(--accent);background:#fff;color:var(--accent);
  border-radius:8px;padding:2px 8px;font:inherit;font-size:.75rem;cursor:pointer}
.dt-asher:hover{background:var(--accent);color:#fff}

/* ── how the work went (a005) ────────────────────────────────────────────────
   The coach's reading, directly under the assign bar and styled as its quieter
   continuation: same width, same ground, no border of its own, so the two read
   as one strip rather than two competing headers. Deliberately flat — no
   colour band, no meter, no badge. A reading that looks like a scoreboard is a
   scoreboard, and the method has none. */
.perf-bar{
  max-width:var(--maxw);margin:0 auto;padding:8px var(--pad) 12px;
  border-bottom:1px solid var(--line);background:#fff6f2;font-size:.85rem;
}
.perf-head{display:flex;align-items:center;gap:8px;color:var(--muted);
  font-size:.82rem}
.perf-says{list-style:none;margin:6px 0 0;padding:0;display:flex;
  flex-wrap:wrap;gap:4px 16px}
.perf-sub{margin:10px 0 4px;color:var(--muted);font-size:.8rem}
.perf-phrases ul,.perf-acts ul,.perf-held ul{list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column;gap:4px}
.perf-phrases li{display:flex;align-items:baseline;flex-wrap:wrap;gap:8px}
.perf-line{font-weight:550}
.perf-tries,.perf-missing{color:var(--muted);font-size:.8rem}
.perf-acts li{display:flex;align-items:center;flex-wrap:wrap;gap:8px}
.perf-acts form{margin-left:auto}
.perf-acts button{
  border:1px solid var(--line);background:#fff;border-radius:8px;
  padding:3px 10px;font:inherit;font-size:.82rem;cursor:pointer;color:var(--ink);
}
.perf-acts button:hover{border-color:var(--accent);color:var(--accent)}
.perf-held li{color:var(--muted);font-size:.8rem}

/* ── the consent dialog she answers when she opens the app (VIT-832) ────────
   A real modal, not a banner: fixed over the whole viewport, above every
   z-index the app uses, and with nothing behind it reachable by pointer. It has
   no close control by design — the two buttons are the two answers, and there
   is no third. `overscroll-behavior:contain` stops a scroll inside the box from
   chaining into the page underneath, which is the one way a fixed overlay can
   still feel dismissible. */
.cm-back{position:fixed;inset:0;z-index:9000;display:flex;align-items:center;
  justify-content:center;padding:16px;background:rgba(20,16,14,.62);
  overflow:auto;overscroll-behavior:contain}
.cm-box{width:100%;max-width:440px;background:var(--card);color:var(--ink);
  border-radius:var(--radius);padding:22px 20px;box-shadow:0 18px 48px rgba(0,0,0,.28)}
/* She can change the language of the question she is being asked. Placed above
   the title, small and quiet — it is a way to READ the dialog, not a way out of
   it (it re-renders the same unanswered dialog in the language she picked). */
.cm-lang{display:inline-flex;gap:2px;margin:0 0 12px}
.cm-title{font-size:1.2rem;line-height:1.35;margin:0 0 10px}
.cm-lead{margin:0 0 8px;font-size:.95rem}
.cm-list{margin:0 0 14px;padding-left:1.15em;font-size:.95rem;line-height:1.55}
.cm-list li{margin:.2em 0}
/* The consequence sits in ordinary type, same weight as everything else: it is
   information she needs to decide, not fine print and not a warning label. */
.cm-if-no{margin:0 0 18px;font-size:.95rem;line-height:1.5;
  border-top:1px solid var(--line);padding-top:14px}
.cm-buttons{display:flex;gap:10px;flex-wrap:wrap}
/* Equal width, equal weight — the box does not push her toward either answer. */
.cm-btn{flex:1 1 140px;text-align:center;padding:11px 14px}

/* ── Where she changes her mind about a coach reviewing her practice (VIT-832)
   The page reuses the dialog's own type (.cm-title/.cm-lead/.cm-list/.cm-if-no)
   so the sentences look the same wherever she reads them. Only the two things
   the dialog does not have get their own rules: her current answer, and the
   mark on the button she is currently holding. */
.cs-card{margin-top:12px}
.cs-state{margin:0 0 10px;font-weight:600;font-size:.95rem}
/* The mark is STATE, not advice: an outline, not a filled "do this" button, so
   neither answer is styled as the recommended one. Kept legible without colour
   for anyone who cannot see the border — both buttons carry aria-pressed and
   the sentence above says the same thing in words. */
.cs-on{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink);font-weight:600}
.cs-note{margin:14px 0 0;font-size:.88rem;line-height:1.5;color:var(--muted)}

/* ── the sittings waiting for an answer (a026) ── */
.sessions-row{align-items:baseline}
.sessions-alarm{color:var(--off);font-weight:600}
.sessions-rule{font-size:.85rem;margin:10px 0}
.sessions-list{margin:14px 0}

/* ── his one-minute answer, recorded in the app (a033) ─────────────────────── */
.rr { margin: 12px 0; }
.rr-video { width: 100%; max-width: 480px; border-radius: 10px; background: #000; display: block; }
.rr-bar { display: flex; align-items: baseline; gap: 10px; margin: 8px 0 4px; }
.rr-clock { font-variant-numeric: tabular-nums; font-size: 1.4rem; font-weight: 600; }
.rr-clock.rr-over { color: #b8860b; }          /* past his minute — a note, not an error */
.rr-target { font-size: .85rem; }
.rr-buttons { display: flex; gap: 8px; flex-wrap: wrap; }
.rr-bad { color: #b3261e; }
.hub-answer { display: block; border-left: 3px solid currentColor; }

/* ── a section she has not been given: visible, named, and shut (a035) ────── */
.spoke.locked { opacity: .72; cursor: default; }
.spoke.locked .spoke-icon { opacity: .6; }
.lock-badge {
  font-size: .7rem; font-weight: 600; padding: 1px 7px; border-radius: 999px;
  background: var(--surface-2, #f1f3f5); color: var(--muted, #6b7280);
  vertical-align: middle; margin-left: 6px;
}
.spoke-solves { font-size: .84rem; color: var(--muted, #6b7280); margin-top: 6px; line-height: 1.4; }
/* ── stickie (Липучка — /s/p) ─────────────────────────────────────────────
   Prefixed `stk-`, NOT `lp-`: `.lp-` is already the lookup panel's namespace
   (mode_lookup.js / a_mode.js, ~18 classes), and `.lp-more` in particular would
   have collided outright.
   Deliberately flat: no bars, no rings, no level chips. The tally is a plain
   number because it is a count of her own taps and grades nothing (VIT-625
   rule 4), and the retired lists are two plain lists because only one of them
   is a failure. */
/* Three tabs, his order and default (2026-09-16). Same quiet underline as the
   lookup panel's .lp-tabs, sized for a page-level switch: equal thirds so the
   three fit a phone without ellipsis. A pane that JS hides needs the [hidden]
   guard because it has no author display — kept explicit anyway, see .stk-ask. */
.stk-tabs{display:flex;gap:0;margin:.2rem 0 1rem;border-bottom:1px solid var(--line)}
.stk-tab{flex:1 1 0;border:0;background:none;font:inherit;font-size:.92rem;color:var(--muted);
  padding:8px 4px 10px;margin-bottom:-1px;border-bottom:2px solid transparent;cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.stk-tab:hover{color:var(--ink)}
.stk-tab.is-on{color:var(--accent);border-bottom-color:var(--accent);font-weight:600}
.stk-pane[hidden]{display:none}
.stk-go-add,.stk-go-day{margin:.2rem 0 1rem}
.stk-go-day[hidden]{display:none}

/* The idea written for HER phrase and HER routine (2026-09-16): the text in
   Ukrainian, the example sentences in her language as a plain list. */
.stk-idea{margin-top:.6rem;padding:9px 12px;border-left:2px solid var(--accent);
  font-size:.92rem;line-height:1.5}
.stk-idea[hidden]{display:none}
.stk-idea-none{border-left-color:var(--line);color:var(--muted)}
.stk-idea-ex{margin:.45rem 0 0;padding-left:1.1rem}
.stk-idea-ex li{margin-top:2px;font-weight:500}
.stk-idea-again{margin-top:.5rem;display:inline-block}

.stk-day{padding:14px 16px}
.stk-day-sum{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem;
  cursor:pointer;list-style:none}
.stk-day-sum::-webkit-details-marker{display:none}
.stk-day-sub{margin:.5rem 0 0}
.stk-part{margin:1rem 0 .4rem}
.stk-pills{display:flex;flex-wrap:wrap;gap:6px}
.stk-pill{border:1px solid var(--line);border-radius:20px;background:var(--card);
  color:inherit;font:inherit;font-size:.85rem;padding:5px 11px;cursor:pointer}
.stk-pill:hover{border-color:var(--accent)}
.stk-pill.on{background:var(--accent);border-color:var(--accent);color:#fff}
/* The last pill of a section is hers to fill — orange rim, not grey (Vitaly,
   2026-09-16); the field that replaces it keeps the pill's shape. */
.stk-pill-add{border-color:var(--accent);color:var(--accent);background:transparent}
.stk-pill-add:hover{background:var(--accent);color:#fff}
.stk-pill-add[hidden]{display:none}
.stk-own-input{border:1px solid var(--accent);border-radius:20px;background:var(--card);
  color:inherit;font:inherit;font-size:.85rem;padding:5px 11px;min-width:12ch;max-width:100%}
.stk-own-input[hidden]{display:none}
.stk-day-foot{display:flex;align-items:center;gap:.8rem;margin-top:1.1rem}

.stk-suggest,.stk-live,.stk-retired{display:flex;flex-direction:column;gap:10px}
.stk-cand,.stk-sticker{padding:14px 16px}
.stk-cand-routine{font-weight:600;line-height:1.35}
.stk-cand-idea{color:var(--muted);font-size:.92rem;line-height:1.5;margin-top:.3rem}
.stk-cand-x{margin-top:.6rem;font-size:.92rem;line-height:1.45}
.stk-cand-x-lbl{color:var(--muted);font-size:.74rem;text-transform:uppercase;
  letter-spacing:.07em;margin-right:.5rem}
.stk-cand-x-none{color:var(--muted);font-style:italic}
.stk-cand-choices{display:flex;flex-direction:column;gap:6px;margin-top:.4rem}
.stk-chip{display:block;width:100%;text-align:left;border:1px solid var(--line);border-radius:10px;
  background:var(--card);color:inherit;font:inherit;font-size:.9rem;line-height:1.4;
  padding:8px 11px;cursor:pointer}
.stk-chip:hover{border-color:var(--accent)}
.stk-chip.on{border-color:var(--accent);background:var(--accent);color:#fff}
.stk-chip-main{display:flex;align-items:baseline;gap:6px}
.stk-chip-check{flex-shrink:0;font-size:.85em;visibility:hidden}
.stk-chip.on .stk-chip-check{visibility:visible}
.stk-chip-examples{margin-top:3px;font-size:.85em;opacity:.72}
.stk-chip-examples div{margin-top:1px}
.stk-cand-picked{margin-top:.5rem;font-size:.88rem;font-weight:600;color:var(--accent)}
.stk-cand-pic{margin-top:.6rem;padding:9px 12px;border-left:2px solid var(--accent);
  font-size:.92rem;line-height:1.5}
.stk-cand-pic-none{border-left-color:var(--line);color:var(--muted)}
.stk-cand-actions{display:flex;align-items:center;gap:.7rem;margin-top:.9rem;flex-wrap:wrap}
.stk-ghost{border:0;background:transparent;cursor:pointer;font:inherit;font-size:.85rem;
  color:var(--muted);padding:2px 0;text-decoration:underline;text-underline-offset:3px}
.stk-ghost:hover{color:var(--accent)}
.stk-more{align-self:flex-start;border:0;background:transparent;cursor:pointer;font:inherit;
  font-size:.85rem;color:var(--muted);padding:2px 0;text-decoration:underline;
  text-underline-offset:3px;margin-top:.2rem}
.stk-note{margin:.5rem 0 1.4rem}

.stk-sticker-x{margin-top:.6rem;font-size:.95rem;line-height:1.45;font-weight:500}
.stk-sticker-pic{margin-top:.5rem;padding:9px 12px;border-left:2px solid var(--accent);
  font-size:.92rem;line-height:1.5;color:var(--muted)}
.stk-tally{display:flex;align-items:center;gap:.8rem;margin-top:.9rem;flex-wrap:wrap}
.stk-tally-n{color:var(--muted);font-size:.85rem}
.stk-letgo{margin-top:.7rem;display:inline-block}
.stk-ask{display:flex;align-items:center;gap:.9rem;margin-top:.6rem;flex-wrap:wrap}
/* An author `display` beats the UA stylesheet's [hidden]{display:none}, so every
   flex box here that JS hides needs saying twice. Without this the two
   retirement choices sit on the card permanently and «Відпустити» looks dead. */
.stk-ask[hidden]{display:none}
.stk-ask-q{color:var(--muted);font-size:.85rem}
.stk-ask-mature{color:var(--ok)}
.stk-ask-stale{color:var(--off)}

.stk-old{padding:11px 14px}
.stk-old-t{font-size:.95rem;line-height:1.35}
.stk-old-x{color:var(--muted);font-size:.88rem;margin-top:.2rem}
.stk-old-stale{opacity:.72}

/* Мій список — compact rows (Vitaly, 2026-09-03), not cards: `.row`'s own
   11px/0 padding + divider, tightened further since two lines share a row. */
.stk-pool-list{margin-bottom:12px}
.stk-pool-row{gap:14px;align-items:center}
.stk-pool-main{flex:1;min-width:0}
.stk-pool-text{font-size:.92rem;line-height:1.3}
.stk-pool-badge{display:inline-block;font-size:.72rem;color:var(--accent);
  border:1px solid var(--accent);border-radius:8px;padding:0 5px;margin-left:2px}
.stk-pool-bar{margin:3px 0 0}
.stk-pool-side{display:flex;align-items:center;gap:6px;flex-shrink:0}
.stk-pool-count{font-variant-numeric:tabular-nums}
.stk-cand-orig{margin-top:2px;text-decoration:line-through;text-decoration-color:var(--muted,#999)}
.stk-cand-keep{min-width:34px}

/* ── what happened in a sitting (a109) ────────────────────────────────────────
   His summary of one sitting, above the recorder. The design carries one thing:
   HER WORDS AND THE REAL SCORE ARE ALWAYS ON THE ROW. The grouping is a
   convenience; the evidence is the point, so nothing here may collapse a line
   into a verdict without the words that earned it. */
.hl{margin-bottom:14px}
.hl-head{font-size:.78rem;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);margin:14px 0 6px;font-weight:600}
.hl-head:first-of-type{margin-top:10px}
.hl-up{color:var(--ok,#2f7d52)}
.hl-down{color:var(--accent)}
.hl-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 8px;
  padding:5px 0;border-bottom:1px solid var(--line)}
.hl-row:last-child{border-bottom:none}
/* Her voice, on the row that quotes her. Small and quiet — he is scanning
   words, and the button is there for the line he stops on. */
.hl-play{flex:0 0 auto;width:22px;height:22px;line-height:20px;padding:0;
  border:1px solid var(--line);border-radius:50%;background:transparent;
  color:var(--muted);font-size:.62rem;cursor:pointer}
.hl-play:hover{color:var(--fg);border-color:var(--fg)}
.hl-play[aria-pressed="true"]{color:var(--fg);border-color:var(--fg)}
.hl-play-gone{opacity:.35;cursor:default}
.hl-from{color:var(--muted)}
.hl-to{color:var(--fg)}
.hl-arrow{color:var(--muted);font-size:.85rem}
.hl-score{font-variant-numeric:tabular-nums;font-size:.82rem;color:var(--muted);
  white-space:nowrap}
.hl-good{color:var(--ok,#2f7d52)}
@media (max-width:520px){
  .hl-arrow{display:none}
  .hl-row{flex-direction:column;gap:2px}
}

/* ── record while he watches (a109/b) ─────────────────────────────────────────
   The controls under the player. The recording itself is a canvas the browser
   never shows him — what he sees here is only the buttons, the counter, and
   afterwards the take, so he can throw it away before she has received it. */
.rp-rec{margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
.rp-rec-bar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
.rp-rec-clock{font-variant-numeric:tabular-nums;min-width:3.2em}
.rp-rec-clock.over{color:var(--accent)}
.rp-rec-preview{display:block;width:100%;max-width:480px;margin-top:10px;
  border-radius:var(--radius);background:#000}
.rp-rec-preview[hidden]{display:none}   /* the black box before there is a take: display:block beat [hidden] (a663) */

/* the phrase she had in front of her, above the path (a109/c) */
.rp-seen{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  font-size:1.05rem;line-height:1.3;max-height:2.6em}
.rp-gloss{display:block;font-size:.85rem;margin-bottom:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* Reading size picker (a184) — Settings and setup step 0.
   Each option is rendered AT the size it selects, so the control previews
   itself; that is why the label's font-size is inline per option and not here.
   Wraps rather than scrolls: at the largest step four labels do not fit a
   phone in one row, and a control that needs a sideways drag to reach its
   last option is exactly the wrong thing to hand someone who chose it. */
.font-row{display:flex;flex-wrap:wrap;gap:8px}
.font-pick{display:inline-flex;align-items:baseline;gap:6px;cursor:pointer;
  border:1px solid var(--line);border-radius:var(--radius);padding:8px 14px;
  background:var(--card);line-height:1.2}
.font-pick.on{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.font-pick input{margin:0;accent-color:var(--accent)}

/* ── replay: her screen, re-rendered ──────────────────────────────────────────
   The frame holds the practice page she was actually on (a378). It is scaled
   down rather than cropped — he is glancing at a whole screen, not reading it —
   and it takes no pointer events at all, because it is a likeness of a moment
   and not a page anybody may act on. */
.rp-screenframe {
  position: relative;
  /* A PHONE'S WIDTH, and no wider. The box used to be the full width of the
     stage with a 9/16 ratio, which made the screen 152px across on a laptop —
     rendered correctly and far too small to review, which is the only thing it
     is for (seen in a browser, 2026-09-10). Now it is her screen's own width
     wherever there is room, and it never scales UP past life size. */
  width: min(390px, 100%);
  margin-inline: auto;
  aspect-ratio: 390 / 844;
  max-height: 78vh;
  margin: 0 auto;
  overflow: hidden;
  border: 1px solid var(--line, #e2e8f0);
  border-radius: 10px;
  background: #fff;
}
/* THE FROZEN PAGE ONLY (#rp-screenview). This rule used to hit every iframe
   in the frame — including the replayer's, which carries HER screen's own
   width and height as attributes — and forced her 1280-px laptop page into a
   phone's 390 px, so he was shown a layout she never had (Vitaly,
   2026-09-14: «this is not showing me the real interface she saw»). */
#rp-screenview {
  position: absolute;
  top: 0; left: 0;
  width: 390px;                 /* a phone's width, then scaled to the box */
  height: 844px;
  border: 0;
  transform-origin: top left;
  pointer-events: none;         /* a replay is watched, never used */
}
.rp-screenrec iframe { pointer-events: none; }

/* The goal she had THAT day was never captured (a378). Shown as a gap rather
   than left out: hatched, grey, spanning the bar so it reads "extent unknown"
   and never as a real range, with the words on the chip beside it. */
.goal-band.unknown {
  left: 0; width: 100%;
  background: repeating-linear-gradient(45deg,
    rgba(100,116,139,.16) 0 6px, transparent 6px 12px);
  border: 1px dashed rgba(100,116,139,.35);
  box-sizing: border-box;
}
.goal-chip.unknown {
  background: transparent;
  color: var(--muted, #64748b);
  border: 1px dashed rgba(100,116,139,.35);
  font-style: italic;
}

/* A replay that goes quiet says why. Red because it is a fault, not a state;
   hidden the moment anything plays. */
.rp-sound { margin-top:4px; font-size:.85rem; color:#b91c1c; height:1.3rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

/* ── what she saw, on the frame ─────────────────────────────────────────────
   The two strips ride on top of her screen: her rating (the scorer's word and
   number for the take just made) and the action under way. The button she
   pressed is lit inside the frame by replay.js. (a378, 2026-09-11) */
.rp-screenframe { overflow: hidden; }
/* Top-right, under the mode pills, over the empty half of her top bar — the one
   place always in view on a phone-tall frame and covering nothing she used. */
/* Her screen as recorded (VIT-832): the replayer's box, scaled to fit the
   frame like the frozen page is; the wrapper inside is transformed by
   replay.js. */
.rp-screenrec { position:relative; margin:0 auto; overflow:hidden; background:#fff; max-width:100%; }
.rp-screenrec .replayer-wrapper { position:relative; }
.rp-screenrec iframe { border:0; display:block; }
.rp-plan-move { font-size:.78rem; color:var(--accent); white-space:nowrap; }

/* The log, closed by default and scrolling inside its own box so the page
   never moves under the screen he is watching. */
.rp-log > summary { cursor:pointer; font-weight:600; margin:14px 0 6px; }
.rp-log .rp-list { max-height: 40vh; overflow:auto; }

/* ── the Sandwich front door (/sandwich): the locked map ─────────────────── */
.sd-map { display: grid; gap: 12px; margin: 1.4em 0 1.8em; }
.sd-tile { border: 1px solid currentColor; border-radius: 10px; padding: 14px 16px; opacity: .78; }
.sd-tile .spoke-sub { font-size: .95rem; margin-top: .2em; }
.sd-tile .spoke-solves { font-size: .9rem; opacity: .75; margin-top: .4em; line-height: 1.45; }
.sd-subs { margin: .6em 0 0; padding-left: 1.2em; font-size: .92rem; line-height: 1.6; }
.sw-next { margin-top: 1.2em; }
.sw-next-link { display: inline-block; padding: 12px 22px; border-radius: 8px; background: #1f6feb; color: #fff; text-decoration: none; font-weight: 600; }

/* ── the front doors (/sandwich, and the German door when it lands) ──────────
   These pages are read by a stranger from an ad, on a phone, with no account —
   so they set their own type scale instead of inheriting one tuned for a
   signed-in screen. The ud-* names are shared with the German door's branch
   (a284) so the two doors look like one house. */
.ud-wrap { max-width: 640px; margin: 0 auto; padding: 24px 18px 56px; }
.ud-h1 { font-size: 2rem; line-height: 1.15; margin: 0 0 .5em; letter-spacing: -.01em; }
.ud-lead { font-size: 1.08rem; line-height: 1.55; margin: 0 0 1.4em; }
.ud-video video { width: 100%; border-radius: 10px; background: #000; margin: 0 0 1.2em; }
/* His door videos are 9:16 (phone). On a phone they fill the width; on a wide
   screen a full-width portrait video would tower, so it is capped to the
   height of the screen and centred, black either side — never stretched. */
.ud-video { text-align: center; }
/* The door's review card (2026-09-18): one address, one button, nothing else. */
.sd-review { margin: 1.4em 0; padding: 14px 16px; border: 1px solid var(--line, #e6e3dc); border-radius: 12px; background: var(--card, #fff); }
.sd-review h3 { margin: 0 0 .3em; font-size: 1.05rem; }
.sd-review p { margin: 0 0 .8em; line-height: 1.5; }
.sd-review.on p { margin: 0; }
.sd-review-form { display: flex; gap: 8px; flex-wrap: wrap; }
.sd-review-form input[type=email] { flex: 1 1 200px; padding: 12px 12px; font: inherit; border: 1px solid var(--line, #ccc); border-radius: 8px; }
.sd-review-form .ud-go { margin-top: 0; }
.sd-review-err { color: #b45309; margin: .5em 0 0; font-size: .92rem; }
.ud-video video { max-height: 70vh; width: auto; max-width: 100%; }
.ud-steps { margin: 1.2em 0; padding-left: 1.2em; line-height: 1.7; }
.ud-go { display: inline-block; margin-top: .6em; padding: 14px 26px; border-radius: 8px;
         background: var(--accent); color: #fff; text-decoration: none; font-weight: 600;
         font-size: 1.05rem; }
.ud-go:hover { filter: brightness(.94); }
.ud-note { margin-top: 1.2em; opacity: .72; font-size: .92rem; line-height: 1.5; }
.ud-top { display: flex; align-items: center; gap: 12px; margin-bottom: 1.4em;
          font-size: .92rem; opacity: .75; }
.ud-back { text-decoration: none; font-size: 1.3rem; opacity: .8; }
.ud-count { flex: 1; }
.ud-done { font-variant-numeric: tabular-nums; }
/* The door's language pills (2026-09-24). Plain links: they work with no
   script, and the one she is on is filled in rather than merely bolder. */
/* TWO LETTERS, SMALL (Vitaly, 2026-09-27: «make L2 pills smaller, two-letter
   ones»). Which language she is chewing is a setting, not the point of the
   screen — the sentence under it is. Still a real target: 2rem square is above
   the size a finger needs, so shrinking the label does not shrink the tap. */
.ud-langs { display: flex; flex-wrap: wrap; gap: .3rem; margin: 0 0 .9rem; padding: 0; }
.ud-lang { display: inline-flex; align-items: center; justify-content: center;
           min-width: 2rem; height: 2rem; padding: 0 .5rem; border-radius: 999px;
           border: 1px solid currentColor; font-size: .72rem; font-weight: 600;
           letter-spacing: .02em; text-decoration: none; color: inherit; opacity: .5; }
.ud-lang:hover { opacity: .8; }
.ud-lang.on { background: #ff4700; border-color: #ff4700; color: #fff; opacity: 1; }
/* THE CHEW, GIVEN ROOM (Vitaly, 2026-09-24: «give it more space, use a bit of
   #ff4700, larger font, some playback interface, not just a button, speed
   controls»). The orange is the accent on what she acts on — the play button,
   the bar as it fills, the speed she is on — and nowhere else, so it keeps
   meaning «this one». */
.ud-swallow { font-size: 1rem; opacity: .75; margin: 0 0 .7em; line-height: 1.55; }
.ud-phrase { font-size: 1.7rem; line-height: 1.35; font-weight: 650; margin: 0 0 1.1em;
             letter-spacing: -.01em; }

.ud-player { margin: 0 0 1.8rem; padding: .9rem 1rem 1rem; border-radius: 14px;
             background: var(--card, #fff); border: 1px solid var(--line, #e7e7e7); }
.ud-player-top { display: flex; align-items: center; gap: .75rem; }
.ud-play { display: inline-flex; align-items: center; gap: .5rem; flex: none;
           padding: .5rem .95rem .5rem .8rem; border-radius: 999px; cursor: pointer;
           border: 0; background: #ff4700; color: #fff; font: inherit; font-size: .92rem;
           font-weight: 600; }
.ud-play:focus-visible { outline: 2px solid #ff4700; outline-offset: 3px; }
.ud-play-i { width: 0; height: 0; border-left: 10px solid currentColor;
             border-top: 6.5px solid transparent; border-bottom: 6.5px solid transparent; }
.ud-play.on .ud-play-i { width: 10px; height: 13px; border: 0;
                         background: linear-gradient(to right, currentColor 0 3.5px,
                                     transparent 3.5px 6.5px, currentColor 6.5px 10px); }
.ud-seek { flex: 1; min-width: 0; height: 6px; border-radius: 999px;
           background: color-mix(in srgb, currentColor 14%, transparent); overflow: hidden; }
.ud-seek i { display: block; height: 100%; width: 0; background: #ff4700;
             border-radius: 999px; transition: width .08s linear; }
.ud-time { flex: none; font-size: .82rem; opacity: .55; font-variant-numeric: tabular-nums; }
.ud-rates { display: flex; gap: .35rem; margin: .8rem 0 0; }
.ud-rate { padding: .22rem .6rem; border-radius: 999px; border: 1px solid currentColor;
           background: none; color: inherit; font: inherit; font-size: .8rem; opacity: .45;
           cursor: pointer; }
.ud-rate.on { background: #ff4700; border-color: #ff4700; color: #fff; opacity: 1; }
.ud-rate:focus-visible { outline: 2px solid #ff4700; outline-offset: 2px; }

/* ONE SECTION AT A TIME (Vitaly, 2026-09-24: «I want scroll to move between
   sections in steps, not allowing half one section to remain visible while the
   one above/below is half in view», and the neighbours «barely visible» so he
   can film the mechanism as a lead meets it).

   The document is the scroll container, so the snap lives on <html>. Each step
   is a little SHORTER than the screen and snaps to its centre, which is what
   leaves the thin slivers of the step before and after: enough to know they are
   there, not enough to read. `scroll-snap-stop: always` is the part that makes
   it steps — a flick moves exactly one section, never two, and never rests
   between them.

   A step whose content is taller than the screen would be trapped by a centre
   snap, so above that height it snaps to its top and scrolls through normally.
   Nothing here is load-bearing: with the stylesheet gone the page is a page. */
/* PROXIMITY, NOT MANDATORY (Vitaly, 2026-09-25: «hitting Play on "As a native
   says" I get sent to watch that first video»). Mandatory snapping does not
   merely settle the page when a scroll ends — it OVERRIDES every small scroll,
   every anchor jump and every focus change by forcing the nearest snap point.
   In his shrunk window a step is taller than the window (621px inside 520px),
   so the nudge he makes to reach the Record button became a jump to the step
   above, which is the film. Proximity still settles on a step, so he never
   rests between two, and it never takes a scroll away from him. */
/* MANDATORY, now that a step fits the screen. It was proximity because a step
   used to be TALLER than the window (621px inside 520px) and mandatory then
   fought every small scroll — the nudge towards Record became a jump to the
   film. A step that fits is the thing that makes mandatory correct, and
   mandatory is the thing that makes a scroll move one whole section, which is
   what he asked for in the first place: «not allowing half one section to
   remain visible while the one above/below is half in view». */
/* PROXIMITY, because the stepping is the script's now. Mandatory is
   distance-based and pulls a short scroll back to where it started — which is
   the very complaint. Proximity only settles, so it never fights her and never
   undoes a step the page has just made. */
html.ud-steps { scroll-snap-type: y proximity; scroll-behavior: smooth; }
html.ud-steps body { overflow-x: hidden; }
html.ud-steps main { padding-top: 0; padding-bottom: 0; }
html.ud-steps .sd3-step {
  /* A STEP IS A WHOLE SCREEN AND NOTHING ELSE SCROLLS.
     It is FLOORED at 76svh so the next section shows at the edge — «make
     section 2 a bit visible» (2026-09-25), which 82svh had left at 11 real
     pixels. It is not capped: a cap needs somewhere for the overflow to go, and
     the only place was inside the step, which is what broke the scrolling.
     `overflow-y: auto` here made the step its own scroll container, and
     `overscroll-behavior: contain` then told it to keep the scroll to itself —
     so a wheel inside step two moved its last 64px and STOPPED. Scrolling down
     did not reach the next section at all («Scrolling down doesn't step to
     section below, I have to tap the arrow», 2026-09-27). No inner scrolling:
     the page is the only thing that scrolls, and one gesture is one step.
     A step is floored so its neighbour shows at the edge, and the film gives up
     height rather than the step growing past the screen. */
  min-height: 76svh; margin: 0; padding: 2svh 0;
  display: grid; align-content: center;
  scroll-snap-align: start; scroll-snap-stop: always;
}
/* The film is what grows; cap it rather than the text around it, so the step
   keeps its heading and its cue while the picture gives up the height. */
html.ud-steps .ud-filmcard .ud-video video,
html.ud-steps .ud-video video { max-height: 56svh; }
html.ud-steps .sd3-h1 { margin: 2.2svh 0 0; }
/* taller than the screen: read it from the top rather than from its middle */
/* A short window: read each step from its top rather than its middle, and let
   a step that genuinely does not fit scroll on its own instead of being held
   half off screen. */
/* A SHORT WINDOW cannot hold a whole step, and mandatory snapping in a window
   that cannot hold a step is exactly the fight of 2026-09-25. There, the page
   settles rather than steps, and a step may be as tall as it needs. */
@media (max-height: 700px) {
  html.ud-steps .sd3-step { min-height: 0; align-content: start;
                            scroll-snap-align: start; padding: 1.2svh 0 2.4svh; }
  html.ud-steps .ud-filmcard .ud-video video,
  html.ud-steps .ud-video video { max-height: 50svh; }
}
/* The one she is on is the one that is lit. Added by script only, so a page
   with no script shows every step plainly rather than three faint ones. */
html.ud-steps.js .sd3-step { transition: opacity .22s ease, filter .22s ease; }
html.ud-steps.js .sd3-step:not(.here) { opacity: .38; filter: saturate(.55); }
@media (prefers-reduced-motion: reduce) {
  html.ud-steps { scroll-behavior: auto; }
  html.ud-steps.js .sd3-step { transition: none; }
}

/* A MOVEMENT STILL TO COME is on the page, quietly (his words, 2026-09-25:
   «step 2 will have arrows pointing down between subsections», and only
   «subsections that are done» collapse). She reads its letter and its one line,
   so the shape of the exercise is visible before she starts — but it is not
   opened: no player, no bars, no button, nothing to press out of turn. */
.ud-sub.ahead { opacity: .5; }
/* (а) IS THE REFERENCE, not a step she finishes. The recording is what every
   other movement is measured against, so it stays on the page with its player
   under her hand while she works through б, в and г — it used to fold itself
   away the moment the clip finished playing («I played audio 1 time and the
   Play button disappeared. bad. do not make it disappear», 2026-09-25).
   Its heading goes quiet; the player does not. */
.ud-sub.ref { opacity: .72; }
/* A MOVEMENT SHE HAS FINISHED stays exactly where it was in the ladder — it
   used to fold out into a row of letters, and (б) simply vanished from the page
   («second step disappeared … we need clear navigation allowing a user to see
   all stages», 2026-09-26). It reads as done: quiet, ticked, still one tap from
   opening again. */
.ud-sub.done { opacity: .6; }
.ud-sub.done .ud-sub-hint { display: none; }
.ud-sub.done .ud-player, .ud-sub.done .ud-bars, .ud-sub.done .ud-on { display: none; }
.ud-sub.done .ud-sub-l { background: #1a7f4b; color: #fff; }
.ud-sub.done .ud-sub-l::after { content: "✓"; }
.ud-sub.done .ud-sub-l { font-size: 0; }
.ud-sub.done .ud-sub-l::after { font-size: .8rem; }
/* Every movement's name is the way into it, so she can step back to (б) from
   (в) or look ahead without recording her way there. */
.ud-sub-h { cursor: pointer; }
.ud-sub-h:hover { opacity: .78; }
.ud-sub-h:focus-visible { outline: 2px solid #ff4700; outline-offset: 3px; border-radius: 6px; }
.ud-sub.ref .ud-sub-hint { display: none; }
.ud-sub.ref .ud-player { opacity: 1; }
.ud-sub.ref:hover, .ud-sub.ref:focus-within { opacity: 1; }
/* Heading only, until it is her turn. The four movements are meant to read as
   a plan — letter, name, arrow — and carrying all four hints as well made step
   two taller than the screen it has to fit in. The hint arrives with the turn. */
.ud-sub.ahead .ud-sub-hint { display: none; }
.ud-sub.ahead .ud-player,
.ud-sub.ahead .ud-bars,
.ud-sub.ahead .ud-on { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .ud-sub { transition: opacity .2s ease; }
}

/* ── the four movements of the chew (2026-09-25) ────────────────────────────
   His own order: listen, repeat slowly, speed up, relax the mouth — an arrow
   between each, and the ones behind her folded into a row of letters. The one
   she is on has the screen to itself, which is the whole point of folding. */
.ud-chew { margin: 0 0 1rem; }
.ud-subs-row { display: flex; gap: .35rem; margin: 0 0 1rem; padding: 0; }
.ud-subs-row[hidden] { display: none !important; }
.ud-fold { width: 1.75rem; height: 1.75rem; border-radius: 999px; cursor: pointer;
           border: 1px solid currentColor; background: none; color: inherit;
           font: inherit; font-size: .82rem; opacity: .4; }
.ud-fold.on { background: #ff4700; border-color: #ff4700; color: #fff; opacity: 1; }
.ud-fold:focus-visible { outline: 2px solid #ff4700; outline-offset: 2px; }

.ud-sub[hidden] { display: none !important; }
.ud-sub-h { display: flex; align-items: center; gap: .55rem; margin: 0 0 .25rem;
            font-size: 1rem; font-weight: 650; }
.ud-sub-l { display: inline-grid; place-items: center; width: 1.6rem; height: 1.6rem;
            border-radius: 999px; background: #ff4700; color: #fff; font-size: .82rem; }
.ud-sub-hint { margin: 0 0 .9rem; font-size: .9rem; opacity: .65; line-height: 1.5; }
.ud-flow { text-align: center; font-size: 1.1rem; opacity: .3; margin: .1rem 0; }
.ud-flow[hidden] { display: none !important; }
.ud-take[hidden] { display: none !important; }
/* THE RECORDING HALF OF THE CHEW HAD NO STYLES AT ALL until 2026-09-25 — the
   record button, the verdict, what she was heard to say and the rep counters
   all rendered as raw browser defaults, so the drill's main action looked like
   an unfinished form control next to the player's own button (Vitaly, with a
   screenshot: «pls check all elements in all states»). The markup came over in
   the three-step rewrite and the stylesheet did not follow it, the same way
   rec.js did not. These match .ud-play, because they are the same act. */
.ud-take { margin-top: 1rem; }
/* THE SAME RECORD CONTROL AS B-MODE (Vitaly, 2026-09-27: «I would like the Rec
   button to reuse the styles we have in B-mode … the button with rec/play that
   when recording is going, it turns into StopRec»). The door had grown its own
   orange pill with its own pulse and its own name for the recording state — a
   second record button in a product that has one, so a lead met a control she
   would never see again inside the Lab. The markup is now .rec-compound /
   .rec-btn / .rec-mic / .play-attempt, which brings the mic → pulsing stop
   square with it (the rule up at .recording .rec-mic, deliberately unscoped) and
   nothing here repeats it. Only what is different about this screen is written:
   the compound sits on its own line under the movement. */
.ud-take .rec-compound { margin-top: .2rem; }
.ud-take .rec-btn { padding: .55rem 1.1rem; }
.ud-take .play-attempt { padding: .55rem 1rem; }

.ud-verdict { margin: .7rem 0 0; font-size: .95rem; line-height: 1.45; min-height: 1.4em; }
.ud-verdict:empty { display: none; }
.ud-verdict.ok  { color: #1a7f4b; }
.ud-verdict.bad { color: #b3320a; }
/* THE LINE SAYS WHAT ARRIVED. There was a «Почув: …» line under the button — a
   second copy of the sentence, in smaller grey type — and he asked for it gone
   and the words themselves marked instead (2026-09-27). A word the recogniser
   did not catch is underlined in the colour a missed take is marked in, so the
   drill's two verdicts share one palette; a word that arrived is left alone,
   because a line of green ticks would read as a grade, and this screen gives
   none. */
.ud-w { border-bottom: 2px solid transparent; }
.ud-w.miss { color: #ff4700; border-bottom-color: #ff4700; }
@media (prefers-reduced-motion: no-preference) {
  .ud-w { transition: color .18s ease, border-color .18s ease; }
}

/* FIVE REPS, AND WHAT HAPPENED TO EACH TAKE. Green is a rep the engine counted;
   orange is the take it marked, sitting on the stripe she is about to redo —
   «the 5 stripes do not fill with green or orange as I repeat» (Vitaly,
   2026-09-27). Green for banked and orange for redo-this-one is the pair he
   named; the row used to paint counted reps in the brand orange and a missed
   take in nothing at all, so a run of misses left it blank. */
.ud-bars { display: flex; align-items: center; gap: .4rem; margin: .7rem 0 0; }
.ud-bar { width: 2.1rem; height: .34rem; border-radius: 999px;
          background: currentColor; opacity: .16; }
.ud-bar.on { background: #1a7f4b; opacity: 1; }
.ud-bar.miss { background: #ff4700; opacity: 1; }
.ud-count { font-size: .78rem; opacity: .55; margin-left: .35rem;
            font-variant-numeric: tabular-nums; }
.ud-count:empty { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .ud-bar { transition: opacity .18s ease, background .18s ease; }
}
.ud-on[hidden] { display: none !important; }
.ud-on { display: inline-block; margin: .9rem 0 0; padding: .45rem .9rem; border-radius: 999px;
         border: 1px solid #ff4700; color: #ff4700; text-decoration: none; font-size: .9rem; }

/* speeds on the left, the way between examples on the right, a rule between */
.ud-player-bottom { display: flex; align-items: center; justify-content: space-between;
                    gap: .8rem; margin: .8rem 0 0; }
.ud-rates { margin: 0; }
.ud-hop { display: flex; align-items: center; gap: .3rem; padding-left: .8rem;
          border-left: 1px solid color-mix(in srgb, currentColor 18%, transparent); }
.ud-arrow { display: inline-grid; place-items: center; width: 1.7rem; height: 1.7rem;
            border-radius: 8px; border: 1px solid currentColor; text-decoration: none;
            color: inherit; opacity: .55; font-size: 1rem; line-height: 1; }
.ud-arrow.off { opacity: .16; }
/* …AND THE WAY ON FLASHES WHEN THERE IS ONE (Vitaly, 2026-09-27: «flash the Next
   button next to 2/20»). The ‹ › beside the count is the control she has been
   looking at all through the drill, so when the drill ends it is the one that
   says so — rather than a new button appearing somewhere else and her hunting
   for it. It breathes at the same rhythm every live control on the app does. */
.ud-arrow.flash { opacity: 1; border-color: #ff4700; color: #ff4700; }
@media (prefers-reduced-motion: no-preference) {
  .ud-arrow.flash { animation: ax-pulse 1.1s ease-in-out infinite; }
}
.ud-which { font-size: .78rem; opacity: .5; font-variant-numeric: tabular-nums;
            min-width: 2.6rem; text-align: center; }

/* "THERE IS MORE THIS WAY" — THE ARROW ALONE (Vitaly, 2026-09-27: «Remove the
   arrows with Up or Down text. I need just the arrows and only if the next
   section is not visible under the fold»). The words «Далі»/«Вгору» rode beside
   every arrow and said nothing the arrow did not; they are now the link's name
   for a reader and nothing on the screen. `.tuck` is steps.js's: it hides an
   arrow whose section is already on screen, so the arrow only ever means
   something she cannot see. `hidden` stays a different fact — there is nothing
   down there yet — and the two never write each other. */
.ud-down, .ud-up { display: inline-flex; align-items: center; justify-content: center;
                   width: 2rem; height: 2rem; margin: 1.4rem 0 0;
                   opacity: .45; text-decoration: none; color: inherit; }
.ud-up { margin: 0 0 1rem; }
.ud-down[hidden], .ud-up[hidden] { display: none !important; }
.ud-down.tuck, .ud-up.tuck { visibility: hidden; }
.ud-down:hover, .ud-up:hover { opacity: .8; }
.ud-down i, .ud-up i { font-style: normal; font-size: 1.25rem; line-height: 1; }

/* step one, in the same card the chew lives in */
.sd3-lede { margin: 0 0 1rem; font-size: .96rem; opacity: .7; line-height: 1.55; }
.ud-filmcard { padding: .5rem; border-radius: 16px; background: var(--card, #fff);
               border: 1px solid var(--line, #e7e7e7); }
.ud-filmcard .ud-video { margin: 0; }
.ud-filmcard video { display: block; width: 100%; border-radius: 12px; }

/* The fixed price bar is retired (2026-09-27): it carried «Лабораторія · 45 €»
   at every scroll position, which is exactly the price across the drill he
   asked to remove — «the €45 button should not be immediately visible when
   practicing in section 2». Its styles go with it rather than sitting here for
   somebody to revive by accident. The way to step three is the «Далі ↓» cue.

   THE OFFER ITSELF waits for the last film to start (offer.js). */
.sd3-offer[hidden] { display: none !important; }
@media (prefers-reduced-motion: no-preference) {
  .sd3-offer { animation: sd3-offer-in .28s ease both; }
}
@keyframes sd3-offer-in { from { opacity: 0; transform: translateY(6px); } }
.ud-list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2.2em; }
.ud-chip { display: inline-flex; align-items: center; justify-content: center; min-width: 34px;
           height: 34px; border-radius: 6px; border: 1px solid currentColor; opacity: .45;
           text-decoration: none; color: inherit; font-size: .9rem; }
.ud-chip.on { opacity: 1; font-weight: 700; }
.sd-map { display: grid; gap: 10px; margin: 1em 0 1.6em; }
.sd-tile { border: 1px solid var(--line); border-radius: var(--radius); padding: 14px;
           background: var(--card); opacity: .85; }
.sd-subs { margin: .6em 0 0; padding-left: 1.1em; font-size: .92rem; line-height: 1.6; opacity: .8; }

/* the landing's sections and its two drawings */
.sd-lp p { line-height: 1.6; margin: 0 0 1em; }
.sd-hero { padding-bottom: 1.6em; }
.sd-sec { border-top: 1px solid var(--line); padding: 1.8em 0 .6em; }
.sd-h2 { font-size: 1.35rem; line-height: 1.25; margin: 0 0 .7em; letter-spacing: -.005em; }
.sd-rules { margin: 0 0 1.2em; padding-left: 1.2em; line-height: 1.6; }
.sd-rules li { margin-bottom: .5em; }
.sd-price { font-size: 1.08rem; }

.sd-sw { margin: 1.2em 0 1em; }
.sd-sw-row { display: flex; align-items: stretch; gap: 6px; }
.sd-sw-box { position: relative; flex: 1; min-width: 0; border: 1px solid var(--line);
             border-radius: 10px; padding: 26px 8px 10px; background: var(--card);
             font-size: .86rem; line-height: 1.3; text-align: center; }
.sd-sw-box small { display: block; margin-top: .4em; opacity: .6; font-size: .78rem; }
.sd-sw-n { position: absolute; top: 6px; left: 8px; width: 16px; height: 16px; line-height: 16px;
           border-radius: 50%; background: var(--ink); color: #fff; font-size: .7rem;
           font-weight: 700; text-align: center; }
.sd-sw-three { border-color: var(--accent); }
.sd-sw-lines { display: flex; flex-direction: column; gap: 3px; margin: 8px auto 0; width: 70%; }
.sd-sw-lines i { display: block; height: 3px; border-radius: 2px; background: var(--accent); }
.sd-sw-lines i:nth-child(2) { width: 80%; }
.sd-sw-lines i:nth-child(3) { width: 60%; }
.sd-sw-fix { border-style: dashed; }
.sd-sw-arrow { align-self: center; opacity: .5; font-size: 1.1rem; }
@media (max-width: 480px) {
  .sd-sw-row { flex-wrap: wrap; }
  .sd-sw-box { flex: 1 1 42%; }
  .sd-sw-arrow { display: none; }
}

.sd-loop { display: grid; gap: 8px; margin: 1.2em 0 1.4em; }
.sd-loop-step { display: grid; grid-template-columns: 30px 1fr; column-gap: 10px;
                border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px;
                background: var(--card); align-items: start; }
.sd-loop-step b { display: block; font-size: 1rem; line-height: 1.3; }
.sd-loop-step small { display: block; grid-column: 2; margin-top: 2px; opacity: .68;
                      font-size: .86rem; line-height: 1.4; }
.sd-loop-n { grid-row: span 2; width: 26px; height: 26px; line-height: 26px; border-radius: 50%;
             background: var(--ink); color: #fff; text-align: center; font-size: .82rem;
             font-weight: 700; }
.sd-loop-him { border-color: var(--accent); }
.sd-loop-him .sd-loop-n { background: var(--accent); }
.sd-loop-back { text-align: center; opacity: .55; font-size: .95rem; letter-spacing: .02em; }

/* The game's rule under the exercise (2026-09-14): his sentence, shown until
   she hides it, one small link to bring it back. */
.game-reminder{position:relative;margin:10px 0 4px;padding:10px 36px 10px 14px;border:1px dashed var(--accent);
  border-radius:var(--radius);background:#fff7f3;font-size:.95rem;line-height:1.4}
.game-reminder.is-hidden{padding:0;border:0;background:transparent}
.game-reminder-text{margin:0}
.game-reminder-hide{position:absolute;right:6px;top:6px;border:0;background:transparent;cursor:pointer;
  font-size:1rem;line-height:1;color:var(--muted);padding:4px 6px}
.game-reminder-show{border:0;background:transparent;cursor:pointer;color:var(--accent);font-size:.85rem;
  text-decoration:underline dotted;padding:2px 0}
/* Her goal and what is in the way — the fold-out on the answer page (2026-09-14). */
.why summary{list-style:none;display:inline-block;cursor:pointer}
.why summary::-webkit-details-marker{display:none}
.why[open] summary{background:var(--accent);color:#fff;border-color:var(--accent)}
.why-body{margin-top:8px;padding:12px 14px;border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
.why-name{font-weight:600;margin-bottom:6px}
/* NO TABLE. Vitaly, 2026-09-14, on a phone: «I need much wider thing. no
   need for a table.» The label sits above its text, the text takes the whole
   width; the panel itself spans the row, not the name button. */
.why-row{display:block;padding:6px 0;border-top:1px solid var(--line)}
.why-row:first-of-type{border-top:0}
.why-k{display:block;margin-bottom:2px;font-size:.72rem;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.why-namef{padding:0 0 8px}
.why-namef-row{display:flex;gap:6px}
.why-namef input{flex:1 1 auto;min-width:0;font:inherit;padding:6px 8px;border:1px solid var(--line);border-radius:8px}
.who-note{flex-basis:100%;color:#b45309}
.why-list{list-style:none;margin:0;padding:0}
.why-d{padding:3px 0 3px 10px;border-left:3px solid var(--line)}
.why-high{border-left-color:#dc2626}
.why-medium{border-left-color:#d97706}
.why-low{border-left-color:#16a34a}

/* One row: ← ◀ [her name] ▶ · position · minutes · Ignore (2026-09-14). Her
   name is the fold-out; what it opens sits under the row, above her screen. */
.who-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:6px 0 10px;position:relative}
.who-back{font-size:1.3rem;text-decoration:none;color:var(--ink);padding:0 4px}
.who-arrow{font-size:1rem;text-decoration:none;color:var(--accent);padding:4px 8px;border:1px solid var(--line);border-radius:8px}
.who-arrow.off{color:var(--line);pointer-events:none}
/* The fold-out is as wide as the ROW (position:static here, relative on the
   row), not as wide as the name button it hangs off. */
.who{position:static}
.who summary{list-style:none;cursor:pointer;font-weight:600;font-size:1.05rem;padding:4px 10px;border:1px solid var(--line);border-radius:8px;background:var(--card)}
.who summary::-webkit-details-marker{display:none}
.who[open] summary{background:var(--accent);color:#fff;border-color:var(--accent)}
/* Opens OVER her screen, so the screen itself never moves (his rule of the
   same day: fixed in one place); one more click on her name closes it. */
.who-body{position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:5;padding:12px 14px;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--card);
  box-shadow:0 10px 30px rgba(0,0,0,.12);max-height:70vh;overflow:auto}
.who-meta{white-space:nowrap}
.who-ignore{margin-left:auto}
.why-video{margin-top:6px;aspect-ratio:16/9;max-width:520px}
.why-video iframe{width:100%;height:100%;border:0;border-radius:8px;background:#000}

.kp-note{display:block;font-size:.8em;opacity:.7;margin:.15em 0 0 1.6em}

/* THE TOP ROW (Vitaly, 2026-09-22 and 2026-09-23). Left: the logo, and on a
   practice screen its pill row (← · rungs · [?]). Right, together: today's
   minutes, «Звіт» once ten focused minutes are in (white on orange from thirty:
   «become white on orange after 30m»), the profile and the language icons — «Profile
   and Font/L1 should always be in the top right corner». The minutes take the free
   space's left edge, so the four sit as one group at the right.
   One row on a computer. On a phone the logo shrinks to «vi» and the pill row
   takes a second row of its own: measured at 375px, the logo, the rungs, the
   minutes, the button and the icons need ~470px. */
.nav .activity-timer{margin-left:auto}
.nav .activity-timer:hover{color:var(--ink)}
.nav .activity-timer ~ .links{margin-left:0}
.nav .nav-pills{flex:1 1 auto;min-width:0;padding:0}
.rep-btn{padding:5px 12px;border:1.5px solid #ff4700;border-radius:999px;background:#fff;color:#ff4700;font-size:.9rem;font-weight:600;text-decoration:none;white-space:nowrap}
.rep-btn.earned{background:#ff4700;color:#fff}
.rep-btn:active{transform:translateY(1px)}
@media (max-width:759px){.brand-full{display:none}.brand-mark{display:block}}
/* 619, not 639 (Vitaly, 2026-09-25, squeezing the window on C5's page: «the top
   got split into two rows when there was still space to go»): measured against
   the real markup, C's row — the widest of A/B/C, 5 pills — still fits on one
   line down to 611px (610 is the first width it does not); 619 keeps an 8px
   margin under that and drops the ~28px (620-638) the old 639 wrapped for
   nothing. Below it, the same order:10/flex-basis:100% still forces nav-pills
   onto a full row of its own — a natural flex-wrap here would let it just
   shrink/scroll instead (min-width:0 above), which is worse, not better. */
@media (max-width:619px){.nav .nav-pills{order:10;flex:1 0 100%}}
@media (max-width:420px){.rep-btn{padding:4px 10px;font-size:.82rem}}

/* The free doors' three numbered steps (Vitaly, 2026-09-23/24). Both /sandwich
   and /unchew draw them, so the look lives here rather than in one page. */
.sd3 { max-width: 34rem; margin: 0 auto; padding: 1.2rem 1rem 3rem; }
  .sd3-h1 { font-size: 1.5rem; line-height: 1.25; margin: .2rem 0 1.6rem; }
  .sd3-step { margin: 0 0 3.2rem; }
.sd3-step[hidden] { display: none !important; }
  .sd3-step h2 { display: flex; align-items: center; gap: .65rem; font-size: 1.15rem;
                 margin: 0 0 .9rem; font-weight: 600; }
  .sd3-n { display: inline-grid; place-items: center; width: 1.7rem; height: 1.7rem;
           border-radius: 999px; background: #ff4700; color: #fff; font-size: .95rem; }
  .sd3-price { margin: 1rem 0 .8rem; font-size: 1.05rem; }
  .sd3-pay { display: block; text-align: center; }
  .sd3-terms { margin: .7rem 0 0; font-size: .85rem; opacity: .6; }
  .sd3-terms a { color: inherit; }
  .ud-done-line { margin: .8rem 0 0; font-size: .9rem; opacity: .55; font-variant-numeric: tabular-nums; }
  .sd3-modal { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
               background: rgba(0,0,0,.45); padding: 1rem; }
  .sd3-modal[hidden] { display: none !important; }
  .sd3-modal-card { background: var(--card, #fff); color: inherit; border-radius: 16px;
                    padding: 1.25rem; max-width: 22rem; width: 100%; }
  .sd3-modal-card h3 { margin: 0 0 .4rem; font-size: 1.05rem; }
  .sd3-modal-card p { margin: 0 0 1rem; font-size: .9rem; opacity: .75; line-height: 1.45; }
  .sd3-later { display: block; margin: .9rem auto 0; background: none; border: 0; font: inherit;
               font-size: .85rem; opacity: .55; text-decoration: underline; cursor: pointer; color: inherit; }
