/* IELTS Speaking Practice, in the Writing site's look (ielts-docs-grader/web/app.css): the IELTS red as the accent,
   black text on white and light grey, the DISC project's Additional CSS typography (system font, body 17px, body
   reduced 14px, caption 12px, headlines), the same radii (cards 24px, inner 16px, fields 12px, pills) and spacing
   (multiples of 12px, then 6px, then 4px). Light mode only.
   This file holds the tokens, the type, the frame, buttons, cards, chips, the shared components (the stage, the big
   record button, sheets and the two answer bars), the toast and the focus rules. Each area's own rules are in css/
   (coach, practice, practice-read, details, mock, sounds, progress, repeat), loaded after this file. */
:root {
  --red: #d0343e;          /* the official IELTS red, as on the Writing site */
  --red-dark: #b02a33;
  --red-press: #962229;
  --red-bright: #d0343e;
  --pink-50: #fdf1f2;
  --pink-100: #f8dcdf;
  --pink-200: #f2c2c6;
  --pink-300: #e68d94;
  --ink: #1d1d1f;
  --ink-2: #6e6e73;
  --line: #e3e3e6;
  --bg: #f5f5f7;
  --bg-hover: #e9e9ec;     /* a grey control under the pointer */
  --card: #ffffff;
  --good: #1f7a3a;
  --good-50: #e9f4ec;
  --highlight: #fff3a3;    /* useful phrases in model answers, like a highlighter pen (the Writing site's token) */
  --toast: rgba(29, 29, 31, 0.92);
  --font: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Helvetica", system-ui, "Roboto", "Segoe UI", "Arial", sans-serif;
  --r-card: 24px;
  --r-inner: 16px;
  --r-field: 12px;
  --r-pill: 100px;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 8px 24px rgba(0, 0, 0, 0.05);
  --page-wide: 1280px;     /* the content width: the window's width less the gutters, up to this (Eric, 2026-10-26: use
                              the whole window) */
  --gutter: 24px;
  --panel-gap: 36px;
  --frame-pad: 44px;       /* the space below the last content (the standard layout) */
  --frame-gap: 36px;       /* between the top bar and the page */
  --top-h: 36px;           /* the controls in the top bar: the Settings button and the tabs */
  --head-h: 60px;          /* the top bar: its 36px controls with 12px above and below */
  --tabbar-h: 54px;        /* the phone's bottom tab bar, above the home indicator */
  --dock: 0px;             /* the room the bottom tab bar takes: none above 734px */
  --panel-w: 360px;        /* a tab's progress panel beside its main column */
  --seg-h: 42px;           /* the Practice | Test switch: a 32px segment in 4px of padding and a 1px border */
  --bar-bg: rgba(245, 245, 247, 0.86);   /* the top bar: the page's grey, slightly see-through */
  --tabbar-bg: rgba(255, 255, 255, 0.92); /* the phone's tab bar: white, slightly see-through, as on iPhone */
  /* The height a page has under the top bar: a stage fills it, so its content is centred in the window. */
  --avail: calc(100dvh - var(--head-h) - env(safe-area-inset-top, 0px) - var(--frame-gap) - var(--frame-pad) - max(var(--dock), env(safe-area-inset-bottom, 0px)));
  --ease: cubic-bezier(.2, .8, .2, 1);
  --t-morph: 240ms;        /* a button changing shape */
  --t-move: 360ms;         /* content moving */
  color-scheme: light;
}
@media only screen and (max-width: 1068px) { :root { --panel-gap: 24px; --frame-pad: 36px; } }
@media only screen and (max-width: 734px) { :root { --frame-pad: 32px; --frame-gap: 24px; --dock: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px)); } }
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; min-height: 100dvh; background: var(--bg); color: var(--ink); font-family: var(--font);
  font-synthesis: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-tap-highlight-color: transparent;
}

/* ---------- type: the Additional CSS styles, each written once with every element that uses it ---------- */
/* .typography-headline-reduced: pane titles */
.sec h1 { font-size: 40px; line-height: 1.1; font-weight: 600; letter-spacing: 0em; }
@media only screen and (max-width: 1068px) { .sec h1 { font-size: 32px; line-height: 1.125; font-weight: 600; letter-spacing: 0.004em; } }
@media only screen and (max-width: 734px) { .sec h1 { font-size: 28px; line-height: 1.14286; font-weight: 600; letter-spacing: 0.007em; } }
/* .typography-eyebrow-super: figures in tiles, scores; .t-super: a question or a point's headline
   (also on an h1 inside a pane, which would otherwise take the pane title's size) */
.tile-value, .score b, .ring .rec-time, .t-super, .sec .t-super { font-size: 32px; line-height: 1.125; font-weight: 600; letter-spacing: 0.004em; }
@media only screen and (max-width: 1068px) { .tile-value, .score b, .ring .rec-time, .t-super, .sec .t-super { font-size: 28px; line-height: 1.14286; font-weight: 600; letter-spacing: 0.007em; } }
@media only screen and (max-width: 734px) { .tile-value, .score b, .ring .rec-time, .t-super, .sec .t-super { font-size: 24px; line-height: 1.16667; font-weight: 600; letter-spacing: 0.009em; } }
/* The question or point on the stage (.t-super): on a computer the headline's bundle (.typography-headline-reduced),
   below 1069px .t-super's own. Written here, after .t-super, so it wins over .sec .t-super. */
.stage .t-super { font-size: 40px; line-height: 1.1; font-weight: 600; letter-spacing: 0em; }
@media only screen and (max-width: 1068px) { .stage .t-super { font-size: 28px; line-height: 1.14286; font-weight: 600; letter-spacing: 0.007em; } }
@media only screen and (max-width: 734px) { .stage .t-super { font-size: 24px; line-height: 1.16667; font-weight: 600; letter-spacing: 0.009em; } }
/* .typography-eyebrow-reduced: card and block headings, the cue card's prompt, the drill words */
.card-title, .block h2, .confirm h2, .cue-prompt, .word, .choice, .syll { font-size: 21px; line-height: 1.19048; font-weight: 600; letter-spacing: 0.011em; }
@media only screen and (max-width: 734px) { .card-title, .block h2, .confirm h2, .cue-prompt, .word, .choice, .syll { font-size: 19px; line-height: 1.21053; font-weight: 600; letter-spacing: 0.012em; } }
/* .typography-intro: ledes and the texts read aloud, the model answers, the question in the test;
   .t-intro: a sub line or a sentence to say */
.lede, .read-text, .model-text, .t-intro { font-size: 21px; line-height: 1.381; font-weight: 400; letter-spacing: 0.011em; }
@media only screen and (max-width: 734px) { .lede, .read-text, .model-text, .t-intro { font-size: 19px; line-height: 1.4211; font-weight: 400; letter-spacing: 0.012em; } }
/* .typography-body: everything else unless listed below; .t-body: the label under the big button */
body, .btn, .transcript, textarea, .pane h3, .sheet h3, .chart-title, .coach-tip, .t-body { font-size: 17px; line-height: 1.47059; font-weight: 400; letter-spacing: -0.022em; }
/* .typography-body-reduced; .t-small: an eyebrow, a caption, a hint line */
.seg button, .seg a, .hint, .field-err, .chip, .tile-label, .tile-note, .crumb, .compare, .notes-kept, .toast,
.t-small, .quiet, .foot-link { font-size: 14px; line-height: 1.42859; font-weight: 400; letter-spacing: -0.016em; }
/* .typography-caption: the names in the phone's bottom tab bar */
@media only screen and (max-width: 734px) { .tab span { font-size: 12px; line-height: 1.33337; font-weight: 400; letter-spacing: -0.01em; } }
/* A small pill (Done, Delete) has the reduced size and keeps the pills' semibold, like every other pill. */
.btn.small { font-size: 14px; line-height: 1.42859; letter-spacing: -0.016em; }
/* The roles of the .t-* classes (B.0): the label under the big button is semibold; the small lines are secondary.
   With .t-small, .eyebrow ("Part 1") is semibold and .caption (the question on a point or practice screen) keeps to
   two lines; with .t-intro, .sub (the line under a headline) is secondary, while a sentence to say stays black. */
.t-body { font-weight: 600; }
.t-small { color: var(--ink-2); }
.t-small.eyebrow { font-weight: 600; }
.t-small.caption { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
.t-intro.sub { color: var(--ink-2); }

[hidden] { display: none !important; }
.nowrap { white-space: nowrap; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
b, strong { font-weight: 600; }
p { margin: 0; }
a { color: var(--red); text-decoration: none; }
/* Hover styles apply only where there is a pointer that hovers: on a phone a tap never leaves a control looking
   hovered. */
@media (hover: hover) { a:hover { color: var(--red-dark); } }
button, a, input, textarea { font-family: inherit; letter-spacing: inherit; }
button:focus-visible, a:focus-visible, input:focus-visible, textarea:focus-visible, summary:focus-visible {
  outline: 2px solid var(--red); outline-offset: 3px;
}
/* A control without corners of its own gets a rounded ring; one with its own corners (a card, a choice, a chip) keeps
   them, so the keyboard never reshapes it (no specificity, so any class rule wins). */
:where(button, a, input, textarea, summary):where(:focus-visible) { border-radius: 10px; }
button:focus:not(:focus-visible), a:focus:not(:focus-visible) { outline: none; }
/* Headings and panes that take the focus when they appear (a sheet's heading, the stage's question) are not controls. */
[tabindex="-1"]:focus { outline: none; }
/* Pills and rows keep their own corners under the ring. */
.btn:focus-visible, .menu-btn:focus-visible, .seg button:focus-visible, .seg a:focus-visible, .tab:focus-visible, a.link-chip:focus-visible { border-radius: var(--r-pill); }
/* In the phone's tab bar the ring sits inside the tab, with the field's corners. */
@media only screen and (max-width: 734px) { .tab:focus-visible { outline-offset: -4px; border-radius: var(--r-field); } }
.list-row:focus-visible, .list-link:focus-visible { border-radius: var(--r-field); }
.ico { width: 18px; height: 18px; flex: none; }
.play:focus-visible, .rec:focus-visible, .mic-btn:focus-visible { border-radius: 50%; }

/* The content area: the window's width less 24px each side, up to 1280px, 87.5% on a phone. The top bar's row and
   the page share it. The page starts 36px under the bar (24px on a phone) and leaves 44px under its last content (36px
   on a tablet, 32px on a phone), plus the bottom tab bar on a phone. */
.top-in, .main { width: min(var(--page-wide), calc(100% - 2 * var(--gutter))); margin-inline: auto; }
@media only screen and (max-width: 734px) { .top-in, .main { width: 87.5%; } }

/* ---------- the top bar (B.0): the brand on the left, Settings on the right, the tabs between them ---------- */
/* It stays at the top of the window, on the page's grey, slightly see-through over what scrolls under it. */
header.top {
  position: sticky; top: 0; z-index: 20; padding-top: env(safe-area-inset-top, 0px);
  background: var(--bar-bg); -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px);
}
/* On a phone the bar is the page's grey without the blur: a blur would hold the tab bar (fixed) inside the top bar. */
@media only screen and (max-width: 734px) { header.top { background: var(--bg); -webkit-backdrop-filter: none; backdrop-filter: none; } }
/* Brand, tabs, Settings, in reading order; the tabs centred in the bar whatever the brand's width. */
.top-in { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 24px; height: var(--head-h); }
.top-in > .menu-btn { justify-self: end; }
.brand { display: flex; align-items: center; justify-self: start; min-width: 0; }
/* The nóinhiều wordmark (Logos/noinhieu.com), its letters as shapes: 'nói' in the IELTS red, 'nhiều' in black. */
.logo { display: block; height: 24px; width: auto; }
.logo-a { fill: var(--red); }
.logo-b { fill: var(--ink); }
@media only screen and (max-width: 734px) { .logo { height: 20px; } }
/* The tabs (js/tabs.js): in the middle of the top bar, the current one in pink; on a
   phone, a bar along the bottom with an icon over each name, the current one in red, as on iPhone. */
.tabs { display: flex; gap: 4px; }
.tab {
  display: inline-flex; align-items: center; height: var(--top-h); padding: 0 18px; border-radius: var(--r-pill);
  color: var(--ink); white-space: nowrap; transition: background-color .15s ease;
}
@media (hover: hover) { .tab:hover { background: var(--bg-hover); color: var(--ink); } }
.tab[aria-current] { background: var(--pink-100); color: var(--ink); }
.tab-ico { display: none; }
@media only screen and (max-width: 734px) {
  .top-in { grid-template-columns: minmax(0, 1fr) auto; }
  .tabs {
    position: fixed; z-index: 21; bottom: 0; inset-inline: 0; height: var(--dock); padding-bottom: env(safe-area-inset-bottom, 0px); gap: 0;
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    background: var(--tabbar-bg); -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px); box-shadow: 0 -1px 0 var(--line);
  }
  .tab { flex-direction: column; justify-content: center; gap: 4px; min-width: 0; height: var(--tabbar-h); padding: 4px; border-radius: 0; color: var(--ink-2); }
  /* A name too long for a narrow phone ends in an ellipsis, as on iPhone. */
  .tab span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  .tab[aria-current] { background: none; color: var(--red); }
  .tab-ico { display: block; width: 24px; height: 24px; }
}
@media only screen and (max-width: 734px) and (hover: hover) { .tab:hover { background: none; color: var(--ink); } .tab[aria-current]:hover { color: var(--red); } }
/* The Settings button: a 48x36 pill with SF Symbols' gearshape. */
.menu-btn {
  display: inline-flex; align-items: center; justify-content: center; flex: none; width: 48px; height: var(--top-h); padding: 0;
  border: 1px solid var(--line); border-radius: var(--r-pill); background: #fff; color: var(--ink); cursor: pointer;
  transition: background-color .15s ease;
}
@media (hover: hover) { .menu-btn:hover { background: var(--bg-hover); } } /* a tap leaves no grey behind */
.menu-btn svg { width: 20px; height: 20px; }

/* ---------- buttons and fields (the Writing site's) ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font-weight: 600; line-height: 1; padding: 12px 24px; min-height: 48px;
  border-radius: var(--r-pill); border: 0; background: var(--red); color: #fff; cursor: pointer; text-align: center;
  transition: background-color .15s ease;
}
@media (hover: hover) { .btn:hover { background: var(--red-dark); color: #fff; } }
.btn:active { background: var(--red-press); }
.btn:disabled { opacity: .55; cursor: default; }
.btn.plain { background: var(--bg); color: var(--ink); }
@media (hover: hover) { .btn.plain:hover { background: var(--bg-hover); color: var(--ink); } }
.btn.small { padding: 6px 18px; min-height: 36px; }
.link { display: inline-flex; align-items: center; gap: 4px; background: none; border: 0; padding: 0; color: var(--red); font-weight: 600; cursor: pointer; font-size: inherit; text-align: left; }
@media (hover: hover) { .link:hover { color: var(--red-dark); } }
/* The quiet secondary control (B.0): a text button with a 44px hit area; it turns black under the pointer, never red. */
.quiet {
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 12px;
  border: 0; background: none; color: var(--ink-2); font-weight: 600; cursor: pointer; text-align: center;
}
@media (hover: hover) { .quiet:hover { color: var(--ink); } }
/* The footer link after an answer ("See all feedback"): a link, not a control. Its 44px box leaves 12px above the text. */
.foot-link {
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 12px;
  border: 0; background: none; color: var(--ink-2); cursor: pointer; text-align: center;
}
@media (hover: hover) { .foot-link:hover { color: var(--ink); } }
textarea {
  font: inherit; width: 100%; padding: 12px; color: var(--ink); resize: vertical;
  border: 1px solid var(--line); border-radius: var(--r-field); background: #fff;
}
/* A field's focus is its own border, 2px solid red with its corners (1px border and 1px shadow), so nothing moves. */
textarea:focus { border-color: var(--red); outline: none; box-shadow: 0 0 0 1px var(--red); }
.hint { color: var(--ink-2); }
.field-err { color: var(--red-bright); }
.spinner { width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--pink-100); border-top-color: var(--red); animation: spin .8s linear infinite; flex: none; display: inline-block; }
@keyframes spin { to { transform: rotate(360deg); } }
.status { display: flex; align-items: center; gap: 12px; }
.actions { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
/* A page's primary and its quiet secondary (the Test page, Pronunciation): side by side, the primary at least
   240px wide; on a phone the primary fills the width and the quiet one sits centred under it, as on the stage. The
   quiet one's 44px box leaves 12px around its text, so it reads 24px from the primary. */
.menu-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.menu-actions > .btn { min-width: 240px; }
@media only screen and (max-width: 734px) {
  .menu-actions { display: grid; justify-items: center; }
  .menu-actions > .btn { width: 100%; min-width: 0; }
}

.seg { display: inline-flex; background: #fff; border-radius: var(--r-pill); padding: 4px; border: 1px solid var(--line); justify-self: start; max-width: 100%; }
/* Its parts are buttons, or links where it switches between pages (Practice | Test, js/tabs.js). */
.seg button, .seg a { font-weight: 400; border: 0; background: transparent; color: var(--ink-2); padding: 6px 12px; border-radius: var(--r-pill); cursor: pointer; white-space: nowrap; }
@media (hover: hover) { .seg button:hover, .seg a:hover { color: var(--ink); } }
.seg button[aria-selected="true"], .seg button[aria-pressed="true"], .seg a[aria-current] { background: var(--red); color: #fff; }
@media (hover: hover) { .seg a[aria-current]:hover { color: #fff; } }
/* The ring sits outside the segment, so it shows on the current one's red too. */
.seg button:focus-visible, .seg a:focus-visible { outline-offset: 2px; }

.card { background: var(--card); border-radius: var(--r-card); padding: 36px; box-shadow: var(--shadow); display: grid; gap: 24px; align-content: start; min-width: 0; }
@media only screen and (max-width: 734px) { .card { padding: 24px; border-radius: 20px; } }
.card-title { margin: 0; }
/* A line under a card's title belongs to it: 12px from the title, 24px from what follows. */
.card > .card-title + .hint { margin-top: -12px; }
.pane h2, .pane h3 { margin: 0; }

/* ---------- the page ---------- */
.main { display: grid; gap: 36px; min-width: 0; padding-block: var(--frame-gap) calc(var(--frame-pad) + max(var(--dock), env(safe-area-inset-bottom, 0px))); }
.pane:focus { outline: none; }
.sec { display: grid; gap: 24px; align-content: start; }
.sec-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.sec-title { display: grid; gap: 12px; min-width: 0; }
.sec h1 { margin: 0; overflow-wrap: anywhere; }
.sec > .sec-head + .hint { margin-top: -12px; }
.sec h1::after { content: ""; display: block; width: 56px; height: 5px; border-radius: 5px; background: var(--red); margin-top: 12px; }
.lede { color: var(--ink-2); max-width: 34em; }
.crumb { display: inline-flex; align-items: center; gap: 4px; color: var(--ink-2); font-weight: 600; justify-self: start; }
@media (hover: hover) { .crumb:hover { color: var(--ink); } }
.crumb .ico { width: 14px; height: 14px; }

/* The confirmation before anything is deleted (js/confirm.js, shared with the Writing site). */
.confirm {
  width: min(420px, calc(100% - 48px)); padding: 36px; border: 0; border-radius: var(--r-card);
  background: var(--card); color: var(--ink); box-shadow: 0 20px 48px rgba(0, 0, 0, 0.18); text-align: center;
}
.confirm[open] { display: grid; gap: 12px; }
.confirm::backdrop { background: rgba(0, 0, 0, 0.32); }
.confirm h2, .confirm p { margin: 0; }
.confirm p { color: var(--ink-2); }
.confirm-actions { display: flex; justify-content: center; gap: 12px; flex-wrap: wrap; margin-top: 12px; }
@media only screen and (max-width: 734px) { .confirm { padding: 24px; } }

/* ---------- tiles, chips, blocks ---------- */
.tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; }
.tile { display: grid; gap: 4px; align-content: start; padding: 24px; border-radius: var(--r-card); background: var(--card); box-shadow: var(--shadow); min-width: 0; }
.card .tile { background: var(--bg); box-shadow: none; border-radius: var(--r-inner); }
.tile-label { color: var(--ink-2); font-weight: 600; }
.tile-value { font-variant-numeric: tabular-nums; }
.tile-note { color: var(--ink-2); }
@media only screen and (max-width: 1068px) { .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; } }
@media only screen and (max-width: 734px) { .tile { padding: 18px; border-radius: 20px; } .card .tile { border-radius: var(--r-inner); } }
.block { display: grid; gap: 12px; align-content: start; min-width: 0; }
.block h2, .block h3 { margin: 0; }
.block h3 { font-weight: 600; }
.chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.chip { display: inline-flex; align-items: center; gap: 4px; padding: 6px 12px; border-radius: var(--r-pill); background: var(--bg); color: var(--ink); }
.chip .ico { width: 14px; height: 14px; }
.chip.good { background: var(--good-50); color: var(--good); }
a.link-chip { background: var(--pink-50); color: var(--red-dark); font-weight: 600; }
@media (hover: hover) { a.link-chip:hover { background: var(--pink-100); color: var(--red-dark); } }
mark.phr { background: var(--highlight); color: inherit; border-radius: 4px; padding: 0 2px; box-decoration-break: clone; -webkit-box-decoration-break: clone; }
mark.used { background: var(--good-50); color: var(--good); border-radius: 4px; padding: 0 2px; box-decoration-break: clone; -webkit-box-decoration-break: clone; }
.transcript { max-width: 46em; }
.model-text, .read-text { max-width: 36em; }
.score { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }

/* ---------- list rows (All Sounds, Topics, Past Tests, History, the practices after an answer) ---------- */
.list { gap: 0; }
.list .card-title { margin-bottom: 12px; }
.list > .card-title + .hint { margin-top: 0; }
.list-row { position: relative; display: flex; align-items: center; gap: 12px; padding: 12px; margin-inline: -12px; border-radius: var(--r-field); color: var(--ink); }
@media (hover: hover) {
  a.list-row:hover, .list-row:has(.list-link:hover) { background: var(--bg); color: var(--ink); }
  .list-link:hover { color: var(--ink); }
}
/* Separators inset to the text, as in an iPhone list, so they stay straight beside a row's rounded fill; a filled or
   focused row hides the lines above and below it. */
.list-row + .list-row::before { content: ""; position: absolute; top: 0; left: 12px; right: 12px; height: 1px; background: var(--line); }
@media (hover: hover) { a.list-row:hover::before, a.list-row:hover + .list-row::before, .list-row:has(.list-link:hover)::before, .list-row:has(.list-link:hover) + .list-row::before { display: none; } }
.list-row:focus-visible::before, .list-row:focus-visible + .list-row::before, .list-row:has(.list-link:focus-visible)::before, .list-row:has(.list-link:focus-visible) + .list-row::before { display: none; }
.list-link { display: flex; flex: 1; min-width: 0; color: var(--ink); border-radius: var(--r-field); padding: 0; }
.list-main { display: grid; gap: 4px; flex: 1; min-width: 0; }
.list-title { overflow-wrap: anywhere; }
.list-row > .ico { color: var(--ink-2); }

/* ---------- the record button (the stage, the mock test, reading aloud, sounds) ---------- */
.rec-title { font-weight: 600; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.rec-time { font-variant-numeric: tabular-nums; }
/* The record button, as in Voice Memos: a red dot to start, a rounded square to stop. */
.rec {
  position: relative; display: grid; place-content: center; width: 72px; height: 72px; flex: none; padding: 0;
  border-radius: 50%; border: 0; background: #fff; box-shadow: 0 0 0 4px var(--line) inset; cursor: pointer;
}
.rec-dot { width: 52px; height: 52px; border-radius: 50%; background: var(--red); transition: background-color .15s; }
@media (hover: hover) {
  .rec:hover { box-shadow: 0 0 0 4px var(--pink-200) inset; }
  .rec:hover .rec-dot { background: var(--red-dark); }
}
.rec-square { width: 28px; height: 28px; border-radius: 8px; background: var(--red); }
.rec.on { box-shadow: 0 0 0 4px var(--pink-200) inset; }
.rec.listening { background: var(--pink-50); box-shadow: none; cursor: default; }
.rec-wave { display: flex; align-items: center; gap: 4px; height: 28px; }
.rec-wave i { width: 5px; height: 100%; border-radius: 3px; background: var(--red); animation: wave 1s ease-in-out infinite; }
.rec-wave i:nth-child(2) { animation-delay: -0.33s; }
.rec-wave i:nth-child(3) { animation-delay: -0.66s; }
@keyframes wave { 0%, 100% { transform: scaleY(0.35); } 50% { transform: scaleY(1); } }
/* A round play button for a clip. */
.play {
  display: grid; place-content: center; width: 44px; height: 44px; flex: none; padding: 0;
  border: 0; border-radius: 50%; background: var(--bg); color: var(--ink); cursor: pointer;
}
@media (hover: hover) { .play:hover { background: var(--bg-hover); } }
.play[aria-pressed="true"] { background: var(--pink-100); color: var(--red-dark); }
.play.big { width: 56px; height: 56px; }
.play .ico { width: 18px; height: 18px; }
.card .play { background: var(--bg); }
@media (hover: hover) { .card .play:hover { background: var(--bg-hover); } }
.rec-play { display: flex; align-items: center; gap: 12px; }

/* ---------- the guided practice's stage (B.0): one state at a time, centred, at most 720px wide ---------- */
/* .stage-main holds the eyebrow, the question or point and its visual; .stage-controls the big button or the primary,
   its label, the quiet secondary and the footer link. The stage fills the window under the top bar, its content
   centred; on a phone the content is centred and the controls sit at the bottom, in the thumb zone. On a computer it
   is bigger: 720px wide, the question in the headline size and the big button 120px (600px and 96px below 1069px). */
.stage { width: 100%; max-width: 720px; min-height: var(--avail); margin-inline: auto; display: grid; gap: var(--panel-gap); align-content: center; justify-items: center; text-align: center; }
@media only screen and (max-width: 1068px) { .stage { max-width: 600px; } }
.stage h1::after { display: none; }
.stage-main { display: grid; gap: 12px; justify-items: center; width: 100%; min-width: 0; }
.stage-controls { display: grid; justify-items: center; width: 100%; }
.stage-controls > .quiet, .stage-controls > .foot-link { margin-top: 12px; }
.stage-controls > .btn { min-width: 240px; }
@media only screen and (max-width: 734px) {
  .stage { grid-template-rows: minmax(0, 1fr) auto; align-content: stretch; }
  .stage-main { align-self: center; }
  .stage-controls { align-self: end; }
  .stage-controls > .btn { width: 100%; min-width: 0; }
}
/* The big record button: a 96px white circle with the 4px ring and a 72px red dot; to stop, a 36px square with 10px
   corners (today's 8px on 28px); on a computer 120px, a 90px dot and a 44px square with 12px corners. It keeps a 12px
   margin for the level ring, so nothing moves while it grows. */
.rec.big { --lv: 0; width: 120px; height: 120px; margin: 12px; transition: box-shadow 80ms linear, background-color var(--t-morph) var(--ease); }
.rec.big .rec-dot { width: 90px; height: 90px; }
.rec.big .rec-square { width: 44px; height: 44px; border-radius: 12px; }
@media only screen and (max-width: 1068px) {
  .rec.big { width: 96px; height: 96px; }
  .rec.big .rec-dot { width: 72px; height: 72px; }
  .rec.big .rec-square { width: 36px; height: 36px; border-radius: 10px; }
}
.rec.big .rec-dot, .rec.big .rec-square { transition: width var(--t-morph) var(--ease), height var(--t-morph) var(--ease), border-radius var(--t-morph) var(--ease), background-color .15s; }
/* Recording: the ring follows the voice (--lv, 0 to 1, set while recording). */
.rec.big.on { box-shadow: 0 0 0 4px var(--pink-200) inset, 0 0 0 calc(var(--lv) * 12px) var(--pink-100); }
/* Listening: the pink wave; a tap skips the question's audio. */
.rec.big.listening { background: var(--pink-50); box-shadow: none; cursor: pointer; }
/* Thinking: the spinner in the button's place. */
.rec.big.thinking { background: none; box-shadow: none; cursor: default; }
.rec.big .spinner { width: 24px; height: 24px; }
/* The big button with its label under it (js/recpanel.js recButton). */
.rec-btn { display: grid; justify-items: center; }

/* ---------- words to tap for a reason (reading aloud, the read-back practices, the feedback) ---------- */
.w.bad {
  display: inline; padding: 0; border: 0; background: none; font: inherit; color: inherit; cursor: pointer;
  text-decoration: underline wavy var(--red-bright); text-decoration-skip-ink: none; text-underline-offset: 4px;
}
@media (hover: hover) { .w.bad:hover { color: var(--red-dark); } }
.w.bad:focus-visible { outline-offset: 2px; border-radius: 4px; }
.tip-card { display: grid; gap: 6px; padding: 12px 18px; border-radius: var(--r-field); background: var(--pink-50); max-width: 36em; }
.tip-word { font-weight: 600; }
/* Status lines that are announced when they change (aria-live) stay in place even while empty, and keep one line of
   height so nothing moves when their words appear. */
.read-detail:empty, .read-result:empty, .status:empty, p.hint:empty:not([aria-live]) { display: none; }
p.hint[aria-live]:empty::before { content: "\200b"; }

/* ---------- switches (the test, Settings) ---------- */
.switch-row { display: flex; align-items: center; gap: 12px; cursor: pointer; font-weight: 600; justify-self: start; }
.switch-row input { position: absolute; opacity: 0; width: 1px; height: 1px; }
/* The size of the iPhone switch. */
.switch { position: relative; width: 51px; height: 31px; flex: none; border-radius: var(--r-pill); background: var(--line); transition: background-color .2s; }
.switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 27px; height: 27px; border-radius: 50%; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); transition: transform .2s; }
.switch-row input:checked + .switch { background: var(--red); }
.switch-row input:checked + .switch::after { transform: translateX(20px); }
.switch-row input:focus-visible + .switch { outline: 2px solid var(--red); outline-offset: 3px; }

/* ---------- how it works (B.35): four short blocks, two a row where there is room, then the credit ---------- */
.card.how { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 36px; }
.how .how-credit { grid-column: 1 / -1; }
@media only screen and (max-width: 734px) { .card.how { grid-template-columns: minmax(0, 1fr); gap: 24px; } }

/* ---------- sheets (B.20, B.21): a <dialog> over the page, opened with showModal() ---------- */
/* .sheet: the full-height sheet (All Feedback). Wider than 734px it is a 720px panel down the middle of the screen; on
   a phone it rises from the bottom with 24px top corners and 24px of the page left above it. */
.sheet {
  --sheet-pad: 36px; --sheet-pad-x: 36px;
  position: fixed; inset: 24px 0; margin: 0 auto; width: min(720px, calc(100% - 48px)); max-width: none; height: auto; max-height: none;
  padding: var(--sheet-pad) var(--sheet-pad-x); border: 0; border-radius: var(--r-card); background: var(--card); color: var(--ink);
  box-shadow: 0 20px 48px rgba(0, 0, 0, 0.18); overflow-y: auto; overscroll-behavior: contain;
}
.sheet[open] { display: grid; gap: 24px; align-content: start; animation: sheet-in var(--t-move) var(--ease); }
.sheet::backdrop { background: rgba(0, 0, 0, 0.32); }
/* The title and Done stay at the top while a long sheet scrolls under them, edge to edge, with a hairline under
   them once something has scrolled under (where the browser has scroll-driven animations). */
.sheet-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  position: sticky; top: calc(-1 * var(--sheet-pad)); z-index: 1;
  margin: calc(-1 * var(--sheet-pad)) calc(-1 * var(--sheet-pad-x)) 0; padding: var(--sheet-pad) var(--sheet-pad-x) 12px;
  background: var(--card);
}
@supports (animation-timeline: scroll()) {
  .sheet-head { animation: sheet-head-line linear both; animation-timeline: scroll(nearest block); animation-range: 0 24px; }
}
@keyframes sheet-head-line { from { box-shadow: 0 1px 0 transparent; } to { box-shadow: 0 1px 0 var(--line); } }
.sheet-head h2 { margin: 0; }
@keyframes sheet-in { from { opacity: 0; transform: translateY(24px); } }
/* .sheet.settings: Settings (js/settings.js). Wider than 734px it sits at the top right, 324px wide, 12px under the top
   bar and lined up with the page's right edge; on a phone it is a bottom sheet. Its title and Close,
   then the tips switch and the row to the page about the site, 12px apart. */
.sheet.settings {
  --sheet-pad: 24px; --sheet-pad-x: 24px;
  inset: calc(env(safe-area-inset-top, 0px) + var(--head-h) + 12px) max(var(--gutter), calc((100% - var(--page-wide)) / 2)) auto auto;
  margin: 0; width: 324px; max-height: calc(100dvh - env(safe-area-inset-top, 0px) - var(--head-h) - 36px);
}
.sheet.settings[open] { gap: 12px; }
/* The switch lines up with the row's text (a row reaches 12px past it for its hover fill). */
.sheet.settings .switch-row { padding-block: 6px; }
@media only screen and (max-width: 734px) {
  .sheet, .sheet.settings {
    --sheet-pad: 24px; --sheet-pad-x: 6.25vw; /* the phone's 87.5% content width: the sheet is as wide as the screen */
    inset: 24px 0 0; margin: 0; width: 100%; border-radius: 24px 24px 0 0;
    padding: var(--sheet-pad) var(--sheet-pad-x) calc(var(--sheet-pad) + env(safe-area-inset-bottom));
  }
  .sheet.settings { inset: auto 0 0; max-height: calc(100dvh - 24px); }
}

/* ---------- a tab's page (js/tabs.js): its main column, and its progress panel ---------- */
/* The panel sits beside the main column on a computer (360px, 36px away) and under it below 1069px. The Practice tab's
   Practice | Test switch sits over its main column, 24px above the page. A page with a stage keeps the window's height
   for its main column, so the stage is centred in the window and the panel is under it on a phone. */
.tab-page { display: grid; grid-template-columns: minmax(0, 1fr) var(--panel-w); gap: var(--panel-gap); align-items: start; }
.tab-body { display: flex; flex-direction: column; gap: 24px; min-width: 0; }
.tab-body:has(.stage) { min-height: var(--avail); }
.tab-top { align-self: center; }
.tab-main { flex: 1; display: grid; gap: 24px; align-content: start; min-width: 0; }
.tab-main:has(> .stage) { align-content: stretch; }
.tab-main > .stage { min-height: 0; }
.tab-panel { display: grid; gap: 24px; align-content: start; min-width: 0; }
/* The panel's card is narrower than a page's, so it keeps 24px inside, as on a phone; a long question keeps to two lines. */
.tab-panel .card { padding: 24px; }
.tab-panel .list-title { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
/* Above 734px the Practice | Test switch sits over the top of a stage without taking its room, and the stage keeps the
   switch's room above and below it, so the question is centred in the window exactly as on the other tabs. */
.tab-body { position: relative; }
.tab-body:has(.stage) > .tab-top { position: absolute; top: 0; inset-inline: 0; margin-inline: auto; width: max-content; z-index: 1; }
.tab-body:has(> .tab-top) > .tab-main > .stage { padding-block: calc(var(--seg-h) + 24px); }
@media only screen and (max-width: 734px) {
  .tab-body:has(.stage) > .tab-top { position: static; margin-inline: 0; width: auto; }
  .tab-body:has(> .tab-top) > .tab-main > .stage { padding-block: 0; }
}
/* Below 1069px the panel is under the main column: under a stage it keeps the page's bottom space above it, so it
   starts out of sight instead of showing a sliver of its top edge. */
@media only screen and (max-width: 1068px) {
  .tab-page { grid-template-columns: minmax(0, 1fr); }
  .tab-body:has(.stage) + .tab-panel { margin-top: var(--frame-pad); }
}

/* ---------- the pause timeline and the length bar (B.0): 12px pill tracks, drawn from the answer's timing ---------- */
/* .timeline: speech segments (.tl-speech) in pink, pauses of 2 s or more (.tl-stop) in red; each is placed with inline
   left and width in percent of the answer. */
.timeline { position: relative; width: 100%; height: 12px; border-radius: var(--r-pill); background: var(--bg); overflow: hidden; }
.tl-speech, .tl-stop { position: absolute; top: 0; bottom: 0; }
.tl-speech { background: var(--pink-200); }
.tl-stop { background: var(--red); min-width: 4px; border-radius: var(--r-pill); }
/* .lenbar: the good-length zone (.len-zone) in green, and the answer (.len-fill) in pink up to its length. */
.lenbar { position: relative; width: 100%; height: 12px; border-radius: var(--r-pill); background: var(--bg); overflow: hidden; }
.len-zone, .len-fill { position: absolute; top: 0; bottom: 0; }
.len-zone { background: var(--good-50); }
.len-fill { left: 0; background: var(--pink-300); border-radius: var(--r-pill); transition: width var(--t-move) var(--ease); }
/* The stage sits on the page's own grey, where a --bg track would vanish, so there the track is one step darker. */
.stage .timeline, .stage .lenbar { background: var(--bg-hover); }

/* A short message at the bottom of the screen. */
.toast {
  position: fixed; left: 50%; bottom: calc(24px + var(--dock)); z-index: 50; max-width: calc(100% - 48px); padding: 12px 18px; border-radius: var(--r-field);
  background: var(--toast); color: #fff; transform: translate(-50%, 12px); opacity: 0; transition: opacity .2s, transform .2s; pointer-events: none;
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }

@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 2.4s; }
  .rec-wave i { animation: none; }
  .toast, .switch, .switch::after { transition: none; }
  /* The stage: short fades only, a fixed ring and a still spinner. */
  .rec.big, .rec.big .rec-dot, .rec.big .rec-square, .len-fill { transition: opacity 120ms linear; }
  .rec.big.on { box-shadow: 0 0 0 4px var(--pink-200) inset, 0 0 0 4px var(--pink-100); }
  .rec.big .spinner { animation: none; }
  .sheet[open] { animation: sheet-fade 120ms linear; }
}
@keyframes sheet-fade { from { opacity: 0; } }
