* { box-sizing: border-box; }

:root {
  --bg: #f7f4ef;
  --panel: #eeeae2;
  --card: #ffffff;
  --border: #cdc5b7;
  --text: #1d1a15;
  --muted: #6a6356;
  --accent: #1a5c9e;
  --accent-soft: #e6eef8;
  --masc: #1d4fd0;
  --fem: #b8302f;
  --neut: #8f5700;
  --verb: #07734f;
  --other: #5f5953;
  --warn: #b3321f;
  --on-accent: #ffffff;
  --tint-s: 58%;
  --tint-l: 30%;
  --hue-text-l: 32%;      /* a hue as text: dark on the light theme */
  --studied: rgba(250, 204, 21, 0.28);
  --shadow: 0 1px 3px rgba(40, 30, 10, 0.06), 0 8px 24px rgba(40, 30, 10, 0.05);
  --shadow-pop: 0 4px 12px rgba(20, 15, 5, 0.1), 0 16px 40px rgba(20, 15, 5, 0.14);
  --serif: "Iowan Old Style", "Palatino", Georgia, serif;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #151311;
    --panel: #1c1a17;
    --card: #26231f;
    --border: #4a443b;
    --text: #f2eee6;
    --muted: #a39b89;
    --accent: #7db4e8;
    --accent-soft: #23303f;
    --masc: #8ab0f7;
    --fem: #f28e8e;
    --neut: #e6b060;
    --verb: #5cc9a2;
    --other: #b3ada3;
    --warn: #f28f75;
    --on-accent: #10151b;
    --tint-s: 55%;
    --tint-l: 68%;
    --hue-text-l: 74%;
    --studied: rgba(250, 204, 21, 0.16);
    --shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    --shadow-pop: 0 8px 30px rgba(0, 0, 0, 0.55);
  }
}
:root[data-theme="dark"] {
  --bg: #151311;
  --panel: #1c1a17;
  --card: #26231f;
  --border: #4a443b;
  --text: #f2eee6;
  --muted: #a39b89;
  --accent: #7db4e8;
  --accent-soft: #23303f;
  --masc: #8ab0f7;
  --fem: #f28e8e;
  --neut: #e6b060;
  --verb: #5cc9a2;
  --other: #b3ada3;
  --warn: #f28f75;
  --on-accent: #10151b;
  --tint-s: 55%;
  --tint-l: 68%;
  --hue-text-l: 74%;
  --studied: rgba(250, 204, 21, 0.16);
  --shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  --shadow-pop: 0 8px 30px rgba(0, 0, 0, 0.55);
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--text);
}
[hidden] { display: none !important; }
.hidden { display: none !important; }
button { font-family: inherit; }

.layout { display: flex; min-height: 100vh; }

/* ---------- rail (language + navigation + settings) ---------- */
.rail {
  width: 236px; flex-shrink: 0;
  position: sticky; top: 0; height: 100vh;
  display: flex; flex-direction: column; gap: 18px;
  background: var(--panel); border-right: 1px solid var(--border);
  padding: 16px 12px 14px;
}
.brand { display: block; text-decoration: none; color: inherit; margin-bottom: 2px; }
.brand-name {
  display: block; font-size: 19px; font-weight: 700; letter-spacing: -0.01em; color: var(--text);
}
.brand-tag { display: block; font-size: 11px; color: var(--muted); line-height: 1.3; }
.brand:hover .brand-name { color: var(--accent); }

.rail-top { position: relative; display: flex; align-items: center; gap: 8px; }
.lang-btn {
  flex: 1; display: flex; align-items: center; gap: 10px; text-align: left;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
  border-radius: 12px; padding: 8px 10px; cursor: pointer; box-shadow: var(--shadow);
  transition: border-color 0.15s;
}
.lang-btn:hover { border-color: var(--accent); }
.lang-flag {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; flex-shrink: 0;
  border: 1.5px solid currentColor; border-radius: 50%; font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
}
.lang-option .lang-flag { width: 26px; height: 26px; font-size: 10px; }
.lang-text { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.lang-text > span:first-child { font-size: 15px; font-weight: 600; }
.lang-native { font-size: 11px; color: var(--muted); }
.caret { margin-left: auto; color: var(--muted); }
.lang-menu {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 30;
  background: var(--card); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--shadow-pop); padding: 6px;
}
.lang-option {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  border: none; background: none; color: var(--text); border-radius: 8px;
  padding: 7px 8px; cursor: pointer; font-size: 14px;
}
.lang-option:hover { background: var(--accent-soft); }
.lang-option.active { color: var(--accent); font-weight: 600; }
.lang-menu-hint { margin: 6px 8px 4px; font-size: 11px; color: var(--muted); line-height: 1.4; }
.rail-toggle {
  display: none; border: 1px solid var(--border); background: var(--card); color: var(--text);
  border-radius: 9px; padding: 5px 9px; cursor: pointer; align-items: center;
}

.rail-nav { flex: 1; display: flex; flex-direction: column; gap: 16px; overflow-y: auto; }
.rail-group h3 {
  margin: 0 0 4px 10px; font-size: 10.5px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--muted);
}
.rail-item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  border: none; background: none; color: var(--text);
  font-size: 14px; font-weight: 500; padding: 8px 10px; border-radius: 10px; cursor: pointer;
  transition: background 0.12s;
}
.rail-item:hover { background: var(--card); }
.rail-item.active { background: var(--card); color: var(--accent); box-shadow: var(--shadow); }
.rail-item .icon { flex-shrink: 0; }
/* [ Language | Atlas ]: which half of the app the rail shows (shell.js renderSwitch) */
.rail-switch {
  display: flex; gap: 2px; padding: 3px; border-radius: 12px;
  background: var(--border);
}
.rail-switch-btn {
  flex: 1; border: none; background: none; color: var(--muted); cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 600; padding: 7px 8px; border-radius: 9px;
  transition: background 0.12s, color 0.12s;
}
.rail-switch-btn:hover { color: var(--text); }
.rail-switch-btn.active { background: var(--card); color: var(--accent); box-shadow: var(--shadow); }

/* the sibling views of the rail entry on screen (shell.js renderSectionTabs) */
.section-tabs {
  display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 18px;
  border-bottom: 1px solid var(--border);
}
.section-tabs[hidden] { display: none; }
.section-tab {
  display: inline-flex; align-items: center; gap: 7px; border: none; background: none;
  color: var(--muted); font-size: 14px; font-weight: 500; padding: 9px 12px 10px; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.section-tab:hover { color: var(--text); }
.section-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.icon { vertical-align: -3px; }
button .icon, a .icon { pointer-events: none; }

.rail-bottom { display: flex; flex-direction: column; gap: 12px; }
.rail-hours { font-size: 12px; color: var(--muted); }
.rail-settings { display: flex; flex-direction: column; gap: 7px; }
.rail-settings select {
  font: inherit; font-size: 12px; color: var(--text); background: var(--card);
  border: 1px solid var(--border); border-radius: 7px; padding: 2px 6px; margin-left: 4px;
}
.rail-credit { margin: 0; font-size: 10.5px; color: var(--muted); line-height: 1.4; }
.rail-credit a { color: var(--muted); }
.toggle { font-size: 12px; color: var(--muted); user-select: none; cursor: pointer; }
.learner-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* ---------- admin ---------- */
/* what the word means, which the card used to leave to inference */
.dr-gloss { margin: 2px 0 10px; font-size: 15px; color: var(--text); }
.dr-gloss .dr-pos { margin-right: 8px; }

/* watchable Tune In cards: everything on screen at once, no tap required */
.dr-idiom, .dr-paradigm { padding: 4px 2px; }
.dr-phrase { background: none; border: 0; padding: 0; text-align: left; cursor: pointer; color: inherit; }
.dr-phrase strong { font-size: 22px; line-height: 1.25; }
.dr-means { margin: 8px 0 4px; font-size: 15px; }
.dr-literal { margin: 0; color: var(--muted); font-size: 13.5px; font-style: italic; }
.dr-forms { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 4px 12px; margin-top: 12px; }
.dr-form { display: flex; justify-content: space-between; gap: 8px; border-bottom: 1px solid var(--border); padding: 3px 0; }
.dr-form-word { font-weight: 600; }
.dr-form-label { color: var(--muted); font-size: 12px; text-align: right; }
/* ---------- signing in / creating an account (a sheet) ----------
   One card, two tabs (Sign in · Create account), two steps (the address, then
   the code). Everything is built from the app's own tokens so it follows the
   theme; the inputs are 16px on purpose — below that iOS zooms the page when
   a field is focused. */
.sheet[data-size="narrow"] .sheet-card { width: min(440px, 100%); padding: 20px 24px 24px; }
.signin-sheet { max-width: 420px; }
.auth { display: flex; flex-direction: column; gap: 14px; }
.auth-tabs { display: flex; padding: 3px; border-radius: 11px; background: var(--panel); border: 1px solid var(--border); }
.auth-tab {
  flex: 1; border: 0; background: none; color: var(--muted); font: inherit; font-size: 14px; font-weight: 500;
  padding: 8px 10px; border-radius: 8px; cursor: pointer; transition: background 0.15s, color 0.15s;
}
.auth-tab:hover { color: var(--text); }
.auth-tab[aria-selected="true"] { background: var(--card); color: var(--text); box-shadow: var(--shadow); }
.auth-lead, .auth-why, .auth-sent, .auth-note { margin: 0; font-size: 14px; line-height: 1.45; color: var(--muted); }
.auth-why { color: var(--text); padding: 10px 12px; border-radius: 10px; background: var(--accent-soft); }
.auth-sent { color: var(--text); }
.auth-sent b { font-weight: 600; }
.auth-dev { display: block; margin-top: 4px; color: var(--accent); font-variant-numeric: tabular-nums; }
.auth-form { display: flex; flex-direction: column; gap: 12px; }
.auth-field { display: flex; flex-direction: column; gap: 6px; }
.auth-field > span { font-size: 12px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.auth-input {
  font: inherit; font-size: 16px; padding: 11px 13px; width: 100%; outline: none;
  border: 1px solid var(--border); border-radius: 10px; background: var(--bg); color: var(--text);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.auth-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.auth-input::placeholder { color: var(--muted); opacity: 1; }
.auth-code { font-size: 26px; letter-spacing: 0.4em; text-align: center; font-variant-numeric: tabular-nums; padding: 10px 0 10px 0.4em; }
.auth-primary { width: 100%; justify-content: center; min-height: 46px; font-size: 15px; font-weight: 600; border-radius: 10px; }
.auth-primary:disabled { opacity: 0.7; cursor: wait; }
.auth-links { margin: 0; font-size: 13px; color: var(--muted); }
.auth-links .linkish { text-decoration: none; }
.auth-links .linkish:hover { text-decoration: underline; }
.auth-error { margin: 0; font-size: 13.5px; color: var(--warn); background: color-mix(in srgb, var(--warn) 10%, transparent); border-radius: 8px; padding: 8px 10px; }
.auth-foot { margin: 8px 0 0; font-size: 13px; text-align: center; color: var(--muted); }
.auth-foot .linkish { color: var(--muted); text-decoration: none; }
.auth-foot .linkish:hover { color: var(--accent); }
/* the account, once signed in */
.auth-who { display: flex; align-items: center; gap: 10px; margin: 0; font-size: 15px; min-width: 0; }
.auth-avatar { flex: none; display: inline-flex; width: 36px; height: 36px; border-radius: 50%; align-items: center; justify-content: center; background: var(--accent-soft); color: var(--accent); }
.auth-email { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.auth-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.auth-section { border-top: 1px solid var(--border); padding-top: 12px; }
.auth-section h3 { margin: 0 0 8px; font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.auth-section .signin-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.auth-section .signin-form input { flex: 1; min-width: 180px; font: inherit; font-size: 15px; padding: 9px 11px; border: 1px solid var(--border); border-radius: 9px; background: var(--bg); color: var(--text); }
.auth-section .signin-form .muted, .auth-section .close-account .muted { flex-basis: 100%; font-size: 13px; margin: 4px 0 0; }

/* asking for a sign-in where the reader tried to keep something */
.signin-ask {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 22px; z-index: 40;
  display: flex; align-items: center; gap: 10px; max-width: min(640px, calc(100vw - 32px));
  padding: 10px 14px; border: 1px solid var(--border); border-radius: 999px;
  background: var(--card); box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18); font-size: 14px;
}
.signin-ask .ghost-btn, .signin-ask .primary-btn { padding: 5px 12px; min-height: 34px; white-space: nowrap; }

/* the age gate, shown in the reader where the piece would have been */
.gate { max-width: 520px; margin: 24px auto; padding: 20px 22px; border: 1px solid var(--border);
        border-radius: 10px; background: var(--card); }
.gate h3 { margin: 0 0 8px; font-size: 17px; }
.gate-note { margin: 0 0 8px; font-weight: 600; }
.gate-why { margin: 0 0 16px; color: var(--muted); font-size: 13.5px; }
.gate-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.adm-card { padding: 18px 22px 20px; }

/* Tabs, and tabs inside them: the panel holds ten reports and seventeen
   actions, which as one document is navigated by scrolling and remembering. */
.adm-tabs {
  display: flex; flex-wrap: wrap; gap: 2px;
  border-bottom: 1px solid var(--border);
  margin: 4px 0 16px;
}
.adm-tab {
  appearance: none; background: none; border: 0;
  border-bottom: 2px solid transparent;
  padding: 8px 14px; margin-bottom: -1px;
  font: inherit; font-size: 14px; font-weight: 500;
  color: var(--muted); cursor: pointer; white-space: nowrap;
}
.adm-tab:hover { color: var(--text); }
.adm-tab[aria-selected="true"] { color: var(--text); border-bottom-color: var(--accent); }
.adm-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 3px; }

.adm-subtabs {
  display: flex; gap: 6px; margin: 0 0 14px;
}
.adm-subtab {
  appearance: none; background: var(--panel); border: 1px solid var(--border);
  border-radius: 999px; padding: 4px 13px;
  font: inherit; font-size: 12.5px; font-weight: 500;
  color: var(--muted); cursor: pointer;
}
.adm-subtab:hover { color: var(--text); }
.adm-subtab[aria-selected="true"] {
  color: var(--text); border-color: var(--accent);
  background: var(--accent-soft, var(--panel));
}
.adm-subtab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.adm-group { display: flex; flex-direction: column; }
.adm-pane { display: flex; flex-direction: column; gap: 16px; }
/* the token gate: the only thing on the page when the server refuses */
.adm-gate { padding: 18px 22px 20px; max-width: 520px; }
.adm-gate h2 { margin: 0 0 4px; font-size: 17px; }
.adm-gate .muted { margin: 0 0 12px; font-size: 12.5px; }
.adm-gate-row { display: flex; gap: 8px; }
.adm-gate-row input { flex: 1; min-width: 0; }
.adm-token-note { margin: 16px 2px 0; font-size: 12.5px; color: var(--muted); }
.linkish { background: none; border: 0; padding: 0; font: inherit; color: var(--accent);
           cursor: pointer; text-decoration: underline; }
.adm-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.adm-head h2 { margin: 0 0 2px; font-size: 17px; }
.adm-head .muted { margin: 0; font-size: 12.5px; }
.adm-head .ghost-btn { padding: 6px 9px; }
.adm-total { margin: 0 0 12px; font-size: 14px; color: var(--muted); }
.adm-section { margin-bottom: 14px; }
.adm-row {
  display: grid; grid-template-columns: minmax(160px, 1.2fr) 2fr 130px; align-items: center; gap: 10px;
  padding: 3px 0 3px calc(var(--depth, 0) * 18px); font-size: 13px;
}
.adm-section > .adm-row, .adm-section > .adm-details > summary > .adm-row { font-weight: 600; }
.adm-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adm-bar { display: block; height: 8px; border-radius: 4px; background: var(--panel); overflow: hidden; }
.adm-fill { display: block; height: 100%; background: var(--accent); border-radius: 4px; }
.adm-num { text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); white-space: nowrap; }
.adm-details > summary { list-style: none; cursor: pointer; }
.adm-details > summary::-webkit-details-marker { display: none; }
.adm-details > summary .adm-label::before { content: "▸ "; color: var(--muted); }
.adm-details[open] > summary .adm-label::before { content: "▾ "; }
.adm-sub { margin: 14px 0 6px; font-size: 14px; }
.adm-kv { border-collapse: collapse; font-size: 13px; width: 100%; }
.adm-kv th { text-align: left; font-weight: 500; color: var(--muted); padding: 3px 12px 3px 0; vertical-align: top; white-space: nowrap; }
.adm-kv td { padding: 3px 0; }
.adm-actions { display: flex; flex-direction: column; gap: 10px; }
.adm-simple { display: flex; gap: 8px; flex-wrap: wrap; }
.adm-result { margin: 12px 0 0; font-size: 12px; white-space: pre-wrap; background: var(--panel); padding: 10px 12px; border-radius: 9px; max-height: 260px; overflow: auto; }
.adm-sub.small { font-size: 13px; margin-top: 12px; }
.adm-note { margin: 4px 0 10px; font-size: 12.5px; }
.adm-sum { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.adm-sum h3 { margin-right: 6px; }
.adm-filter { margin-left: auto; font-size: 12.5px; color: var(--muted); display: flex; align-items: center; gap: 4px; }
.adm-chip { display: inline-block; padding: 1px 7px; border-radius: 10px; font-size: 11.5px; font-weight: 600; background: var(--panel); color: var(--muted); white-space: nowrap; }
.adm-chip.ok { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.adm-chip.warn, .adm-chip.stale { background: color-mix(in srgb, var(--neut) 15%, transparent); color: var(--neut); }
.adm-chip.unbaked { background: color-mix(in srgb, var(--muted) 12%, transparent); color: var(--text); }
.adm-chip.amber { background: color-mix(in srgb, var(--neut) 15%, transparent); color: var(--neut); }
.adm-chip.error { background: color-mix(in srgb, var(--warn) 13%, transparent); color: var(--warn); }
.adm-scroll { overflow-x: auto; margin: 6px 0 10px; }
.adm-table { border-collapse: collapse; font-size: 12.5px; width: 100%; }
.adm-table th { text-align: left; font-weight: 500; color: var(--muted); padding: 4px 10px 4px 0; white-space: nowrap; border-bottom: 1px solid var(--border); }
.adm-table td { padding: 5px 10px 5px 0; vertical-align: top; border-bottom: 1px solid color-mix(in srgb, var(--border) 50%, transparent); }
.adm-table td:last-child, .adm-table th:last-child { padding-right: 0; }
.adm-problems { display: block; font-size: 11.5px; max-width: 260px; }
.adm-rowacts { display: flex; gap: 6px; flex-wrap: wrap; }
.ghost-btn.tiny { padding: 3px 8px; font-size: 12px; }
.adm-input { font: inherit; font-size: 12.5px; padding: 4px 7px; border: 1px solid var(--border); border-radius: 7px; background: var(--bg); color: inherit; min-width: 120px; }
.adm-budget { height: 6px; border-radius: 3px; background: var(--panel); overflow: hidden; margin: -6px 0 12px; }
.adm-budget .adm-fill { display: block; height: 100%; background: var(--accent); }
.adm-budget.warn .adm-fill { background: #c9401f; }
.adm-words { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 10px; }
.adm-word { font-size: 12.5px; padding: 2px 8px; background: var(--panel); border-radius: 9px; }
.adm-form { border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; }
.adm-form-head { font-size: 13px; margin-bottom: 8px; }
.adm-fields { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: flex-end; }
.adm-field { display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--muted); }
.adm-jobs { display: flex; flex-direction: column; gap: 6px; }
.adm-job { border: 1px solid var(--border); border-radius: 9px; padding: 6px 10px; font-size: 13px; }
.adm-job > summary { cursor: pointer; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.adm-job .ghost-btn.tiny { margin-left: auto; }
.adm-pre { margin: 8px 0 2px; font-size: 11.5px; white-space: pre-wrap; max-height: 220px; overflow: auto; background: var(--panel); padding: 8px 10px; border-radius: 7px; }
.adm-details.plain > summary { font-size: 12.5px; color: var(--muted); }
.learner-row select { margin-left: 0; }

/* ---------- the account corner of the rail ---------- */
.rail-account { display: flex; flex-direction: column; gap: 8px; }
.rail-auth-buttons { display: flex; gap: 8px; }
.rail-auth-buttons .ghost-btn, .rail-auth-buttons .primary-btn {
  flex: 1; min-height: 40px; padding: 0 10px; font-size: 13.5px; justify-content: center; white-space: nowrap; border-radius: 10px;
}
.rail-account-btn .rail-account-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- check yourself (comprehension questions) ---------- */
.check { margin: 22px 0 8px; padding: 14px 18px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--card); }
.check-title { margin: 0 0 8px; font-size: 15px; }
.check-q { padding: 8px 0; border-top: 1px solid var(--border); }
.check-question { margin: 0 0 6px; font-size: 15px; }
.check-answer { margin: 6px 0 0; font-size: 14px; color: var(--accent); }

/* ---------- today (random mode) ---------- */
.lib-today { margin: 0 0 18px; padding: 14px 16px 16px; border: 1px solid var(--border); border-radius: 14px; background: var(--card); box-shadow: var(--shadow); }
.today-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; font-size: 14px; }
.today-head strong { font-size: 15px; }
.today-head .ctl { margin-left: auto; font-size: 12.5px; color: var(--muted); }
.today-head .ctl select { font: inherit; font-size: 12.5px; margin-left: 4px; color: var(--text); background: var(--card); border: 1px solid var(--border); border-radius: 7px; padding: 2px 6px; }
.today-head .ghost-btn { padding: 5px 10px; font-size: 12.5px; }
.today-grid { margin: 0; }
.today-why { margin: 8px 0 0; font-size: 12px; color: var(--accent); }
.dialect { border-bottom: 1px dotted var(--accent); cursor: help; }
.toggle input { accent-color: var(--accent); }

/* ---------- main ---------- */
.main { flex: 1; min-width: 0; padding: 26px 32px 48px; max-width: 980px; }
.view { animation: rise 0.2s ease-out; }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.view-intro { color: var(--muted); font-size: 13px; max-width: 640px; line-height: 1.5; margin: 0 0 14px; }
.empty-note { font-size: 13px; color: var(--muted); }

.errors {
  margin-bottom: 14px; padding: 10px 14px; border-radius: 10px;
  background: rgba(220, 60, 60, 0.08); border: 1px solid rgba(220, 60, 60, 0.3);
  color: var(--fem); font-size: 14px;
}
.errors div + div { margin-top: 4px; }
.voice-warning, .notice {
  margin-bottom: 14px; padding: 10px 14px; border-radius: 10px;
  background: rgba(220, 160, 20, 0.09); border: 1px solid rgba(220, 160, 20, 0.35);
  color: var(--neut); font-size: 13px; line-height: 1.5;
}
.notice code { background: var(--panel); border-radius: 5px; padding: 1px 5px; font-size: 12px; }
.notice.info { background: var(--accent-soft); border-color: transparent; color: var(--text); }

/* ---------- shared components ---------- */
.card {
  background: var(--card); border: 1px solid var(--border);
  border-radius: 16px; padding: 20px 24px 22px; box-shadow: var(--shadow);
}
.primary-btn {
  background: var(--accent); color: var(--on-accent); border: none; border-radius: 9px;
  padding: 9px 20px; font-size: 14px; font-weight: 500; cursor: pointer; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 8px;
  transition: filter 0.15s, transform 0.1s;
}
.primary-btn:hover { filter: brightness(1.08); }
.primary-btn .icon, .ghost-btn .icon, .back-btn .icon, .side-head a .icon { vertical-align: -2px; }
.ghost-btn { display: inline-flex; align-items: center; gap: 6px; }
.back-btn { display: inline-flex; align-items: center; gap: 4px; }
.primary-btn:active { transform: scale(0.97); }
.primary-btn:disabled { opacity: 0.6; cursor: wait; }
.btn-spinner {
  display: none; width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--on-accent) 35%, transparent); border-top-color: var(--on-accent);
  animation: spin 0.7s linear infinite;
}
.primary-btn.loading .btn-spinner { display: inline-block; }
@keyframes spin { to { transform: rotate(360deg); } }
/* ⚠️ The app's secondary button, and the reason it is 44px: that is the floor
   for a touch target, and this class is on buttons across every page — Today's
   "Something else", the reader's controls, the dictionary's actions. It was
   36px, which is fine with a mouse and a nuisance with a thumb.

   `.ghost-btn.tiny` below is the escape hatch for the genuinely dense places
   (a chip inside a card), so raising the default does not fight them. */
.ghost-btn {
  border: 1px solid var(--border); background: var(--card); color: var(--text);
  border-radius: 9px; padding: 0 18px; font-size: 14px; cursor: pointer;
  min-height: 44px; box-sizing: border-box; justify-content: center;
}
.ghost-btn:hover { border-color: var(--accent); color: var(--accent); }
.back-btn {
  border: none; background: none; color: var(--accent); font-size: 13px;
  cursor: pointer; padding: 0; margin-bottom: 12px; font-weight: 500;
}
.round-btn {
  border: 1px solid var(--border); background: var(--card); color: var(--text);
  border-radius: 50%; width: 40px; height: 40px; font-size: 15px; cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.round-btn:hover { border-color: var(--accent); color: var(--accent); }
.round-btn { display: inline-flex; align-items: center; justify-content: center; }
.round-btn.speaking { border-color: var(--verb); color: var(--verb); animation: pulse 1.2s ease-in-out infinite; }
@keyframes pulse { 50% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--verb) 18%, transparent); } }
.rate-label { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 6px; }
.rate-label input { width: 90px; accent-color: var(--accent); }
.kbd-hint { color: var(--muted); font-size: 12px; }
.kbd-hint kbd {
  font-family: inherit; font-size: 11px; background: var(--panel);
  border: 1px solid var(--border); border-bottom-width: 2px;
  border-radius: 5px; padding: 1px 5px; margin-right: 2px;
}
.input-row { display: flex; align-items: center; gap: 10px; margin-top: 10px; }

/* split layout: main column + side list (Translate history, Notes notebook) */
.split-layout { display: flex; gap: 24px; align-items: flex-start; }
.split-main { flex: 1; min-width: 0; }
.side-panel { width: 250px; flex-shrink: 0; }
.side-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 12px; }
.side-title { margin: 0; font-size: 12px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); }
.side-head a { font-size: 12px; color: var(--accent); text-decoration: none; font-weight: 500; }
.side-head a:hover { text-decoration: underline; }
.side-list { list-style: none; margin: 0; padding: 0; }
.side-list li {
  padding: 9px 12px; margin-bottom: 7px; border-radius: 10px;
  background: var(--card); border: 1px solid var(--border);
  cursor: pointer; position: relative;
  transition: border-color 0.15s, transform 0.1s;
}
.side-list li:hover { border-color: var(--accent); }
.side-list li:active { transform: scale(0.985); }
.side-list .h-main { font-size: 13px; display: block; padding-right: 18px; font-weight: 500; }
.side-list .h-sub {
  font-size: 11px; color: var(--muted); display: block; padding-right: 18px;
  margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.side-list .h-del {
  position: absolute; top: 7px; right: 8px; border: none; background: none;
  color: var(--muted); cursor: pointer; padding: 2px; display: inline-flex;
  opacity: 0; transition: opacity 0.15s;
}
.side-list li:hover .h-del { opacity: 1; }
.side-list .h-del:hover { color: var(--fem); }
.history-empty { font-size: 13px; color: var(--muted); }

/* ---------- translate ---------- */
.input-area textarea {
  width: 100%; font-size: 17px; padding: 14px 16px;
  border: 1px solid var(--border); border-radius: 12px;
  resize: vertical; font-family: inherit;
  background: var(--card); color: var(--text);
  box-shadow: var(--shadow);
  transition: border-color 0.15s;
}
.input-area textarea:focus { outline: none; border-color: var(--accent); }
.empty-hint { margin-top: 36px; color: var(--muted); font-size: 14px; }
.examples { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.example {
  border: 1px dashed var(--border); background: var(--card); color: var(--text);
  border-radius: 999px; padding: 6px 14px; font-size: 13px; cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.example:hover { border-color: var(--accent); color: var(--accent); border-style: solid; }

.result { margin-top: 26px; animation: rise 0.25s ease-out; }
.result-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.english-line { color: var(--muted); font-size: 15px; margin: 0; flex: 1; min-width: 200px; }
.audio-controls { display: flex; align-items: center; gap: 10px; }
.target-output { font-family: var(--serif); font-size: 30px; line-height: 1.55; margin-top: 14px; }
.target-output .sent { display: block; margin-bottom: 6px; }
.shimmer {
  display: inline-block; height: 30px; width: 70%; border-radius: 8px;
  background: linear-gradient(90deg, var(--panel) 25%, var(--border) 50%, var(--panel) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.2s linear infinite;
}
@keyframes shimmer { to { background-position: -200% 0; } }

.word {
  cursor: pointer; border-radius: 5px; padding: 0 2px;
  border-bottom: 2px solid transparent;
  transition: border-color 0.12s, background 0.2s;
}
.word:hover { border-bottom-color: currentColor; }
.word.studied { background: var(--studied); }
body.colored .word.masc { color: var(--masc); }
body.colored .word.fem { color: var(--fem); }
body.colored .word.neut { color: var(--neut); }
body.colored .word.verb { color: var(--verb); }
body.colored .word.other { color: var(--other); }

.sentence-note {
  margin-top: 14px; font-size: 14px; line-height: 1.5;
  background: var(--accent-soft); border-radius: 10px; padding: 11px 14px;
  animation: rise 0.25s ease-out;
}
.sentence-note { border-left: 3px solid var(--accent); }
.engine-note { font-size: 12px; color: var(--muted); margin-top: 10px; margin-bottom: 0; }
.legend { margin-top: 16px; display: none; gap: 14px; font-size: 12px; padding-left: 4px; }
body.colored .legend { display: flex; flex-wrap: wrap; }
.lg { color: var(--muted); }
.lg::before { content: "●"; margin-right: 4px; }
.lg.masc::before { color: var(--masc); }
.lg.fem::before { color: var(--fem); }
.lg.neut::before { color: var(--neut); }
.lg.verb::before { color: var(--verb); }
.lg.other::before { color: var(--other); }

/* ---------- library head + cards ---------- */
.lib-head { display: flex; flex-direction: column; align-items: stretch; gap: 12px; }
.lib-head-text { min-width: 0; }
.lib-head .view-intro { margin-bottom: 0; }
.lib-title { margin: 0 0 6px; font-size: 22px; }
/* one row, four controls. The selects carry their own names now, so there is
   no caption column to make room for. */
.lib-filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.lib-filter {
  font: inherit; font-size: 13.5px; color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: 9px; padding: 0 10px;
  height: 40px; flex: 0 1 auto; min-width: 132px;
}
.lib-filter[hidden] { display: none; }

/* ⚠️ These were 88px cards in a 140px grid — a second navigation menu, the
   size of a shelf of content, repeating the seven entries already open in
   the sidebar two inches to the left. They still have to exist (the sidebar
   is not there on a phone, and only these carry the counts), but as one row
   of controls rather than a wall of panels. */
.lib-cats {
  display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 20px;
}
.lib-cat {
  display: inline-flex; flex-direction: row; align-items: center; gap: 8px; text-align: left;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
  border-radius: 999px; padding: 0 15px; min-height: 44px; cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.lib-cat:hover { border-color: var(--accent); }
.lib-cat.active { border-color: var(--accent); color: var(--on-accent); background: var(--accent); }
.lib-cat.empty { color: var(--muted); }
.lib-cat .icon { width: 18px; height: 18px; flex: none; }
.lib-cat-label { font-size: 14.5px; font-weight: 600; }
.lib-cat-count {
  font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.lib-cat.active .lib-cat-count { color: inherit; opacity: 0.8; }
.chip {
  border: 1px solid var(--border); background: var(--card); color: var(--muted);
  border-radius: 999px; padding: 4px 11px; font-size: 12px; cursor: pointer;
}
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; margin-top: 16px; }
/* Every piece card in the app — Today's picks and every Library shelf, both
   from makeCard() in static/js/library.js. The level's colour on the left
   edge and the arrow bottom-right are the same language as the Course and
   Playlists cards, so the three pages read as one app. */
.pkg-card {
  position: relative;
  text-align: left; background: var(--card); border: 1px solid var(--border);
  border-left: 4px solid var(--lv, var(--border));
  border-radius: 14px; padding: 16px 16px 16px 18px; cursor: pointer; color: var(--text);
  display: flex; flex-direction: column; gap: 6px; box-shadow: var(--shadow);
  transition: border-color 0.15s, transform 0.1s; font-size: 14px;
  min-height: 132px;
}
.pkg-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.pkg-card:active { transform: scale(0.985); }
.pkg-card strong { font-size: 15.5px; line-height: 1.35; }
/* the arrow that says the card is a door; see the note over makeCard() */
.cc-go {
  position: absolute; right: 12px; bottom: 12px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 999px;
  border: 1px solid var(--border); color: var(--muted);
}
.pkg-card:hover .cc-go { border-color: var(--accent); color: var(--accent); }
/* ⚠️ Room for it on whatever ends up last. The arrow is positioned, so it
   sits OVER the final line of the card — and Today appends its own reason
   line ("brings back 3 words you slowed down on") after makeCard has already
   added the arrow, so padding the meta line alone was not enough. */
.pkg-card .cc-meta,
.pkg-card .td-reason,
.pkg-card .cc-bar { padding-right: 38px; }
/* Two lines, then stop. Descriptions run to three and four lines and are the
   part of a card people skim past on the way to the title — left to run they
   set the height of every card in the row, which is what made 113 of them
   eight screens of scrolling. */
.cc-desc {
  color: var(--muted); font-size: 13px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  line-clamp: 2; overflow: hidden;
}

/* ── the level groups ────────────────────────────────────────────────────
   A fold, not a filter: everything is still on the page and one click away.
   The heading is a button and says so — the arrow turns, and the count is
   there so a folded group still tells you how much is inside. */
.lib-group-head {
  display: flex; align-items: center; gap: 10px; width: 100%; margin-top: 22px;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--panel); color: var(--text); cursor: pointer; text-align: left;
  font-size: 15px; font-weight: 600;
}
.lib-group-head:hover { border-color: var(--accent); }
.lib-group-head .icon { transition: transform 0.15s; opacity: 0.6; }
.lib-group-head.open .icon { transform: rotate(180deg); }
.lib-group-head.plain { background: none; border: none; cursor: default; padding-left: 2px; }
.lgh-name { flex: 1; }
.lgh-code {
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.06em;
  border-radius: 999px; padding: 2px 8px; background: var(--card); color: var(--muted);
}
.lgh-count { color: var(--muted); font-size: 13px; font-weight: 400; min-width: 2ch; text-align: right; }
.lib-group-note { color: var(--muted); font-size: 13px; margin: 8px 2px 0; }
.lib-group { margin-top: 10px; }
/* ⚠️ #lib-cards is NOT a grid, whatever its name suggests. Everything
   appended to it is a block section — a level heading, the sentence under
   it, a grid of cards, a Show all button — and while it carried card-grid
   itself each of those became one cell of a three-column grid: the heading
   in column one, its note stranded in column two, and the whole shelf of
   cards stacked single-file in column three. The grids are the .lib-group
   rows inside it. */
.lib-cards { display: block; }
.lib-search {
  min-width: 200px; flex: 1 1 260px; height: 40px;
  font: inherit; font-size: 14px; color: var(--text); background: var(--card);
  border: 1px solid var(--border); border-radius: 9px; padding: 0 12px;
}
.lib-search::placeholder { color: var(--muted); }
.lib-search:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.cc-meta { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; }
.badges { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 4px; }
.badge {
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  border-radius: 999px; padding: 2px 8px; background: var(--panel); color: var(--muted);
}
.badge.level-a { background: color-mix(in srgb, var(--verb) 12%, transparent); color: var(--verb); }
.badge.level-b { background: color-mix(in srgb, var(--neut) 12%, transparent); color: var(--neut); }
.badge.level-c { background: color-mix(in srgb, var(--fem) 11%, transparent); color: var(--fem); }
.badge.culture { background: var(--accent-soft); color: var(--accent); }

/* ---------- player heads (Read + Listen) ---------- */
.player-title-row { display: flex; align-items: flex-start; gap: 16px; justify-content: space-between; }
.player-head h2 { margin: 0 0 4px; font-size: 19px; }
.player-desc { margin: 0; color: var(--muted); font-size: 13px; }
.convo-controls { display: flex; align-items: center; gap: 20px; margin-top: 14px; flex-wrap: wrap; }

/* ---------- reader ---------- */
.read-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.read-actions-main { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
/* an occasional action, kept legible but not competing with Play */
.read-offline { font-size: 12.5px; color: var(--muted); text-decoration: none; }
.read-offline:hover { color: var(--accent); text-decoration: underline; }
#read-play { min-width: 124px; justify-content: center; }
.read-progress { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.player-top { display: flex; align-items: center; min-height: 40px; margin-bottom: 10px; padding-right: 52px; }
.player-top .back-btn { margin-bottom: 0; }

/* floating settings: a sticky dock at the top of the player holds the button and its panel */
.float-dock { position: sticky; top: 10px; height: 0; z-index: 25; }
.fab {
  position: absolute; right: 0; top: 0; width: 40px; height: 40px; border-radius: 50%;
  border: 1px solid var(--border); background: var(--card); color: var(--text); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; box-shadow: var(--shadow-pop);
  transition: border-color 0.15s, color 0.15s;
}
.fab:hover, .fab.on { border-color: var(--accent); color: var(--accent); }
.settings-panel {
  position: absolute; right: 0; top: 48px; width: min(400px, calc(100vw - 32px));
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  padding: 12px 16px 12px; box-shadow: var(--shadow-pop); animation: rise 0.15s ease-out;
}
.settings-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; font-size: 13px; }
.settings-head .sheet-close { padding: 2px; }
.srow {
  display: grid; grid-template-columns: 92px 1fr 48px; align-items: center; gap: 8px;
  font-size: 12px; color: var(--muted); margin-bottom: 8px;
}
.srow.dim { opacity: 0.6; }
.srow select {
  grid-column: 2 / 4; font: inherit; font-size: 12.5px; color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: 7px; padding: 4px 6px; min-width: 0;
}
.srow input[type="range"] { width: 100%; accent-color: var(--accent); margin: 0; min-width: 0; }
.srow output { text-align: right; color: var(--text); font-variant-numeric: tabular-nums; font-weight: 500; }
.srow-toggles { display: flex; gap: 16px; margin: 6px 0 8px; }
.srow-toggles .toggle { font-size: 12.5px; display: inline-flex; align-items: center; gap: 5px; }
.settings-panel .kbd-help { margin: 0; line-height: 1.5; border-top: 1px solid var(--border); padding-top: 8px; }

.ctl { display: flex; flex-direction: column; gap: 5px; font-size: 12px; color: var(--muted); }
.ctl select {
  font: inherit; font-size: 13px; color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: 8px; padding: 5px 8px;
}
.ctl input[type="range"] { width: 100%; accent-color: var(--accent); margin: 0; }
.ctl small { font-size: 11px; opacity: 0.8; }
.ctl.toggle { flex-direction: row; align-items: center; gap: 6px; align-self: end; font-size: 13px; }
.kbd-help { margin: 12px 0 0; font-size: 11px; color: var(--muted); }

.read-lines { list-style: none; margin: 18px 0 0; padding: 0; max-width: 720px; }
.rl {
  padding: 12px 16px 13px; border-radius: 14px; border: 1px solid transparent;
  margin-bottom: 4px; cursor: pointer; opacity: 0.7;
  transition: opacity 0.3s, border-color 0.2s, box-shadow 0.2s, background 0.2s;
}
.rl:hover { opacity: 0.85; }
.rl.reached { opacity: 1; }
.rl.current { background: var(--card); border-color: var(--accent); box-shadow: var(--shadow), 0 0 0 3px var(--accent-soft); }
.rl-head { display: flex; align-items: center; gap: 8px; margin-bottom: 3px; }
.rl-num { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.rl-speaker { font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--accent); }
.rl-text { font-family: var(--serif); font-size: 24px; line-height: 1.5; transition: filter 0.2s; }
.read-lines.text-spoken .rl:not(.reached) .rl-text,
.read-lines.text-hidden .rl-text { filter: blur(7px); user-select: none; }
.read-lines .rl .rl-text.peek { filter: none; }
.rl-sub { position: relative; min-height: 20px; margin-top: 5px; font-size: 14px; line-height: 1.4; color: var(--muted); }
.rl-sub span { display: block; opacity: 0; transform: translateY(2px); transition: opacity 0.4s ease, transform 0.4s ease; }
.rl-sub.shown span, .read-lines.subs-always .rl-sub span { opacity: 1; transform: none; }
.rl-sub:not(.shown)::after { content: "· · ·"; position: absolute; left: 0; top: 0; opacity: 0.85; letter-spacing: 1px; }
.read-lines.subs-always .rl-sub::after { content: none; }
/* Culture pages, read the other way round: the reader's own language is the
   text and the target language sits underneath it, in the reading face but
   quieter. Three modes, set per reader in the player's settings: both, the
   reader's language alone, or the target language alone — and in that last
   one the target text is the page, so it takes the full size back. */
.rl-learner { font-size: 17px; line-height: 1.6; }
.read-lines.culture .rl-text { font-size: 19px; margin-top: 7px; color: var(--muted); }
.read-lines.culture.cult-learner .rl-text { display: none; }
.read-lines.culture.cult-target .rl-learner { display: none; }
.read-lines.culture.cult-target .rl-text { font-size: 24px; margin-top: 0; color: inherit; }
/* a culture page is prose, not a drill: no blurring it to be revealed */
.read-lines.culture.text-spoken .rl:not(.reached) .rl-text,
.read-lines.culture.text-hidden .rl-text { filter: none; user-select: auto; }
.rl-time { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.rl-head .t-btn { opacity: 0; transition: opacity 0.15s; }
.rl:hover .t-btn, .rl.current .t-btn, .rl-head .t-btn.recording, .rl-head .t-mine { opacity: 1; }
.rl-note {
  display: none; margin-top: 7px; padding: 7px 11px 7px 10px; border-radius: 9px;
  background: var(--accent-soft); font-size: 12.5px; line-height: 1.45; white-space: pre-line;
  animation: rise 0.25s ease-out; align-items: flex-start; gap: 7px; border-left: 3px solid var(--accent);
}
.rl-note .icon { flex-shrink: 0; margin-top: 2px; color: var(--accent); }
.rl.reached .rl-note { display: flex; }
.read-lines.notes-off .rl-note { display: none; }

/* ── a culture page, read like a page (library.js renderLines) ──
   It is read more often than it is played, so nothing waits to be
   "reached": every line at full strength and every note showing. */
.read-lines.culture .rl { opacity: 1; }
.read-lines.culture:not(.notes-off) .rl-note { display: flex; }
.rl-toc { list-style: none; margin: 0 0 14px; }
.rl-toc nav { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.rl-toc-label {
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); margin-right: 4px;
}
.rl-toc-chip {
  font: inherit; font-size: 13px; cursor: pointer; padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
}
.rl-toc-chip:hover { border-color: var(--accent); color: var(--accent); }
.rl.rl-heading {
  margin: 22px 0 6px; padding: 8px 16px 6px; border-radius: 0;
  border: 0; border-bottom: 2px solid var(--border); scroll-margin-top: 16px;
}
.rl.rl-heading.current { box-shadow: none; background: none; border-bottom-color: var(--accent); }
.rl-heading-learner { margin: 0; font-size: 20px; letter-spacing: -.01em; }
.rl-heading-target { margin: 2px 0 0; font-family: var(--serif); font-size: 15px; color: var(--muted); }
/* a phrase worth keeping: the line itself, marked */
.rl.rl-phrase { border-color: color-mix(in srgb, var(--verb) 45%, var(--border)); background: color-mix(in srgb, var(--verb) 6%, var(--card)); }
.rl-phrase-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin-top: 8px; }
.rl-phrase-tag {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--verb);
}
.rl-phrase-when { font-size: 13px; color: var(--text); }
.rl-phrase-slow {
  font: inherit; font-size: 12.5px; cursor: pointer; margin-left: auto;
  padding: 4px 10px; border-radius: 8px; border: 1px solid var(--border); background: var(--card); color: var(--text);
}
.rl-phrase-slow:hover { border-color: var(--verb); color: var(--verb); }
.rl-check { list-style: none; margin: 8px 0 14px; }
.rl-extra { list-style: none; margin: 26px 0 0; padding: 16px; border: 1px solid var(--border); border-radius: 14px; background: var(--card); }
.rl-extra-h { margin: 0 0 10px; font-size: 15px; }
.rl-book-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.rl-book-list li { display: grid; grid-template-columns: auto 1fr; column-gap: 10px; align-items: baseline; }
.rl-book-list .t-btn { grid-row: span 2; align-self: center; }
.rl-book-cs { font-family: var(--serif); font-size: 17px; }
.rl-book-en { font-size: 13px; color: var(--muted); }
.rl-word-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.rl-word {
  display: inline-flex; align-items: baseline; gap: 6px; cursor: pointer; font: inherit;
  padding: 5px 10px; border-radius: 9px; border: 1px solid var(--border); background: var(--bg); color: var(--text);
}
.rl-word:hover { border-color: var(--accent); }
.rl-word-cs { font-family: var(--serif); font-size: 15px; font-weight: 600; }
.rl-word-en { font-size: 12px; color: var(--muted); }

/* one question, where it belongs (static/js/quickcheck.js) */
.qc {
  display: grid; gap: 8px; padding: 12px 14px; border-radius: 12px;
  border: 1px dashed color-mix(in srgb, var(--accent) 45%, var(--border)); background: var(--card);
}
.qc-label { margin: 0; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
.qc-q { margin: 0; font-size: 15px; font-weight: 600; line-height: 1.4; }
.qc-choices { display: flex; flex-wrap: wrap; gap: 6px; }
.qc-choice, .qc-show {
  font: inherit; font-size: 14px; cursor: pointer; text-align: left;
  padding: 7px 12px; border-radius: 9px; border: 1px solid var(--border); background: var(--bg); color: var(--text);
}
.qc-choice:hover:not(:disabled), .qc-show:hover { border-color: var(--accent); color: var(--accent); }
.qc-choice:disabled { cursor: default; }
.qc-choice.is-right { border-color: var(--verb); background: color-mix(in srgb, var(--verb) 12%, var(--card)); color: var(--text); font-weight: 600; }
.qc-choice.is-wrong { border-color: var(--warn); background: color-mix(in srgb, var(--warn) 10%, var(--card)); text-decoration: line-through; }
.qc.is-answered .qc-choice:not(.is-right):not(.is-wrong) { opacity: .6; }
.qc-show { justify-self: start; }
.qc-answer { margin: 0; font-size: 14.5px; font-weight: 600; color: var(--accent); }
.qc-why { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--text); }
.qc-why.is-right::before { content: "✓ "; color: var(--verb); font-weight: 700; }

/* ---------- book reading view: paragraphs, tap a sentence for its translation ---------- */
.book { max-width: 680px; margin: 22px 0 0; font-family: var(--serif); font-size: 21px; line-height: 1.75; }
.bk-hint { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-size: 12px; color: var(--muted); margin: 0 0 14px; }
.bk-para { margin: 0 0 1.1em; }
.bk-h { font-size: 24px; font-weight: 600; margin: 1.4em 0 0.5em; line-height: 1.3; display: block; }
.bk-hint + .bk-h { margin-top: 0.2em; }
.bk-sent {
  border-radius: 6px; padding: 1px 3px; cursor: pointer; transition: background 0.15s;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.bk-sent:hover { background: var(--accent-soft); }
.bk-sent.open, .bk-sent.current { background: var(--accent-soft); }
.bk-sent.current { box-shadow: 0 0 0 1px var(--accent); }
.sent-pop {
  position: absolute; z-index: 40; background: var(--card); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: var(--shadow-pop); padding: 10px 12px; font-size: 14px; line-height: 1.45;
  display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: flex-start; animation: rise 0.15s ease-out;
}
.sent-pop[hidden] { display: none; }
.sent-pop .sp-text { flex: 1; min-width: 0; }
.sent-pop .sp-play { border: none; background: none; color: var(--muted); cursor: pointer; padding: 2px; display: inline-flex; }
.sent-pop .sp-play:hover { color: var(--accent); }
.sent-pop .sp-note {
  flex-basis: 100%; display: flex; gap: 7px; font-size: 12.5px; color: var(--muted);
  border-top: 1px solid var(--border); padding-top: 7px; white-space: pre-line;
}
.sent-pop .sp-note .icon { flex-shrink: 0; margin-top: 2px; color: var(--accent); }
.book { user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.bk-sent { touch-action: pan-y; }
.bk-sent.resume { box-shadow: 0 0 0 2px var(--accent); }
.bk-speaker { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--accent); margin-right: 8px; }
.sent-pop .eword { cursor: pointer; border-bottom: 1px dotted transparent; border-radius: 3px; }
.sent-pop .eword:hover { border-bottom-color: var(--accent); color: var(--accent); }
.chap-nav { display: flex; align-items: center; gap: 8px; margin: 14px 0 0; flex-wrap: wrap; }
.chap-nav .ghost-btn { padding: 6px 9px; }
.chap-nav .ghost-btn:disabled { opacity: 0.4; cursor: default; }
.chap-nav select {
  font: inherit; font-size: 13px; color: var(--text); background: var(--card); max-width: min(420px, 60vw);
  border: 1px solid var(--border); border-radius: 8px; padding: 6px 8px;
}
.badge.free { background: color-mix(in srgb, var(--verb) 12%, transparent); color: var(--verb); }
.badge.paid { background: color-mix(in srgb, var(--neut) 12%, transparent); color: var(--neut); }
/* still waiting for its neural reading (server/library.py audio_ai) */
.badge.incomplete { background: color-mix(in srgb, var(--fem) 10%, transparent); color: var(--fem); border: 1px dashed color-mix(in srgb, var(--fem) 45%, transparent); }
.badge.reviewed { background: color-mix(in srgb, var(--verb) 12%, transparent); color: var(--verb); }
.cc-author { font-size: 12px; color: var(--muted); margin-top: -2px; }
/* the other direction: English word → words of the language */
.p-dir { font-size: 12px; color: var(--muted); margin-left: 8px; }
.p-cands { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.p-cand { border-top: 1px solid var(--border); padding-top: 7px; }
.p-cand-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.p-cand-lemma { border: none; background: none; cursor: pointer; font-family: var(--serif); font-size: 18px; color: var(--text); padding: 0; }
.p-cand-lemma:hover { color: var(--accent); }
.p-cand .p-def-text { font-size: 13px; color: var(--muted); margin-top: 2px; }
.p-cand .p-forms { margin-left: auto; }
.p-cand .p-forms.open { background: var(--accent-soft); }
.p-inline-forms { margin-top: 8px; }
.p-inline-forms .paradigm h3 { font-size: 12px; margin: 6px 0 4px; color: var(--muted); }
.p-inline-forms .ptable { font-size: 12.5px; }
.p-matched { margin: 4px 0 0; font-size: 12px; color: var(--muted); font-style: italic; }
.pnote { margin: 8px 0 2px; padding: 8px 10px; border-radius: 9px; background: var(--accent-soft); font-size: 12.5px; line-height: 1.45; }
.pnote p { margin: 3px 0 0; }
.muted { color: var(--muted); }
#player.book-mode .srow.subs, #player.book-mode .srow.text, #player.book-mode .srow.delay { display: none; }
#player.book-mode .kbd-help.lines-only, #player:not(.book-mode) .kbd-help.book-only { display: none; }

/* ---------- listen (dialogue turns) + notes segments ---------- */
.convo-turns { list-style: none; margin: 18px 0 0; padding: 0; }
.turn {
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  padding: 12px 16px 13px; margin-bottom: 10px; max-width: 640px;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.turn.sp-b { margin-left: auto; }
.turn.playing { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.t-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.t-speaker { font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.turn.sp-a .t-speaker { color: var(--accent); }
.turn.sp-b .t-speaker { color: var(--verb); }
.t-time { font-variant-numeric: tabular-nums; text-transform: none !important; letter-spacing: 0 !important; }
.t-btn {
  border: 1px solid var(--border); background: var(--card); color: var(--muted);
  border-radius: 999px; font-size: 11px; padding: 3px 8px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 4px; line-height: 1;
  transition: color 0.15s, border-color 0.15s;
}
.t-btn:hover { color: var(--accent); border-color: var(--accent); }
.t-rec.recording { color: var(--on-accent); background: var(--fem); border-color: var(--fem); animation: pulse 1.2s infinite; }
.t-mine { color: var(--verb); border-color: var(--verb); }
.t-cz { font-family: var(--serif); font-size: 22px; line-height: 1.5; }
.t-en { color: var(--muted); font-size: 13px; margin-top: 4px; transition: filter 0.15s; }
.convo-turns.hide-en .t-en { filter: blur(6px); cursor: pointer; user-select: none; }
.convo-turns.hide-en .t-en.revealed { filter: none; }

/* ---------- immersion hours ---------- */
.hours-card { margin-bottom: 18px; padding: 16px 20px; }
.hours-row { display: flex; justify-content: space-between; align-items: baseline; }
.hours-row strong { font-size: 14px; }
.hours-label { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.hours-bar { height: 8px; border-radius: 999px; background: var(--panel); margin-top: 8px; overflow: hidden; }
.rail .hours-bar { background: var(--border); height: 6px; }
.hours-fill { height: 100%; width: 0; border-radius: 999px; background: var(--accent); transition: width 0.4s ease; }
.hours-fill.done { background: var(--verb); }
.hours-hint { margin: 10px 0 0; font-size: 12px; color: var(--muted); }
.hours-hint code { background: var(--panel); border-radius: 5px; padding: 1px 5px; font-size: 11px; }

/* ---------- notes ---------- */
.note-editor { padding: 18px 20px; }
.note-prompt { margin: 0 0 12px; font-size: 13px; color: var(--muted); line-height: 1.5; }
.note-editor textarea {
  width: 100%; font-size: 16px; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 10px;
  resize: vertical; font-family: inherit; background: var(--bg); color: var(--text);
}
.note-editor textarea:focus { outline: none; border-color: var(--accent); }
.note-segments { margin-top: 18px; }
.note-seg { max-width: 720px; }

/* ---------- popover ---------- */
/* above the sheet (60): a word in a list there opens its card on top of it
   (cognates.js). Opening a sheet hides the card, so it never covers one. */
.popover {
  position: absolute; z-index: 61; max-width: 370px; min-width: 250px; max-height: 72vh; overflow-y: auto;
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: var(--shadow-pop); padding: 15px 17px; font-size: 14px;
  animation: pop 0.16s ease-out; color: var(--text);
}
@keyframes pop { from { opacity: 0; transform: translateY(-4px) scale(0.98); } to { opacity: 1; transform: none; } }
.popover::before {
  content: ""; position: absolute; top: -6px; left: var(--arrow-x, 50%);
  width: 10px; height: 10px; transform: translateX(-50%) rotate(45deg);
  background: var(--card); border-left: 1px solid var(--border); border-top: 1px solid var(--border);
}
.popover.above::before {
  top: auto; bottom: -6px; border-left: none; border-top: none;
  border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);
}
/* first look (static/engine/firstlook.js): the tapped noun's object behind the card */
.popover { --fl-size: 130px; }
.popover .p-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.popover .p-form { font-size: 21px; font-weight: 600; font-family: var(--serif); }
.popover .p-speak { border: none; background: none; cursor: pointer; padding: 2px; color: var(--muted); display: inline-flex; }
.popover .p-speak:hover { color: var(--accent); }
.p-meaning { margin-bottom: 9px; padding-bottom: 9px; border-bottom: 1px dashed var(--border); }
.p-lemma-line { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; font-size: 13px; }
.p-lemma { font-family: var(--serif); font-size: 17px; font-weight: 600; }
/* The word as the way through to its own page (wordLink in tokens.js).

   Deliberately quiet at rest: the popover's whole job is to answer without
   taking the reader out of the sentence, and a headword painted like a link
   would read as the thing to do next. It becomes one under the cursor, and
   the underline on hover is what says it was one all along. */
a.p-open { color: inherit; text-decoration: none; cursor: pointer; }
a.p-open:hover, a.p-open:focus-visible {
  color: var(--accent); text-decoration: underline; text-underline-offset: 3px;
}
.p-arrow { color: var(--muted); }
.p-gloss { font-style: italic; font-size: 14px; }
.p-gloss.muted { color: var(--muted); font-style: normal; font-size: 12px; }
.p-defs { margin-top: 5px; display: flex; flex-direction: column; gap: 3px; }
.p-def { font-size: 12.5px; line-height: 1.45; }
.p-def > .term { margin-right: 5px; }
.p-tags .term { margin-right: 5px; color: var(--verb); }
.p-def-text { color: var(--muted); }
.p-via { color: var(--muted); font-style: italic; }
.popover .p-row { margin: 3px 0; }
.p-row .term:first-child, .p-lemma-line .term:first-child { color: var(--muted); }
.p-sep { color: var(--muted); }
.term {
  background: none; border: none; padding: 0; margin: 0; font: inherit; color: inherit;
  cursor: help; border-bottom: 1px dotted var(--muted); border-radius: 0; line-height: inherit;
}
.term:hover, .term.open { color: var(--accent) !important; border-bottom-color: var(--accent); }
.popover .p-why { margin-top: 10px; padding-top: 9px; border-top: 1px dashed var(--border); font-size: 13px; line-height: 1.45; }
.p-term {
  margin-top: 10px; padding: 9px 11px; border-radius: 10px; background: var(--accent-soft);
  font-size: 12.5px; line-height: 1.45; animation: rise 0.2s ease-out;
}
.p-term strong { display: block; margin-bottom: 3px; font-size: 13px; }
.p-term p { margin: 0; }
.p-term .p-example { margin-top: 5px; font-family: var(--serif); font-size: 13.5px; }

/* ---------- sheet (inflection tables) ---------- */
.sheet {
  position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, 0.35);
  display: flex; align-items: flex-start; justify-content: center; padding: 40px 16px; overflow-y: auto;
}
.sheet-card {
  background: var(--card); color: var(--text); border: 1px solid var(--border); border-radius: 16px;
  box-shadow: var(--shadow-pop); width: min(760px, 100%); padding: 18px 22px 22px; animation: sheet-in 0.2s ease-out;
}
@keyframes sheet-in { from { transform: translateY(10px); } to { transform: none; } }
.sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.sheet-head h2 { margin: 0; font-size: 18px; }
.sheet-close { border: none; background: none; color: var(--muted); cursor: pointer; padding: 4px 8px; display: inline-flex; }
.sheet-close:hover { color: var(--text); }
.paradigm h3 { margin: 12px 0 6px; font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); }
.ptable { border-collapse: collapse; font-size: 14px; margin: 6px 0 12px; width: 100%; }
.ptable th, .ptable td { text-align: left; padding: 5px 10px; border-bottom: 1px solid var(--border); vertical-align: top; }
.ptable thead th { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); font-weight: 600; }
.ptable tbody th { font-weight: 500; color: var(--muted); white-space: nowrap; font-size: 13px; }
.ptable.wide { font-size: 13px; }
.pform {
  border: none; background: none; padding: 0; margin: 0; font: inherit; color: var(--text);
  font-family: var(--serif); font-size: 16px; cursor: pointer; border-bottom: 1px dotted transparent;
}
.pform:hover { color: var(--accent); border-bottom-color: var(--accent); }
.pextras, .phelp { font-size: 13px; color: var(--muted); margin: 8px 0 0; line-height: 1.5; }
.plist { list-style: none; margin: 4px 0 8px; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 16px; }
.ptags { margin-left: 6px; font-size: 11px; color: var(--muted); }
.p-forms {
  margin-left: auto; border: 1px solid var(--border); background: var(--card); color: var(--accent);
  border-radius: 999px; font-size: 11px; padding: 2px 9px; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;
}
.p-forms:hover { border-color: var(--accent); }

/* ---------- grammar ---------- */
.gr-section { margin-bottom: 18px; }
.gr-section h2 { margin: 0 0 10px; font-size: 16px; }
.gr-text { font-size: 14px; line-height: 1.55; color: var(--text); margin: 0 0 10px; }
.gr-input {
  flex: 1; font: inherit; font-size: 15px; padding: 9px 12px; border: 1px solid var(--border);
  border-radius: 9px; background: var(--bg); color: var(--text);
}
.gr-input:focus { outline: none; border-color: var(--accent); }
.gr-result { margin-top: 10px; }
.gr-entry { margin: 4px 0; font-size: 14px; }
.table-wrap { overflow-x: auto; }
.gtable { border-collapse: collapse; width: 100%; font-size: 13.5px; }
.gtable th, .gtable td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--border); vertical-align: top; }
.gtable thead th { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.gtable tbody th { font-weight: 500; white-space: nowrap; }
.gr-q { font-family: var(--serif); white-space: nowrap; }
.gr-prep { font-family: var(--serif); }
.gr-ex { font-family: var(--serif); color: var(--muted); }
.gtable .p-speak { border: none; background: none; cursor: pointer; padding: 0 4px; color: var(--muted); vertical-align: middle; }
.gtable .p-speak:hover { color: var(--accent); }
.gr-terms { display: flex; flex-direction: column; gap: 10px; }
.gr-term-list { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 13px; }
.gr-term-card { padding: 10px 14px; border-radius: 10px; background: var(--accent-soft); font-size: 13.5px; line-height: 1.5; }
.gr-term-card strong { display: block; margin-bottom: 3px; }
.gr-term-card p { margin: 0; }
.gr-term-card .p-example { margin-top: 5px; font-family: var(--serif); }

/* ---------- mobile ---------- */
@media (max-width: 720px) {
  .layout { flex-direction: column; }
  .rail {
    width: 100%; height: auto; position: sticky; top: 0; z-index: 20;
    flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px;
    padding: 8px 10px; border-right: none; border-bottom: 1px solid var(--border);
  }
  .rail-top { flex: 1; }
  .rail-switch { flex: 0 0 100%; }
  .lang-btn { padding: 5px 8px; }
  .lang-flag { font-size: 18px; }
  .rail-toggle { display: inline-block; }
  .rail-nav { flex: 0 0 100%; flex-direction: row; flex-wrap: wrap; gap: 4px; }
  .rail-group { display: flex; gap: 4px; }
  .rail-group h3 { display: none; }
  .rail-item { width: auto; padding: 6px 10px; font-size: 13px; }
  .rail-bottom { display: none; width: 100%; }
  .rail.open .rail-bottom { display: flex; }
  .lib-filters { width: 100%; }
  .main { padding: 16px; }
  .split-layout { flex-direction: column; }
  .side-panel { width: 100%; }
  .target-output { font-size: 25px; }
  .turn { max-width: 100%; }
  .rl-text { font-size: 21px; }
  .book { font-size: 19px; }
  .read-actions { align-items: flex-start; }
}

/* the server is not reachable and no offline copy exists (shell.js unreachable()) */
.unreachable { max-width: 560px; padding: 48px 32px; }
.unreachable h1 { margin-bottom: 12px; }
.unreachable p { margin: 0 0 12px; line-height: 1.5; }

/* a piece whose line translations came from software, not a person (library.js machineTranslated) */
.badge.machine { background: color-mix(in srgb, var(--neut) 14%, transparent); color: var(--neut); }

/* ---------- Overheard (the feed) ---------- */
/* A phone-shaped column on a desktop, most of the screen on a phone. The
   scene behind a card is always dark so the text over it reads the same in
   either theme, which is why the word colours are pinned here rather than
   inherited from the page. */
.fd { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.fd-top { display: flex; align-items: center; gap: 10px; width: 100%; max-width: 460px; }
.fd-top h2 { margin: 0; font-size: 19px; }
.fd-badge {
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em; color: var(--muted);
  border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px;
}
.fd-top .fd-mute { margin-left: auto; }

.fd-stream {
  width: 100%; max-width: 460px; height: min(74vh, 740px);
  overflow-y: auto; overscroll-behavior-y: contain;
  scroll-snap-type: y mandatory; scrollbar-width: none;
  border: 1px solid var(--border); border-radius: 22px; box-shadow: var(--shadow);
  background: #14120f;
}
.fd-stream::-webkit-scrollbar { display: none; }
.fd-stream:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.fd-card, .sk-feed {
  position: relative; height: 100%; scroll-snap-align: start; scroll-snap-stop: always;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 24px 22px 18px; overflow: hidden; color: #f6f2ea;
  --masc: #8fb6f7; --fem: #f39a9a; --neut: #e6b566; --verb: #5ed0a8; --other: #d6d0c4;
  /* ⚠️ A card is a dark scene in either theme, so it carries the dark
     palette whatever the page's is. Without this a light-theme learner got
     the page's near-black --text on the scene — the drill cards' headword,
     gloss and hints at about 1.1:1, which is to say not there. */
  --bg: #151311; --panel: #1c1a17; --card: rgba(24, 21, 18, 0.8); --border: rgba(246, 242, 234, 0.24);
  --text: #f6f2ea; --muted: #d4ccbd; --accent: #8cc0f0; --accent-soft: rgba(140, 192, 240, 0.16);
  --on-accent: #10151b; --warn: #f5977e;
}
/* Each piece gets its own light, so you recognise where you are before you
   have read a word. Bright enough to be a place, dark enough to read on. */
.fd-bg {
  position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(80% 50% at 22% 8%, hsl(var(--h1) 68% 56%) 0%, transparent 66%),
    radial-gradient(75% 52% at 88% 30%, hsl(var(--h2) 62% 42%) 0%, transparent 64%),
    radial-gradient(100% 60% at 50% 104%, hsl(var(--h2) 50% 22%) 0%, transparent 72%),
    linear-gradient(165deg, hsl(var(--h1) 46% 28%), hsl(var(--h2) 40% 12%) 80%);
}
/* Five looks, so a batch is not one long gradient. Each is the same two hues
   arranged differently — no images and no requests, and the card keeps its own
   look because it is picked from the same hash as the hue. */
.fd-bg-rings {
  background:
    repeating-radial-gradient(circle at 78% 18%, hsl(var(--h1) 62% 52% / 0.40) 0 22px,
                              transparent 22px 54px),
    radial-gradient(70% 50% at 20% 82%, hsl(var(--h2) 58% 40% / 0.5) 0%, transparent 70%),
    linear-gradient(160deg, hsl(var(--h1) 50% 28%), hsl(var(--h2) 44% 11%) 82%);
}
.fd-bg-rays {
  background:
    repeating-linear-gradient(112deg, hsl(var(--h2) 64% 50% / 0.32) 0 12px, transparent 12px 42px),
    radial-gradient(80% 46% at 76% 12%, hsl(var(--h1) 68% 56% / 0.42) 0%, transparent 70%),
    linear-gradient(200deg, hsl(var(--h1) 52% 30%), hsl(var(--h2) 40% 11%) 78%);
}
.fd-bg-grid {
  background:
    repeating-linear-gradient(0deg, hsl(var(--h2) 58% 60% / 0.20) 0 1px, transparent 1px 30px),
    repeating-linear-gradient(90deg, hsl(var(--h2) 58% 60% / 0.20) 0 1px, transparent 1px 30px),
    radial-gradient(90% 55% at 50% 8%, hsl(var(--h1) 66% 54% / 0.40) 0%, transparent 66%),
    linear-gradient(150deg, hsl(var(--h1) 48% 27%), hsl(var(--h2) 42% 11%) 80%);
}
.fd-bg-drift {
  background:
    radial-gradient(58% 34% at 14% 74%, hsl(var(--h2) 64% 50% / 0.75) 0%, transparent 70%),
    radial-gradient(46% 30% at 82% 20%, hsl(var(--h1) 66% 54% / 0.7) 0%, transparent 72%),
    radial-gradient(70% 44% at 52% 108%, hsl(var(--h1) 50% 34%) 0%, transparent 76%),
    linear-gradient(180deg, hsl(var(--h2) 40% 20%), hsl(var(--h1) 34% 11%) 84%);
}

/* Depth, so a scene is a place rather than a fill. A flat two-stop gradient
   reads as a colour swatch at phone size: the light needs somewhere to come
   from, and the corners need to fall away. */
.fd-bg::before {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(120% 80% at 50% 0%, hsl(var(--h1) 70% 62% / 0.28) 0%, transparent 62%),
    radial-gradient(90% 60% at 8% 96%, hsl(var(--h2) 62% 44% / 0.24) 0%, transparent 68%);
  mix-blend-mode: screen;
}

.fd-head { position: relative; z-index: 1; display: flex; flex-wrap: wrap; gap: 7px; }
.fd-tag {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(246, 242, 234, 0.9); background: rgba(20, 16, 12, 0.4);
  border: 1px solid rgba(246, 242, 234, 0.28); border-radius: 999px; padding: 4px 10px;
  backdrop-filter: blur(6px);
}
.fd-place { text-transform: none; letter-spacing: 0.02em; font-weight: 600; }
/* ── Tune In: what am I listening to ─────────────────────────────────────────
   The filter the feed was missing. Its chips sit under the heading so the
   answer to "why am I only getting hospitals" is on the screen rather than
   behind a button, and each one is its own way out. */
.fd-filter {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  width: 100%; max-width: 460px;
}
.fd-filter-how { font-size: 11.5px; color: var(--muted); letter-spacing: .03em; }
.fd-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: inherit; font-size: 12px; cursor: pointer; white-space: nowrap;
  padding: 5px 10px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--card); color: var(--muted);
}
.fd-chip:hover { border-color: var(--accent); color: var(--accent); }
.fd-chip.is-on { border-color: var(--accent); background: var(--accent); color: var(--card); }
.fd-chip small { opacity: .82; font-size: 10.5px; }
.fd-chip-clear { border-style: dashed; }
.fd-tuner-why { margin: 0 0 14px; font-size: 13.5px; color: var(--muted); line-height: 1.55; }
.fd-tuner-group {
  margin: 16px 0 8px; font-size: 11.5px; text-transform: uppercase;
  letter-spacing: .07em; color: var(--muted);
}
.fd-subjects, .fd-tuner-modes { display: flex; flex-wrap: wrap; gap: 6px; }
.fd-opt { display: flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--muted); cursor: pointer; }
.fd-empty .fd-btn { margin-top: 12px; }

.fd-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* The picture behind the words (server/scenes.py).

   ⚠️ It fades in on load rather than appearing, and the gradient stays
   underneath it rather than being replaced: a card whose image is still on
   the wire, or never arrives, is the card as it has always looked instead of
   a grey hole where a photograph should be.

   ⚠️ And it is dimmed, with the dark wash over the foot of it. The words sit
   on this, and white text on an unknown photograph is a contrast accident
   waiting for the one picture that happens to be pale at the bottom. */
.fd-image {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity 420ms ease;
}
.fd-bg.has-image .fd-image { opacity: 0.55; }
/* ⚠️ The wash is on EVERY card, not only the ones with a photograph behind
   them. The words sit on the foot of the card and the gradient's own hue is
   picked by a hash, so whether the text had enough contrast under it was a
   matter of which hue the hash happened to land on. A card carrying an image
   gets more of it, because a photograph can be pale anywhere. */
.fd-bg::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  /* ⚠️ Never quite clear at the top. A card with many lines grows its text
     upward into the brightest part of the scene, where a wash that faded to
     nothing left the first lines at about 2.4:1. */
  background: linear-gradient(to top, rgba(8, 7, 6, 0.72) 0%, rgba(8, 7, 6, 0.4) 42%, rgba(8, 7, 6, 0.24) 100%);
}
.fd-bg.has-image::after {
  background: linear-gradient(to top, rgba(8, 7, 6, 0.88) 0%, rgba(8, 7, 6, 0.52) 38%, rgba(8, 7, 6, 0.3) 100%);
}
@media (prefers-reduced-motion: reduce) {
  .fd-image { transition: none; }
}

.fd-body { position: relative; z-index: 1; margin-top: auto; display: flex; flex-direction: column; gap: 14px; }
.fd-turn { display: flex; flex-direction: column; gap: 3px; }

/* Three lines on screen, whatever the card holds.

   A conversation card carries the whole exchange now, so that a dialogue can
   reach an end instead of stopping after somebody's question. Only three lines
   are up at a time: the one just spoken and the two before it. The oldest
   fades up and out as the newest fades in from below, which is what a
   conversation looks like when you are in it.

   The lines that are not on screen collapse rather than hide, so the card
   stays the same height and the visible three do not jump around. They stay in
   the DOM: the translation toggle reaches every line, and a card can be played
   again without being rebuilt. */
.fd-turn {
  transition: opacity 420ms ease, transform 420ms ease,
              max-height 420ms ease, margin 420ms ease;
  max-height: 40vh;
}
.fd-turn.fd-now { opacity: 1; transform: none; }
/* heard already, and not yet heard. They look alike on purpose — what the
   learner needs to see is which line is being spoken NOW — but they are
   separate classes because they mean opposite things, and only one of them
   may ever appear on a card that has not been played. */
.fd-turn.fd-seen, .fd-turn.fd-ahead { opacity: 0.68; transform: none; }
.fd-turn.fd-gone,
.fd-turn.fd-soon {
  opacity: 0; max-height: 0; margin-top: -14px;    /* cancel the flex gap */
  pointer-events: none; overflow: hidden;
}
.fd-turn.fd-gone { transform: translateY(-10px); }
.fd-turn.fd-soon { transform: translateY(10px); }
/* No voice to follow — the sound is off, or the card was never baked — so the
   moving window has nothing driving it. Three lines of a twelve-line
   conversation with no way to reach the rest is a dead end, so the card shows
   the whole exchange, evenly, to be read. ⚠️ Nothing is dimmed here: dimming
   means "you have heard this", and on a silent card nobody has. */
.fd-card.fd-static .fd-body { overflow-y: auto; overscroll-behavior: contain; }
.fd-card.fd-static .fd-turn {
  opacity: 1; max-height: none; margin-top: 0; transform: none;
  pointer-events: auto; overflow: visible;
}

/* Somebody who has asked for less movement gets the same three lines without
   the travel; the fade alone still says which line is new. */
@media (prefers-reduced-motion: reduce) {
  .fd-turn { transition: opacity 200ms ease, max-height 0ms, margin 0ms; }
  .fd-turn.fd-gone, .fd-turn.fd-soon { transform: none; }
}
.fd-who {
  font-size: 11px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
  color: rgba(246, 242, 234, 0.78);
}
.fd-line { font-family: var(--serif); font-size: 23px; line-height: 1.45; text-shadow: 0 1px 10px rgba(0, 0, 0, 0.55); }
.fd-line .word { border-bottom-color: rgba(246, 242, 234, 0.28); }
.fd-line .word.studied { background: rgba(250, 204, 21, 0.3); border-radius: 3px; }
/* The translation arrives the way every other line on the card does.

   It used to be an element with `hidden` toggled, which cannot transition: the
   English appeared instantly in the middle of a card whose lines all ease. Now
   it is collapsed here and opened by the card's own .showing-en, on the same
   420ms as .fd-turn — the Czech above it slides down to make room while the
   English fades up into the gap, which is the "move" half of the same gesture. */
.fd-en {
  font-size: 14.5px; line-height: 1.45; color: rgba(246, 242, 234, 0.86);
  border-left: 2px solid rgba(246, 242, 234, 0.25); padding-left: 9px;
  max-height: 0; opacity: 0; transform: translateY(-6px);
  overflow: hidden; margin-top: -3px;    /* cancel .fd-turn's gap while closed */
  border-left-color: transparent;
  transition: opacity 420ms ease, transform 420ms ease,
              max-height 420ms ease, margin-top 420ms ease,
              border-left-color 420ms ease;
}
/* ⚠️ Keyed on the ELEMENT's own aria-hidden, not on the card's class. The
   reel capture reveals one line at a time (tests/e2e/capture_card.mjs) to show
   the app's move — hear the line, then see what it means — and a card-level
   class can only open all of them at once. One attribute carries both the
   state and the accessibility, so they cannot drift apart. */
.fd-en[aria-hidden="false"] {
  max-height: 40vh; opacity: 1; transform: none; margin-top: 0;
  border-left-color: rgba(246, 242, 234, 0.25);
}
/* Same courtesy as .fd-turn: the fade alone still says the English arrived. */
@media (prefers-reduced-motion: reduce) {
  .fd-en { transition: opacity 200ms ease, max-height 0ms, margin-top 0ms; transform: none; }
  .fd-en[aria-hidden="false"] { transform: none; }
}

.fd-foot {
  position: relative; z-index: 1; display: flex; align-items: flex-end; gap: 10px;
  margin-top: 18px; padding-top: 12px; border-top: 1px solid rgba(246, 242, 234, 0.14);
}
.fd-source { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fd-title {
  font-size: 12.5px; color: rgba(246, 242, 234, 0.84);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 210px;
}
.fd-source .fd-level { font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; color: rgba(246, 242, 234, 0.74); }
.fd-actions { margin-left: auto; display: flex; gap: 8px; }

.fd-btn {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  font-size: 13px; padding: 7px 12px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
}
.fd-card .fd-btn {
  border-color: rgba(246, 242, 234, 0.3); background: rgba(20, 16, 12, 0.45); color: #f6f2ea;
  backdrop-filter: blur(6px);
}
.fd-card .fd-btn:hover { border-color: rgba(246, 242, 234, 0.62); }
.fd-card.showing-en .fd-reveal { background: rgba(246, 242, 234, 0.9); color: #14120f; }

.fd-empty { justify-content: center; align-items: center; text-align: center; }
.fd-empty p { position: relative; z-index: 1; max-width: 280px; line-height: 1.5; }
.fd-hint { font-size: 12px; color: var(--muted); margin: 0; text-align: center; }

@media (max-width: 720px) {
  /* ⚠️ The stream takes what the view has LEFT, rather than a height guessed
     against the window. `100vh - 190px` was 75px short of the tab bar on a
     390x844 phone — a card that stopped before the screen did — and on a
     shorter one the same constant would have overflowed it. The view is sized
     from the things that actually bound it (the bar above, the tab bar below,
     both of which the app already knows) and the stream flexes into it.

     dvh, not vh: on a phone the address bar makes vh a promise the browser
     does not keep. */
     ⚠️ A DEFINITE height on .fd and a flex-basis of 0 on the stream, not a
     min-height and `auto`. The stream is a scroll container: give it a basis
     of auto inside a parent that is only a minimum and it sizes to its own
     content instead — fourteen cards made it 3047px tall and the whole page
     scrolled rather than the stream. */
  .fd { height: calc(100vh - 89px - var(--tabbar-h)); }
  .fd { height: calc(100dvh - 89px - var(--tabbar-h)); }
  .fd-stream { max-width: none; flex: 1 1 0; min-height: 0; border-radius: 16px; }
  .fd-top { max-width: none; }
  .fd-line { font-size: 21px; }
}

/* ---------- Tune In on a desktop ----------
   The card is laid out for a phone, and on a large screen a 460px column in
   the middle of a 1600px window is a phone held up to a monitor: the text is
   small, the scene is a stripe, and most of the display is empty.

   Wider, taller and bigger, with the text kept to a readable measure so the
   lines do not run the whole width. The card stops pinning its text to the
   bottom — that is a phone habit, where the thumb is — and centres it, which
   is where the eye already is on a desktop. */
@media (min-width: 1024px) {
  .fd-stream { max-width: 960px; height: min(80vh, 880px); border-radius: 26px; }
  .fd-top { max-width: 960px; }
  .fd-card { padding: 40px 48px 30px; justify-content: center; }
  .fd-body { margin-top: 0; gap: 18px; max-width: 44ch; }
  .fd-line { font-size: 30px; line-height: 1.42; }
  .fd-en { font-size: 17px; padding-left: 12px; }
  .fd-who { font-size: 12px; }
  .fd-head { position: absolute; top: 30px; left: 48px; right: 48px; }
  .fd-foot { position: absolute; left: 48px; right: 48px; bottom: 26px; margin-top: 0; }
  /* ⚠️ `.fd-drill > *:not(.fd-bg)` makes every child of a made card
     `position: relative` and outranks the two rules above, so on a made card
     the offsets meant for an absolute box became a relative nudge — and the
     tags slid 30px down onto the headword. */
  .fd-drill > .fd-head, .fd-drill > .fd-foot { position: absolute; }
  .fd-title { max-width: 360px; }
  .fd-hint { font-size: 13px; margin-top: 12px; }
}

/* Beyond about 1500px the scene is doing nothing but stretching, so give the
   card its own proportion and let the page breathe around it. */
@media (min-width: 1500px) {
  .fd-stream { max-width: 1120px; height: min(82vh, 940px); }
  .fd-top { max-width: 1120px; }
  .fd-line { font-size: 33px; }
  .fd-body { max-width: 46ch; }
}

/* ---------- Today (the front door) ---------- */
.td { max-width: 900px; }
.td-head h2 { margin: 0 0 6px; font-size: 26px; }
.td-why { margin: 0 0 18px; color: var(--muted); font-size: 14px; line-height: 1.5; max-width: 60ch; }
.td-grid { margin-bottom: 16px; }
.td-reason { margin: 8px 0 0; font-size: 12.5px; color: var(--accent); }
.td-reason.revisit { color: var(--neut); font-weight: 600; }
.td-reason.companion { color: var(--verb); font-weight: 600; }
.td-foot { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.td-level { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }
.td-level select { font-family: inherit; font-size: 13px; padding: 3px 6px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--card); color: var(--text); }
.td-more { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--border); }
.td-link {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer; font-size: 14px;
  padding: 0 18px; min-height: 48px; box-sizing: border-box;
  border-radius: 10px; border: 1px solid var(--border);
  background: var(--card); color: var(--text); box-shadow: var(--shadow);
}
.td-link:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- the account menu (was a permanently open drawer) ---------- */
.rail-more {
  display: flex; align-items: center; gap: 9px; width: 100%; cursor: pointer;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
  border-radius: 12px; padding: 8px 10px; font-size: 13.5px; text-align: left;
}
.rail-more:hover { border-color: var(--accent); }
.rail-more.open { border-color: var(--accent); }
.rail-more-icon { display: inline-flex; color: var(--muted); }
.rail-more-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail-more .caret { margin-left: 0; color: var(--muted); transition: transform 0.15s; }
.rail-more.open .caret { transform: rotate(180deg); }
.rail-panel {
  margin-top: 10px; display: flex; flex-direction: column; gap: 14px;
  max-height: 60vh; overflow-y: auto;
}
.rail-extra { display: flex; flex-direction: column; gap: 2px; }
.rail-quiet {
  display: flex; align-items: center; gap: 8px; cursor: pointer; text-align: left;
  border: 0; background: none; color: var(--muted); font-size: 13px; padding: 5px 2px; border-radius: 8px;
}
.rail-quiet:hover { color: var(--accent); }

/* ---------- reading modes ---------- */
.rs-modes { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.rs-mode {
  display: flex; flex-direction: column; gap: 1px; cursor: pointer; text-align: left;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
  border-radius: 10px; padding: 8px 11px; font-size: 13.5px;
}
.rs-mode strong { font-weight: 600; }
.rs-mode span { font-size: 12px; color: var(--muted); }
.rs-mode:hover { border-color: var(--accent); }
.rs-mode.on { border-color: var(--accent); background: var(--accent-soft); }
.rs-mode.on span { color: var(--text); }
.rs-custom-btn {
  border: 0; background: none; color: var(--muted); cursor: pointer;
  font-size: 12.5px; padding: 4px 2px; text-decoration: underline; text-underline-offset: 3px;
}
.rs-custom-btn:hover, .rs-custom-btn.open { color: var(--accent); }

/* ---------- how hard a piece is for its own level ---------- */
/* A vertical gauge beside the level badge: low and green at the gentle end of
   the level, filling up through amber to red at the hard end. */
.diffbar {
  display: inline-flex; align-items: flex-end; vertical-align: middle;
  width: 9px; height: 19px; margin-left: 3px; padding: 1px;
  border-radius: 4px; background: color-mix(in srgb, var(--text) 9%, transparent);
  border: 1px solid var(--border); overflow: hidden; flex-shrink: 0;
}
.diffbar-fill { display: block; width: 100%; border-radius: 2px; background: currentColor; }
.diffbar.green { color: var(--verb); }
.diffbar.amber { color: var(--neut); }
.diffbar.red { color: var(--warn); }

/* the line of encouragement under Today's picks */
.td-note {
  margin: 0 0 18px; padding: 11px 15px; border-radius: 10px; max-width: 62ch;
  background: var(--panel); border: 1px solid var(--border);
  color: var(--text); font-size: 13.5px; line-height: 1.55;
}
.td-toggle { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); cursor: pointer; }

/* the one-time explanation of delayed subtitles, shown where it is true */
.pl-tip {
  margin: 0 0 14px; padding: 10px 14px; border-radius: 10px;
  background: var(--accent-soft); color: var(--text); font-size: 13.5px; line-height: 1.5;
  border: 1px solid var(--border); max-width: 62ch;
}

/* ---------- Tune In: a card from the phrase library ---------- */
/* Not a fragment overheard but a small comparison: several ways of saying one
   thing, side by side, each one its own play button. */
.fd-phrases .fp-label { margin: 10px 0 4px; font-size: 17px; font-weight: 700; color: var(--text); }
.fp-list { display: flex; flex-direction: column; gap: 6px; padding: 4px 0 10px; overflow-y: auto; }
.fp-row {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 10px; align-items: baseline;
  width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card);
  padding: 8px 11px; font-family: inherit;
}
.fp-row:hover:not(:disabled) { border-color: var(--accent); }
.fp-row:disabled { cursor: default; opacity: 0.75; }
.fp-phrase { font-size: 17px; font-weight: 600; color: var(--text); }
.fp-gloss { font-size: 13px; color: var(--muted); justify-self: end; }
.fp-chips { grid-column: 1 / -1; display: flex; gap: 5px; }
.fp-chip {
  font-size: 10.5px; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 1px 6px; border-radius: 6px; background: var(--panel); color: var(--muted);
}
.fp-chip.r-formal { color: var(--neut); }
.fp-chip.r-casual { color: var(--verb); }
.fp-note { grid-column: 1 / -1; font-size: 12.5px; color: var(--muted); line-height: 1.45; }

/* one quiet pulse on one word, once ever, to point at the popover */
.word.coach { position: relative; border-radius: 4px; animation: coach-pulse 1.6s ease-in-out 3; }
@keyframes coach-pulse {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 30%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .word.coach { animation: none; outline: 2px solid var(--accent); } }

/* asked once, when a piece has just been finished and there is progress to lose */
.keep-progress {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 16px 0 0; padding: 12px 15px; border-radius: 10px;
  background: var(--accent-soft); border: 1px solid var(--border);
  font-size: 13.5px; color: var(--text);
}

/* the language menu lists what you actually study, and offers the rest */
.lang-add {
  display: flex; align-items: center; gap: 8px; width: 100%; cursor: pointer;
  border: 0; border-top: 1px solid var(--border); background: none; color: var(--accent);
  padding: 9px 12px; font-size: 13px; font-family: inherit; text-align: left; text-decoration: none;
}
.lang-add:hover { background: var(--panel); }
/* a course still being written: shown, greyed, not clickable */
.lang-option.is-soon { cursor: default; }
.lang-option.is-soon:hover { background: none; }
.lang-option.is-soon .lang-flag, .lang-option.is-soon .lang-text > span:not(.lang-soon) { opacity: 0.45; }
/* under the name: the menu is narrow, and beside it a long name ran into it */
.lang-text > .lang-soon {
  align-self: flex-start; margin-top: 4px; white-space: nowrap;
  font-size: 9.5px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--muted); border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px;
}

/* ---------- Tune In: cards made rather than cut ---------- */
.fd-drill .dr-word { display: flex; align-items: baseline; gap: 12px; margin: 12px 0 10px; }
.fd-drill .dr-word strong { font-size: 26px; font-weight: 700; color: var(--text); }
.dr-say, .fd-drill .fd-btn { cursor: pointer; font-family: inherit; }
.dr-say {
  border: 1px solid var(--border); background: var(--card); color: var(--accent);
  border-radius: 8px; padding: 4px 10px; font-size: 12.5px;
}
.dr-say:hover:not(:disabled) { border-color: var(--accent); }
.dr-list { display: flex; flex-direction: column; gap: 7px; overflow-y: auto; padding-bottom: 8px; }
.dr-example {
  display: grid; gap: 2px; padding: 9px 12px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card);
}
.dr-text { font-size: 16px; color: var(--text); }
.dr-en { font-size: 12.5px; color: var(--muted); }
.dr-from { font-size: 10.5px; letter-spacing: 0.04em; color: var(--muted); }
.dr-rates { display: flex; gap: 8px; margin: 10px 0; }

/* the made cards have a background now, so everything on them has to sit on
   top of it rather than behind it */
.fd-drill > *:not(.fd-bg) { position: relative; z-index: 1; }
/* and they are mostly short, so they hang from the top of a tall card. Centre
   what there is: "Hear the difference" is two words and was sitting under a
   third of a screen of empty scene. */
.fd-drill { display: flex; flex-direction: column; }
.fd-drill .dr-pair, .fd-drill .dr-list, .fd-drill .dr-idiom,
.fd-drill .dr-paradigm, .fd-drill .dr-forms { margin-top: auto; margin-bottom: auto; }

.dr-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 14px 0; }
.dr-pair-side {
  display: grid; gap: 3px; cursor: pointer; text-align: left; font-family: inherit;
  border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 14px;
}
.dr-pair-side:hover:not(:disabled) { border-color: var(--accent); }
.dr-pair-side strong { font-size: 24px; color: var(--text); }
.dr-pos { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.dr-hint { font-size: 12.5px; color: var(--muted); margin: 0; }

.dr-member {
  display: grid; grid-template-columns: auto auto 1fr; gap: 4px 10px; align-items: baseline;
  width: 100%; cursor: pointer; text-align: left; font-family: inherit;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card); padding: 9px 12px;
}
.dr-member:hover:not(:disabled) { border-color: var(--accent); }
.dr-member strong { font-size: 17px; color: var(--text); }

/* ---------- Saved: what a learner kept on purpose ---------- */
.sv { max-width: 780px; }
.sv-head h2 { margin: 0 0 6px; font-size: 26px; }
.sv-why { margin: 0 0 20px; color: var(--muted); font-size: 14px; }
.sv-block:not(:empty) { margin-bottom: 26px; }
.sv-title { margin: 0 0 8px; font-size: 13px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.sv-list { display: flex; flex-direction: column; gap: 6px; }
.sv-row { display: flex; align-items: stretch; gap: 6px; }
.sv-main {
  flex: 1; display: grid; gap: 2px; text-align: left; cursor: pointer; font-family: inherit;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card); padding: 10px 13px;
}
.sv-main:hover:not(:disabled) { border-color: var(--accent); }
.sv-main strong { font-size: 16px; color: var(--text); }
.sv-meta { font-size: 12.5px; color: var(--muted); }
.sv-drop {
  cursor: pointer; border: 1px solid var(--border); border-radius: 10px; background: var(--card);
  color: var(--muted); padding: 0 11px; display: flex; align-items: center;
}
.sv-drop:hover { color: var(--warn); border-color: var(--warn); }

/* ---------- Dictionary ---------- */
.dc { max-width: 820px; }
.dc-head h2 { margin: 0 0 6px; font-size: 26px; }
.dc-why { margin: 0 0 20px; color: var(--muted); font-size: 14px; }
.dc-wotd {
  padding: 16px 18px; border-radius: 12px; background: var(--accent-soft);
  border: 1px solid var(--border); margin-bottom: 20px;
}
.dc-tag { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.dc-word { display: flex; align-items: baseline; gap: 12px; margin: 4px 0; }
.dc-word strong { font-size: 26px; font-weight: 700; color: var(--text); }
.dc-gloss { margin: 0 0 6px; font-size: 14px; color: var(--text); }
.dc-also { margin: 0 0 8px; font-size: 13px; color: var(--muted); }
.dc-actions { display: flex; gap: 8px; }
.dc-search { display: flex; gap: 8px; margin-bottom: 14px; }
.dc-search input {
  flex: 1; font-family: inherit; font-size: 15px; padding: 9px 13px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card); color: var(--text);
}
.dc-result:not(:empty) { margin-bottom: 26px; display: flex; flex-direction: column; gap: 12px; }
.dc-found { border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 13px 16px; }
.dc-found h4 { margin: 0 0 8px; font-size: 13px; color: var(--muted); font-weight: 600; }
/* An entry is a meaning plus the facts you need to use it: what it declines
   like, its aspect partner, its gender. Those were a click away or nowhere. */
.dc-entry { padding: 10px 0; border-top: 1px solid var(--border); }
.dc-entry:first-of-type { border-top: none; padding-top: 2px; }
.dc-entry-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; }
.dc-pos { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.dc-sense { margin: 3px 0 0; font-size: 14.5px; line-height: 1.45; max-width: 62ch; }
.dc-tags { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.dc-tag-chip {
  font-size: 10.5px; border-radius: 999px; padding: 1px 7px;
  background: var(--card); color: var(--muted); border: 1px solid var(--border);
}
.dc-facts { display: flex; flex-wrap: wrap; gap: 6px; margin: 7px 0 0; }
.dc-fact {
  display: inline-flex; align-items: baseline; gap: 6px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--card);
  padding: 3px 9px; font-size: 12px; color: inherit;
}
.dc-fact:hover { border-color: var(--accent); }
span.dc-fact:hover { border-color: var(--border); }
.dc-fact-k { color: var(--muted); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.05em; }
.dc-fact-v { font-weight: 600; }
/* what breaks the pattern: "masculine, though it ends in -a" */
.dc-fact-note { color: var(--muted); font-style: italic; }
.dc-fact-note::before { content: "— "; font-style: normal; }

/* Candidates: stacked and big enough to choose from without opening one.
   Six words can all translate "dinner"; what separates them has to be ON the
   card, or the reader is picking at random. */
.dc-cands { display: flex; flex-direction: column; gap: 8px; }
.dc-cand {
  display: flex; flex-direction: column; gap: 3px; width: 100%;
  cursor: pointer; text-align: left; font-family: inherit; color: inherit;
  border: 1px solid var(--border); border-radius: 12px; background: var(--card);
  padding: 12px 15px;
}
.dc-cand:hover { border-color: var(--accent); }
.dc-cand-top { display: flex; align-items: baseline; flex-wrap: wrap; gap: 9px; }
.dc-cand-word { font-size: 19px; font-weight: 700; }
.dc-cand-meta { display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: 6px; }
.dc-cand-gloss { font-size: 13.5px; color: var(--muted); line-height: 1.45; }
.dc-cand-pair { font-size: 12px; color: var(--muted); font-style: italic; }
/* Which version of the word this card is. Three of the eight cards for "rain"
   said only "rain"; this is what separates déšť from deštový. */
.dc-cand-qual {
  font-size: 11px; color: var(--accent); text-transform: uppercase;
  letter-spacing: 0.05em; font-weight: 600;
}
/* one real use of it, the language first so the eye lands on the word */
.dc-cand-ex { display: flex; flex-direction: column; gap: 1px; margin-top: 3px; }
.dc-cand-ex-l { font-size: 13px; }
.dc-cand-ex-t { font-size: 12.5px; color: var(--muted); }

/* the word page: everything the app knows about one word, in one place */
.dc-field { position: relative; flex: 1; }
.dc-search .dc-field input { width: 100%; box-sizing: border-box; }
.dc-suggest {
  position: absolute; z-index: 40; top: calc(100% + 4px); left: 0; right: 0; margin: 0; padding: 4px;
  list-style: none; max-height: 320px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card); box-shadow: var(--shadow-pop);
}
.dc-sg {
  display: flex; align-items: baseline; gap: 8px; padding: 6px 9px; border-radius: 7px;
  cursor: pointer; font-size: 14px;
}
.dc-sg:hover, .dc-sg.on { background: var(--accent-soft); }
.dc-sg strong { font-weight: 600; }
.dc-sg-gloss { color: var(--muted); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dc-via { color: var(--muted); font-size: 12px; margin-left: auto; padding-left: 8px; flex: none; }
.dc-freq { display: inline-flex; align-items: center; gap: 5px; margin-left: auto; }
.dc-band {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em; padding: 2px 6px; border-radius: 999px;
  background: color-mix(in srgb, var(--other) 12%, transparent); color: var(--other);
}
.dc-band.b-A1, .dc-band.b-A2 { background: color-mix(in srgb, var(--verb) 12%, transparent); color: var(--verb); }
.dc-band.b-B1, .dc-band.b-B2 { background: color-mix(in srgb, var(--neut) 12%, transparent); color: var(--neut); }
.dc-band.b-C1, .dc-band.b-C2 { background: color-mix(in srgb, var(--fem) 11%, transparent); color: var(--fem); }
.dc-rank { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.dc-actions { margin-top: 10px; }
.dc-block {
  border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 13px 16px;
}
.dc-block h4 { margin: 0 0 2px; font-size: 13px; color: var(--muted); font-weight: 600; }
.dc-block-why { margin: 0 0 10px; font-size: 12.5px; color: var(--muted); }
.dc-ex-list { display: flex; flex-direction: column; gap: 6px; }
/* one example at a time, with the way to the next one under it */
.dc-ex-one { display: flex; flex-direction: column; }
.dc-ex-foot { display: flex; align-items: center; gap: 10px; margin: 8px 0 0; }
.dc-ex-count { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.dc-ex {
  display: grid; gap: 2px; text-align: left; font-family: inherit; cursor: pointer; width: 100%;
  border: 1px solid transparent; border-left: 3px solid var(--border); border-radius: 0 8px 8px 0;
  background: var(--panel); padding: 8px 11px;
}
.dc-ex:hover { border-left-color: var(--accent); }
.dc-ex-text { font-size: 15px; color: var(--text); }
.dc-ex-tr { font-size: 13px; color: var(--muted); }
.dc-ex-src { display: flex; align-items: center; gap: 6px; margin-top: 3px; font-size: 11.5px; color: var(--muted); }
.dc-ex-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.dc-redirect {
  margin: 0 0 8px; font-size: 12.5px; color: var(--muted);
  padding: 6px 10px; border-radius: 8px; background: var(--panel);
}

/* The word page the SERVER writes (server/wordpage.py, Lane G): what a
   crawler, a link preview and a reader with scripts off get at
   /<pair>/dictionary/<word>. The app removes it once its own view is up
   (shell.js boot). Built from the app's word-page classes wherever they fit,
   so the two read as one page; these are only the parts a server page has
   and the app does not — links where the app has buttons, a heading tree,
   the breadcrumb and a native audio control. */
#prerender:empty { display: none; }
.wordpage { display: flex; flex-direction: column; gap: 12px; }
.wp-crumbs { font-size: 13px; color: var(--muted); }
.wp-crumbs a { display: inline-block; padding: 5px 0; color: var(--accent); text-decoration: none; }  /* a 24px target */
.wp-crumbs a:hover { text-decoration: underline; }
.wordpage h1 { margin: 0; font-size: 26px; font-weight: 700; line-height: 1.2; color: var(--text); }
/* each block is headed the way the app's tabs name it (.dc-tabs: Examples,
   Forms, Thesaurus), with the app's own small-capital labels inside */
.wordpage h2 {
  margin: 0 0 10px; padding: 0 0 7px; font-size: 13px; font-weight: 600; color: var(--text);
  border-bottom: 1px solid var(--border);
}
.wordpage > .dc-block { margin: 10px 0 0; }
.wp-hear { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin: 6px 0 2px;
  font-size: 13px; color: var(--muted); }
.wp-hear audio { height: 34px; max-width: 100%; }
.wp-ex-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
/* a long piece title is cut, not allowed to widen the page on a phone */
.wordpage .dc-ex { grid-template-columns: minmax(0, 1fr); }
.wordpage .dc-ex-src, .wordpage .dc-ex-title { min-width: 0; }
a.dc-ex, a.dc-fact, a.primary-btn { text-decoration: none; color: inherit; }
a.primary-btn { color: var(--on-accent); }
a.dc-ex:focus-visible, .wp-syn a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wp-syn { list-style: none; margin: 0 0 8px; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.wp-syn a {
  display: inline-flex; align-items: baseline; gap: 8px; text-decoration: none; color: inherit;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card); padding: 6px 11px; font-size: 13px;
}
.wp-syn a:hover { border-color: var(--accent); }
.wp-syn strong { font-size: 15px; }
.wp-syn span { color: var(--muted); }
.wp-phrases { list-style: none; margin: 0; }
.wordpage .fp-row { cursor: default; }
.wordpage .fp-row:hover { border-color: var(--border); }
.wp-cta { margin: 4px 0 0; }
.wp-none { margin: 0; font-size: 15px; line-height: 1.5; }
.wp-none a { color: var(--accent); }
@media (max-width: 720px) {
  .wordpage h1 { font-size: 24px; }
  .wordpage .dc-word { flex-wrap: wrap; }
}

.p-near {
  display: grid; gap: 1px; width: 100%; text-align: left; font-family: inherit; cursor: pointer;
  border: 1px solid var(--border); border-radius: 8px; background: var(--panel);
  padding: 5px 9px; margin-top: 5px; font-size: 13px; color: var(--text);
}
.p-near:hover { border-color: var(--accent); }
.p-near span { color: var(--muted); font-size: 12px; }

/* the admin-only "make a clip" control on a Tune In card */
/* the playlist under a piece: where it sits, and what is left */
.pl-series { margin: 26px 0 10px; border-top: 1px solid var(--border); padding-top: 16px; }
.pl-series.hidden { display: none; }
.pl-series-head { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: baseline;
  justify-content: space-between; margin-bottom: 10px; font-size: 13px; }
/* Previous and next through the playlist, at the foot of the piece.

   ⚠️ Sized up deliberately. This is the control somebody reaches for having
   just finished reading — the moment the whole app is trying to earn — and it
   was a 38px row of 13px text. A thumb on a phone needs a target, and the
   thing you want them to press should look like the thing to press. */
.pl-steps { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 16px; }
.pl-step {
  display: flex; align-items: center; gap: 10px; text-align: left;
  padding: 14px 16px; min-width: 0; min-height: 60px; box-sizing: border-box;
  border-radius: 12px;
}
.pl-step:not([disabled]):hover { border-color: var(--accent); color: var(--accent); }
.pl-step-next { justify-content: flex-end; text-align: right; }
.pl-step-text { display: grid; gap: 1px; min-width: 0; }
.pl-step-label { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.pl-step-title { font-size: 14.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the greyed end of a playlist: still there, still the same size, plainly off */
.pl-step[disabled] { opacity: 0.42; cursor: default; }
.pl-step[disabled] .pl-step-title { visibility: hidden; }
/* ⚠️ A line between the rows. Without one the titles ran together as a block
   of similar text and there was nothing to say where one piece ended and the
   next began — the gap alone was not a boundary the eye could use. */
.pl-series-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.pl-series-rows > li + li { border-top: 1px solid var(--border); }
.pl-series-row { display: grid; grid-template-columns: 20px 1fr auto; gap: 9px; align-items: center;
  width: 100%; text-align: left; font-family: inherit; font-size: 14px; cursor: pointer;
  border: 1px solid transparent; border-radius: 8px; background: none; color: var(--text);
  padding: 11px 10px; min-height: 44px; box-sizing: border-box; }
.pl-series-row:hover { background: var(--panel); }
/* a number and a tick are different widths; fix the column so the
   titles line up down the list whatever each row is showing */
.pl-num { text-align: center; font-variant-numeric: tabular-nums; color: var(--muted); }
.pl-series-row.read .pl-series-title { color: var(--muted); }
.pl-series-row.here { background: var(--accent-soft); border-color: var(--accent); cursor: default; }
.pl-series-row.here .pl-series-title { font-weight: 600; }
.pl-series-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-series-meta { font-size: 11.5px; color: var(--muted); }
@media (max-width: 560px) { .pl-steps { grid-template-columns: 1fr; } }

.fd-clip-wrap { margin-top: 10px; display: grid; gap: 6px; justify-items: start; }
.fd-clip { font-size: 12px; }
.fd-clip-panel { display: grid; gap: 6px; justify-items: start; }
.fd-clip-styles { display: flex; flex-wrap: wrap; gap: 5px; }
.fd-clip-style { font-size: 11.5px; text-transform: capitalize; }
.fd-clip-link { font-size: 12px; color: var(--accent); word-break: break-all; }
.fd-clip-note { font-size: 11.5px; color: var(--muted); }

.p-native {
  font-size: 10.5px; letter-spacing: 0.03em; text-transform: lowercase;
  color: var(--muted); border: 1px solid var(--border); border-radius: 999px;
  padding: 0 6px; margin-right: 5px; white-space: nowrap;
}

/* The same badge on the word page: this meaning is written in the language
   being learned, not translated into English. See entryRow in dictionary.js. */
.dc-in-lang {
  font-size: 10.5px; letter-spacing: 0.03em; text-transform: lowercase;
  color: var(--muted); border: 1px solid var(--border); border-radius: 999px;
  padding: 0 6px; white-space: nowrap;
}

.p-why-tag {
  font-size: 10.5px; letter-spacing: 0.03em; color: var(--muted);
  background: var(--panel); border-radius: 999px; padding: 1px 6px; justify-self: start;
}

.p-period {
  font-size: 11.5px; color: var(--muted); font-style: italic;
  margin-bottom: 4px;
}
/* sull' = su + l' · on + the: a written word the analyser took apart */
.p-mwt { font-size: 12.5px; color: var(--muted); margin: 2px 0 6px; }
.p-mwt strong { color: var(--text, inherit); font-weight: 600; }

.dc-rel-row { display: grid; gap: 4px; margin-bottom: 9px; }
.dc-rel-label { font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.dc-rel-chip {
  font-size: 10.5px; letter-spacing: 0.03em; color: var(--muted);
  background: var(--panel); border-radius: 999px; padding: 1px 6px; justify-self: start;
}
.dc-cand .dc-rel-chip { margin-top: 2px; }

.dc-thes-head { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; margin-bottom: 10px; }
.dc-thes-head h3 { margin: 0; font-size: 17px; }
.dc-kinds { display: flex; gap: 6px; }
.dc-kind {
  cursor: pointer; font-family: inherit; font-size: 12.5px; padding: 4px 10px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--card); color: var(--muted);
}
.dc-kind.on { border-color: var(--accent); color: var(--accent); }
.dc-groups { display: flex; flex-direction: column; gap: 6px; }
.dc-group { border: 1px solid var(--border); border-radius: 10px; background: var(--card); }
.dc-group summary {
  cursor: pointer; padding: 10px 14px; display: flex; justify-content: space-between;
  align-items: center; font-size: 15px; color: var(--text);
}
.dc-count { font-size: 12px; color: var(--muted); }
.dc-group .fp-list { padding: 0 12px 12px; }

/* the completion bar on a card, once there is something to show */
.cc-bar { display: block; height: 3px; border-radius: 2px; background: var(--border); margin-top: 8px; overflow: hidden; }
.cc-bar-fill { display: block; height: 100%; background: var(--accent); border-radius: 2px; }
.cc-bar.done .cc-bar-fill { background: var(--verb); }

/* keep buttons that are already keeping */
.ghost-btn.on { border-color: var(--accent); color: var(--accent); }
.pop-keep { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }

/* vocabulary coverage: which piece kinds to count, and the word lists behind a level */
.adm-kinds { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 0 0 10px; }
.adm-kind { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; cursor: pointer; }
.adm-kind input { margin: 0; }
.adm-words { margin: 6px 0 12px; }
.adm-words > summary { cursor: pointer; font-size: 13px; color: var(--muted); }
.adm-words p { margin: 6px 0; font-size: 12.5px; line-height: 1.6; word-break: break-word; }

/* Playlists: editorial collections of pieces (static/js/views/playlists.js) */
.pl-head h2 { margin: 0 0 4px; }
.pl-why { margin: 0 0 14px; color: var(--muted); max-width: 56ch; }
.pl-list { display: grid; gap: 12px; }
/* The same card as the Course section — level colour on the edge, a way in on
   the right, and height enough to hit. See card() in views/playlists.js. */
.pl-card {
  display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  padding: 16px 16px 16px 18px; cursor: pointer; min-height: 88px;
  border: 1px solid var(--border); border-left: 4px solid var(--lv, var(--border));
  transition: border-color 120ms, transform 120ms;
}
.pl-card:hover, .pl-card:focus-visible { border-color: var(--accent); }
.pl-card:hover { transform: translateY(-1px); }
/* one already begun says so, and offers Continue rather than Open */
.pl-card.is-on { border-left-width: 5px; }
.pl-card-body { flex: 1; min-width: 0; }
.pl-card h3 { margin: 0; font-size: 16.5px; }
.pl-card-top { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 8px; }
.pl-chips { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.pl-facts { font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.pl-goal { margin: 6px 0 10px; color: var(--text); max-width: 62ch; }
.pl-note { margin: 4px 0 10px; max-width: 62ch; }
.pl-bar { display: block; height: 4px; border-radius: 3px; background: var(--panel); overflow: hidden; }
.pl-fill { display: block; height: 100%; background: var(--accent); }
.pl-progress { display: grid; gap: 4px; }
.pl-progress .muted { font-size: 12px; }
.pl-back { display: inline-flex; align-items: center; gap: 4px; margin-bottom: 10px; }
.pl-one-title { margin: 0 0 4px; }
.pl-rows { display: grid; gap: 8px; margin-top: 12px; }
.pl-row { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 10px 12px;
          background: var(--card); border: 1px solid var(--border); border-radius: 10px; cursor: pointer; }
.pl-row:hover { border-color: var(--accent); }
.pl-row.read { opacity: 0.82; }
.pl-num { min-width: 18px; color: var(--muted); font-variant-numeric: tabular-nums; font-size: 13px; }
/* the same cell as the number — see the note in renderSeries() */
.pl-num.is-read { color: var(--accent); font-weight: 700; }
.pl-row-main { display: grid; flex: 1; gap: 2px; }
.pl-meta { color: var(--muted); font-size: 12.5px; }
.lib-more { margin-top: 12px; }

/* Credits, and closing an account.
   Both live in the account drawer; both are obligations rather than features
   (attribution licences, App Review 5.1.1(v)), so they are styled to be
   readable and findable rather than to be noticed. */
.credits-sheet h3 { margin: 1.1em 0 .3em; font-size: .95rem; }
.credits-list { list-style: none; margin: 0; padding: 0; }
.credits-list li { padding: .35em 0; border-bottom: 1px solid var(--border); }
.credits-list li:last-child { border-bottom: 0; }
.credits-list p { margin: .15em 0 0; font-size: .82rem; }
.credits-licence { opacity: .85; font-size: .85em; }

.close-account { margin-top: .6em; }
.ghost-btn.danger { color: var(--warn); border-color: currentColor; }
.close-account p { margin: .4em 0 0; font-size: .8rem; line-height: 1.4; }

/* ── The guide: how the language works ───────────────────────────────────── */
/* Everything here takes its colour from the same variables as the rest of the
   app, so the diagrams follow the reader's theme with no second palette. */
/* the contents rail is grouped by shelf: a heading, then its topics.

   ⚠️ The headings used to be 11px UPPERCASE with letter-spacing in a 216px
   rail, which is how six words became a wall: "Adjectives, pronouns and the
   rest" broke over three lines, and seven shelves stacked into a block of
   grey texture with nothing in it for the eye to catch. Uppercase costs
   roughly a third more width and removes the ascenders and descenders a
   reader recognises a word by. Sentence case at reading size puts every
   heading on one or two lines and makes the rail scannable. */
.gd-toc { display: flex; flex-direction: column; align-items: stretch; gap: 0; }
.gd-toc-group { display: flex; flex-direction: column; align-items: stretch; gap: 0; }
.gd-toc-link {
  font-size: 13.5px; color: var(--muted); text-decoration: none; text-align: left;
}
.gd-toc-link:hover { color: var(--accent); }
.gd-toc-head { font-size: 14.5px; font-weight: 600; color: var(--text); }
.gd-topic { scroll-margin-top: 12px; }
/* a arriving reader landed on one of sixteen headings; hold it for a moment */
.gd-landed { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: no-preference) {
  .gd-landed { transition: outline-color 240ms ease; }
}
.gd-blurb { color: var(--muted); font-size: 13px; margin: -2px 0 14px; }

/* Guide cards (static/js/guidecards.js) — used by the Topics page and by any
   other page that wants to point at a topic. */
.gc-grid {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
/* ⚠️ A topic card is a door and has to read as one. These sat at the same
   size and weight as the prose around them, with the shelf heading SMALLER
   than the card titles underneath it — so nothing on the page said which
   things could be pressed. Same language as every other card in the app now:
   an accent edge that lights on hover, and room to hit. */
.gc-card {
  display: flex; flex-direction: column; gap: 6px; position: relative;
  padding: 15px 16px 15px 17px; text-decoration: none; color: inherit;
  border-left: 3px solid transparent; min-height: 104px;
  transition: border-color 120ms, transform 120ms;
}
.gc-card:hover { border-color: var(--accent); border-left-color: var(--accent); transform: translateY(-1px); }
.gc-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gc-card-icon { color: var(--muted); display: inline-flex; }
.gc-card:hover .gc-card-icon { color: var(--accent); }
.gc-card-title { font-size: 15.5px; font-weight: 700; line-height: 1.3; text-wrap: balance; }
.gc-card-blurb { font-size: 13px; line-height: 1.5; color: var(--muted); }

/* The Topics page: five shelves of those cards. */
.gb-shelf { margin: 0 0 34px; }
/* ⚠️ Bigger than the cards below it, which it was not. A heading smaller
   than the titles it governs inverts the hierarchy and the page reads as one
   flat list of similar things. */
.gb-shelf-head {
  display: flex; align-items: center; gap: 9px;
  font-size: 19px; margin: 0 0 3px; letter-spacing: -0.01em;
}
.gb-shelf-icon { color: var(--muted); display: inline-flex; }
.gb-shelf-count {
  font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted); font-weight: 400; margin-left: auto;
}
.gb-shelf-blurb { color: var(--muted); font-size: 13px; margin: 0 0 10px; max-width: 62ch; }
.gd-text { font-size: 14.5px; line-height: 1.62; max-width: 62ch; margin: 0 0 12px; }
.gd-note {
  font-size: 13.5px; line-height: 1.55; max-width: 62ch; margin: 0 0 14px;
  padding: 9px 12px; border-left: 3px solid var(--accent); background: var(--accent-soft);
  border-radius: 0 6px 6px 0;
}
.gd-table { margin: 0 0 16px; }
.gd-table .table-wrap { overflow-x: auto; }

.dg-figure { margin: 2px 0 18px; }
.dg { display: block; width: 100%; height: auto; overflow: visible; }
/* A drawn diagram keeps its size and scrolls rather than shrinking its own
   labels out of legibility on a narrow screen. */
.dg-scroll { overflow-x: auto; overscroll-behavior-x: contain; }
.dg-scroll > .dg { min-width: 560px; }
.dg-caption { font-size: 12.5px; color: var(--muted); line-height: 1.5; max-width: 62ch; margin-top: 6px; }

.dg-hub { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 1.2; }
.dg-hub-label { fill: var(--text); font-size: 14px; font-weight: 600; }
.dg-link { fill: none; stroke: var(--border); stroke-width: 1.6; }
.dg-dot { fill: var(--accent); }
.dg-label { fill: var(--text); font-size: 13px; font-weight: 600; }
.dg-note { fill: var(--muted); font-size: 12px; }
.dg-eg { fill: var(--muted); font-size: 12.5px; }
.dg-muted { opacity: 0.8; }

.dg-axis, .dg-tick { stroke: var(--border); stroke-width: 1.4; }
.dg-axis-label { fill: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; }
.dg-span { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 1.2; }
.dg-point { fill: var(--accent); }
/* the present a perfective verb does not have, drawn as a hole */
.dg-hole { fill: var(--card); stroke: var(--muted); stroke-width: 1.3; stroke-dasharray: 3 2.5; }
.dg-hole-bar { stroke: var(--muted); stroke-width: 1.3; }

.dg-branch { fill: none; stroke: var(--border); stroke-width: 1.2; }

.dg-chain { display: flex; flex-direction: column; gap: 5px; margin: 2px 0 4px; }
.dg-chain-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13.5px; }
.dg-pill {
  min-width: 30px; text-align: center; padding: 2px 9px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--panel); font-weight: 600;
}
.dg-pill-to { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.dg-arrow { color: var(--muted); }
.dg-chain-eg { color: var(--muted); font-size: 13px; }

.dg-stack { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 2px 0 4px; padding: 0; }
.dg-slot {
  flex: 1 1 150px; display: flex; flex-direction: column; gap: 3px;
  padding: 9px 11px; border: 1px solid var(--border); border-radius: 8px; background: var(--card);
}
.dg-slot:last-child { border-color: var(--accent); background: var(--accent-soft); }
.dg-slot-n { font-size: 10.5px; color: var(--muted); letter-spacing: 0.08em; }
.dg-slot-label { font-size: 12.5px; line-height: 1.4; }
.dg-slot-eg { font-size: 13.5px; font-weight: 600; }

@media (max-width: 560px) {
  .dg-chain-row { font-size: 13px; }
  .dg-slot { flex-basis: 100%; }
}

/* Level overviews (static/js/grammarlevels.js): a short grammar list, then the
   level's whole vocabulary band. The word list is long by design, so it is
   built to be scanned and filtered rather than read. */
.lv-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 14px; }
.lv-tab {
  font-size: 13px; font-weight: 600; padding: 5px 14px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--card); color: var(--muted);
}
.lv-tab:hover { color: var(--accent); border-color: var(--accent); }
.lv-tab.is-on { color: var(--bg); background: var(--accent); border-color: var(--accent); }
.lv-head h2 { margin: 0 0 4px; }
.lv-can { color: var(--muted); font-size: 14px; line-height: 1.55; max-width: 62ch; margin: 0; }
.lv-grammar h3, .lv-vocab h3 { font-size: 14px; margin: 0 0 10px; }
.lv-points { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.lv-point { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.lv-point-link { text-decoration: none; color: inherit; display: block; }
.lv-point-link:hover .lv-point-title { color: var(--accent); }
.lv-point-title { font-size: 14px; font-weight: 600; display: block; }
.lv-point-note { color: var(--muted); font-size: 13px; line-height: 1.5; display: block; max-width: 62ch; }
.lv-point-go {
  font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted); border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px;
}
.lv-vocab-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.lv-count { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.lv-filter {
  width: 100%; margin: 0 0 10px; padding: 7px 10px; font-size: 13px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg); color: inherit;
}
.lv-words { list-style: none; margin: 0; padding: 0; max-height: 60vh; overflow-y: auto; }
.lv-word {
  display: grid; grid-template-columns: 52px minmax(96px, 150px) 46px 1fr;
  gap: 8px; align-items: baseline;
  padding: 4px 2px; border-bottom: 1px solid var(--border); font-size: 13px;
}
.lv-word-rank { color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.lv-word-head { font-weight: 600; text-decoration: none; color: inherit; }
.lv-word-head:hover { color: var(--accent); }
.lv-word-pos { color: var(--muted); font-size: 11px; }
.lv-word-gloss { color: var(--muted); line-height: 1.45; }
@media (max-width: 560px) {
  /* the gloss keeps its own line rather than squeezing into a fourth column */
  .lv-word { grid-template-columns: 44px 1fr auto; }
  .lv-word-gloss { grid-column: 1 / -1; padding-left: 52px; }
}

/* The route out of the popover's term panel into the guide topic that
   explains the term properly (server/guide.py TERM_TOPICS). */
.p-term-guide {
  display: inline-block; margin-top: 6px; font-size: 12px;
  color: var(--accent); text-decoration: none;
}
.p-term-guide:hover { text-decoration: underline; }

/* The guide as a reference: contents rail beside one topic. */
.gd-layout { display: grid; grid-template-columns: 244px 1fr; gap: 26px; align-items: start; }
.gd-layout .gd-toc {
  position: sticky; top: 12px; max-height: calc(100vh - 24px); overflow-y: auto;
  display: flex; flex-direction: column; align-items: stretch; gap: 0;
}
.gd-layout .gd-toc-link {
  display: flex; align-items: center; min-height: 44px;
  border-radius: 0 6px 6px 0; padding: 7px 9px 7px 12px; line-height: 1.3;
}
.gd-layout .gd-toc-link:hover { background: var(--card); }
.gd-layout .gd-toc-link.is-on {
  color: var(--accent); background: var(--accent-soft); font-weight: 600;
  box-shadow: inset 2px 0 0 var(--accent);
}
.gd-topic-wrap { min-width: 0; }

/* Worked examples: the Czech, the meaning, and why this one is here. */
.gd-egs { margin: 0 0 16px; }
.gd-examples { display: grid; gap: 7px; margin: 0 0 4px; }
.gd-eg {
  display: grid; grid-template-columns: minmax(140px, 1.1fr) minmax(140px, 1fr) auto;
  gap: 4px 14px; align-items: baseline;
  padding: 7px 10px; border-left: 3px solid var(--border); background: var(--card);
  border-radius: 0 6px 6px 0;
}
.gd-eg-cs { font-size: 14px; font-weight: 600; }
.gd-eg-en { font-size: 13px; color: var(--muted); }
.gd-eg-note { font-size: 12px; color: var(--muted); font-style: italic; }
@media (max-width: 720px) {
  .gd-layout { grid-template-columns: 1fr; gap: 14px; }
  .gd-layout .gd-toc { position: static; max-height: none; }
  .gd-toc-drawer {
    border: 1px solid var(--border); border-radius: 10px; background: var(--card);
    padding: 0 10px;
  }
  .gd-toc-drawer-head {
    display: flex; align-items: center; gap: 8px; width: 100%;
    background: none; border: 0; color: var(--text); font: inherit; text-align: left;
    min-height: 48px; font-size: 14.5px; font-weight: 600; cursor: pointer; padding: 0;
  }
  .gd-toc-drawer-head::after {
    content: ""; margin-left: auto; flex: none; width: 0; height: 0; opacity: 0.6;
    border-top: 5px solid currentColor;
    border-left: 4.5px solid transparent; border-right: 4.5px solid transparent;
  }
  .gd-toc-drawer.is-open > .gd-toc-drawer-head::after { transform: rotate(180deg); }
  .gd-toc-drawer.is-open > .gd-toc-drawer-head { border-bottom: 1px solid var(--border); }
  .gd-toc-drawer:not(.is-open) > .gd-toc { display: none; }
  .gd-toc-drawer > .gd-toc { padding-bottom: 8px; }
  .gd-toc-drawer-tag {
    font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted);
    flex: none;
  }
  .gd-toc-drawer-now { color: var(--accent); min-width: 0; }
  .gd-eg { grid-template-columns: 1fr; }
  .gd-eg-note { grid-column: 1; }
}

/* Previous / next through the guide in shelf order. */
.gd-steps { display: flex; gap: 10px; justify-content: space-between; margin: 14px 0 0; }
.gd-step {
  flex: 1 1 0; display: flex; flex-direction: column; gap: 2px;
  padding: 9px 12px; border: 1px solid var(--border); border-radius: 8px;
  text-decoration: none; color: inherit; background: var(--card);
}
.gd-step:hover { border-color: var(--accent); }
.gd-step-next { text-align: right; }
.gd-step-dir {
  font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted);
}
.gd-step-title { font-size: 13px; font-weight: 600; line-height: 1.35; }

/* See also: the topics a reader of this one wants next. */
.gd-see { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; margin: 18px 0 0; }
.gd-see-head {
  font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted);
}
.gd-see-link {
  font-size: 12.5px; padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--card); text-decoration: none; color: inherit;
}
.gd-see-link:hover { border-color: var(--accent); color: var(--accent); }

/* ── Grammar: one section, three tabs ────────────────────────────────────── */
/* ⚠️ These are the page's main control and they were 30px of 13.5px grey
   text with a tinted pill on the chosen one — smaller than the body copy
   underneath and easy to miss entirely. A tab that decides what the whole
   page shows has to look like something you press. */
.gd-tabs {
  display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 20px;
  border-bottom: 1px solid var(--border); padding-bottom: 12px;
}
.gd-tab {
  border: 1px solid var(--border); background: var(--card); color: var(--muted);
  border-radius: 10px; padding: 0 18px; min-height: 44px; box-sizing: border-box;
  font-size: 15px; font-weight: 600; cursor: pointer;
  display: inline-flex; align-items: center;
}
.gd-tab:hover { color: var(--text); border-color: var(--accent); }
.gd-tab.is-on {
  color: var(--card); background: var(--accent); border-color: var(--accent);
}

/* whether a verb follows its class (server/verbclass.py) */
.dc-reg {
  display: inline-flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  font-size: 12px; border-radius: 999px; padding: 3px 10px; border: 1px solid var(--border);
}
.dc-reg.is-regular { color: var(--verb); border-color: color-mix(in srgb, var(--verb) 40%, var(--border)); }
.dc-reg.is-irregular { color: var(--fem); border-color: color-mix(in srgb, var(--fem) 40%, var(--border)); }
/* Spanish pensar: a rule of its own, between the two */
.dc-reg.is-stem { color: var(--neut); border-color: color-mix(in srgb, var(--neut) 40%, var(--border)); }
.dc-reg-model { color: var(--muted); }
/* the one form a learner has to remember, marked where they will read it */
.ft-odd { color: var(--fem); }
.ft-odd span { text-decoration: underline wavy; text-underline-offset: 4px; text-decoration-thickness: 1px; }

/* a grammar chip's card, under the row of chips on a piece */
.pl-gram-cards:empty { display: none; }
.pl-gram-cards { margin: 8px 0 0; max-width: 62ch; }

/* a term's card inside a form table, and the row labels that open it */
.ft-cards:empty { display: none; }
.ft-cards { margin: 0 0 12px; }
.ft-table th[scope="row"] .term, .ft-head .term, .ft-table thead .term {
  font: inherit; background: none; border: 0; padding: 0; color: inherit;
  cursor: help; text-align: left;
  text-decoration: underline dotted; text-underline-offset: 3px;
  text-decoration-color: var(--border);
}
.ft-table th[scope="row"] .term:hover, .ft-head .term:hover, .ft-table thead .term:hover {
  color: var(--accent); text-decoration-color: currentColor;
}
/* an example in two lines: the language, then what it means */
.p-example-l { display: block; }
.p-example-e { display: block; color: var(--muted); }

/* the landing: what is in here, on one screen */
.gb-search { max-width: 34ch; margin: 0 0 20px; }
.gb-lede { color: var(--muted); font-size: 13.5px; margin: 0 0 20px; max-width: 62ch; }
.gb-tools { border-top: 1px solid var(--border); padding-top: 20px; margin-top: 4px; }

/* the contents rail: one shelf open, the rest closed */
.gd-toc-group { border: none; }
/* a barrier between shelves. Seven headings separated by 10px of air read as
   one paragraph; separated by a line they read as seven doors. */
.gd-toc-group + .gd-toc-group { border-top: 1px solid var(--border); }
.gd-toc-group > summary {
  display: flex; align-items: center; gap: 9px;
  cursor: pointer; list-style: none; padding: 9px 9px; border-radius: 6px;
  min-height: 42px;
  font-size: 14.5px; font-weight: 600; line-height: 1.25; color: var(--text);
}
.gd-toc-group > summary::-webkit-details-marker { display: none; }
/* the caret is the only thing on the row that says a heading opens */
.gd-toc-group > summary::before {
  content: ""; flex: none; width: 0; height: 0; opacity: 0.5;
  border-left: 5px solid currentColor;
  border-top: 4.5px solid transparent; border-bottom: 4.5px solid transparent;
}
.gd-toc-group[open] > summary::before { transform: rotate(90deg); opacity: 0.9; }
@media (prefers-reduced-motion: no-preference) {
  .gd-toc-group > summary::before { transition: transform 140ms ease; }
}
.gd-toc-group[open] > summary { color: var(--accent); }
.gd-toc-group > summary:hover { background: var(--card); }
.gd-toc-title { flex: 1 1 auto; min-width: 0; }
/* ⚠️ The count is a size cue for a shelf you cannot see into. Once the shelf
   is open its topics are listed right underneath, so the number stops being
   information and becomes one more thing to read past. */
.gd-toc-n {
  flex: none; font-size: 11.5px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.gd-toc-group[open] > summary .gd-toc-n { display: none; }
/* the box that makes forty topics findable. A reader who wants the negative
   should not have to know which of six shelves somebody filed it on. */
.gd-toc-search {
  font: inherit; font-size: 13.5px; color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: 9px;
  height: 40px; padding: 0 10px; width: 100%; margin: 0 0 6px;
}
.gd-toc-search:focus-visible { border-color: var(--accent); outline: none; }
.gd-toc-none { font-size: 13px; color: var(--muted); padding: 8px 9px; margin: 0; }

/* The rail is a drawer on a phone (see static/js/views/guide.js) and a plain
   rail above 720px, where its head simply is not there.

   ⚠️ A min-width query, not a bare rule. The phone styles live in the
   max-width block further up this file, so a bare `display: none` here — same
   specificity, later in the source — won every time and the drawer had no
   handle at all on a phone. Two mutually exclusive queries cannot race. */
@media (min-width: 721px) {
  .gd-toc-drawer-head { display: none; }
}

/* the open shelf's topics hang off a rule, so nesting is shown rather than
   implied by an indent the eye has to measure */
.gd-toc-links {
  display: flex; flex-direction: column; gap: 0;
  padding: 0 0 8px; margin-left: 14px; border-left: 1px solid var(--border);
}
/* ⚠️ load-bearing. Giving a direct child of <details> an explicit display
   overrides the UA rule that hides it while the element is closed, so
   every shelf stayed expanded and the rail was still 38 flat links. */
.gd-toc-group:not([open]) > .gd-toc-links { display: none; }

/* show first, explain after */
.gd-more { margin: 14px 0 0; border-top: 1px solid var(--border); padding-top: 12px; }
.gd-more > summary {
  cursor: pointer; list-style: none; display: flex; align-items: baseline; gap: 8px;
  font-size: 13px; font-weight: 600; color: var(--accent);
}
.gd-more > summary::-webkit-details-marker { display: none; }
.gd-more > summary::before { content: "▸"; font-size: 11px; }
.gd-more[open] > summary::before { content: "▾"; }
.gd-more-n { font-weight: 400; color: var(--muted); font-size: 11.5px; }
.gd-more-body { margin: 10px 0 0; }

/* ── Guide widgets ──────────────────────────────────────────── */
/* A topic's one panel you can touch (static/js/guidewidgets/common.js). It has
   to LOOK operable from across the page, because a reader scrolling a grammar
   article does not expect anything on it to answer back — so it is a card on
   the panel ground while the prose around it sits on the page ground, and its
   controls are the only filled shapes in the topic. */
.gd-widget { margin: 2px 0 18px; }
/* Room for the panel before its module arrives, so the article does not grow
   under a reader who has already scrolled past where it goes. Measured at
   desktop width; a little short on a phone, which still beats nothing. */
.gd-widget:empty { min-height: 290px; }
.gd-widget[data-name="secondposition"]:empty { min-height: 400px; }
.gd-widget[data-name="negate"]:empty { min-height: 280px; }
.gw {
  display: flex; flex-direction: column; gap: 10px;
  max-width: 62ch; padding: 14px 16px 16px;
  border: 1px solid var(--border); border-radius: 14px;
  background: var(--card); box-shadow: var(--shadow);
}
.gw-head { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.gw-how { margin: -6px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); }

/* the word: chips to start from, and the box that is the actual point */
.gw-words { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.gw-word {
  font: inherit; font-size: 13.5px; cursor: pointer;
  padding: 4px 11px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
}
.gw-word:hover { border-color: var(--accent); color: var(--accent); }
.gw-word.is-on {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 600;
}
.gw-word:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gw-input {
  font: inherit; font-size: 13.5px; color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: 999px;
  height: 30px; padding: 0 12px; flex: 1 1 170px; min-width: 0;
}
.gw-input:focus-visible { border-color: var(--accent); outline: none; }

/* the slot: cases, persons, tenses */
.gw-slots { display: flex; flex-wrap: wrap; gap: 4px; }
/* ⚠️ load-bearing. The conjugator swaps its persons row for a genders row
   with the `hidden` attribute, and `display: flex` above beats the UA rule
   that hides it — without this both rows show at once and the past tense
   offers "I" for a form that agrees for gender. */
.gw-slots[hidden] { display: none; }
.gw-slot {
  font: inherit; font-size: 12.5px; cursor: pointer;
  padding: 3px 9px; border-radius: 7px;
  border: 1px solid transparent; background: none; color: var(--muted);
}
.gw-slot:hover { color: var(--text); background: var(--panel); }
.gw-slot.is-on {
  color: var(--accent); background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 35%, transparent); font-weight: 600;
}
.gw-slot:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* the answer */
.gw-answers { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.gw-answer-slot { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.gw-answer-label {
  font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted);
}
/* flex: 1 so singular and plural are the same height — only one of them
   carries the "what this case is for" line, and without this the pair sat at
   two different heights and read as two unrelated answers. */
.gw-answer {
  display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 auto;
  padding: 9px 12px 10px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--bg);
}
.gw-answer-top { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; }
.gw-answer-word {
  font-family: var(--serif); font-size: 24px; font-weight: 700; line-height: 1.2;
  overflow-wrap: anywhere;
}
/* an answer that is not there says so quietly rather than shouting a dash */
.gw-answer-word.is-missing { font-size: 20px; font-weight: 400; color: var(--muted); }
.gw-answer-note { margin: 0; font-size: 12px; line-height: 1.45; color: var(--muted); }
.gw-answer-note:empty { display: none; }
.gw-say { flex: none; }
.gw-say[hidden] { display: none; }

/* the line under it: why this form is what it is */
.gw-pattern { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.gw-pattern:empty { display: none; }
/* whether the verb keeps its class — the same verdict, and the same two
   colours, the dictionary page shows beside the headword (.dc-reg) */
.gw-verdict {
  margin: 0; align-self: start; font-size: 12.5px;
  padding: 3px 10px; border-radius: 999px; border: 1px solid var(--border);
}
.gw-verdict:empty { display: none; }
.gw-verdict.is-regular { color: var(--verb); border-color: color-mix(in srgb, var(--verb) 40%, var(--border)); }
.gw-verdict.is-irregular { color: var(--fem); border-color: color-mix(in srgb, var(--fem) 40%, var(--border)); }
.gw-verdict.is-stem { color: var(--neut); border-color: color-mix(in srgb, var(--neut) 40%, var(--border)); }

/* A sentence you can operate: negate.js switches a word between its two
   spellings in place, secondposition.js drops a queue of short words into a
   gap. Both put the change INSIDE the sentence rather than beside it, so what
   a reader is changing and what they are reading are the same object. */
.gw-sentence {
  margin: 2px 0 0; font-family: var(--serif); font-size: 19px; line-height: 2.1;
  color: var(--text);
}
.gw-tok {
  font: inherit; color: inherit; padding: 1px 3px; border: 0; background: none;
  border-bottom: 1px dashed var(--muted); cursor: pointer; border-radius: 4px;
}
.gw-tok:hover { color: var(--accent); border-bottom-color: var(--accent); }
.gw-tok:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* ⚠️ accent-soft, not the red this file uses elsewhere for "irregular".
   A negated word is not a mistake — it is the marked choice — and colouring
   it red teaches a beginner that every negative sentence is an error. */
.gw-tok.is-neg {
  background: var(--accent-soft); color: var(--accent); font-weight: 600;
  border-bottom-color: transparent;
}
/* a word the reader cannot change: part of the sentence, not part of the
   exercise, so it carries no affordance at all */
.gw-tok.is-fixed { border-bottom: 0; cursor: auto; padding: 0; }
.gw-tok.is-fixed:hover { color: inherit; }
.gw-meaning { margin: 0; font-size: 14px; line-height: 1.55; color: var(--muted); }
.gw-meaning:empty { display: none; }
.gw-tally {
  margin: 0; flex: none; font-size: 12px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.gw-verdict-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.gw-verdict.is-neutral { color: var(--muted); }

/* the queue: a gap in the sentence, and the words waiting to go into it */
.gw-gap {
  font: inherit; cursor: pointer; margin: 0 1px; padding: 0 5px;
  min-width: 20px; border-radius: 7px;
  border: 1px dashed var(--border); background: none; color: var(--text);
}
.gw-gap:hover { border-color: var(--accent); background: var(--panel); }
.gw-gap:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.gw-gap.is-here { border-style: solid; border-color: var(--accent); background: var(--accent-soft); }
.gw-gap.has-words { padding: 0 7px; }
.gw-gap-mark { color: var(--muted); font-size: 13px; }
.gw-gap .gw-tok.is-clitic { color: var(--accent); font-weight: 600; border-bottom: 0; padding: 0; }
.gw-pool { display: flex; flex-wrap: wrap; gap: 6px; }
.gw-clitic {
  font: inherit; font-size: 13.5px; cursor: pointer;
  padding: 3px 11px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
}
.gw-clitic:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.gw-clitic:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* placed, and still tappable — tapping it takes it back out of the queue */
.gw-clitic.is-down { opacity: 0.55; text-decoration: line-through; }
.gw-clitic:disabled { opacity: 0.45; cursor: default; }

@media (max-width: 480px) {
  .gw { padding: 12px 13px 14px; }
  .gw-answers { grid-template-columns: 1fr; }
  .gw-sentence { font-size: 17px; }
}

/* ── your place in the guide ─────────────────────────────────────────────── */
/* A read topic keeps its card and gains a tick in the corner — the page
   looks different on the second visit, which is the whole point. */
.gc-card-check {
  position: absolute; top: 12px; right: 12px; display: inline-flex;
  width: 20px; height: 20px; border-radius: 50%; align-items: center; justify-content: center;
  background: var(--verb); color: var(--on-accent);
}
.gc-card.is-read .gc-card-title { color: var(--muted); }
.gc-card.is-read .gc-card-icon { opacity: 0.6; }

/* the first step, at the top of Browse */
.gb-next { margin: 0 0 22px; display: flex; flex-direction: column; gap: 10px; }
.gb-next-cards { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.gb-next-card { min-height: 120px; padding-top: 13px; }
.gb-next-card.is-next { border-left-color: var(--accent); }
.gb-next-card.is-back { border-left-color: var(--neut); }
.gb-next-card .gc-card-icon { display: none; }
.gb-next-label {
  font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase; font-weight: 600;
  color: var(--accent);
}
.gb-next-card.is-back .gb-next-label { color: var(--neut); }
.gb-next-card .gc-card-title { font-size: 18px; }
.gb-next-meta {
  display: flex; gap: 8px; align-items: center; margin-top: auto; padding-top: 4px;
  font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.gb-next-level {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em;
  padding: 1px 6px; border-radius: 5px; border: 1px solid var(--border);
}
.gb-next-done { margin: 0; font-size: 13.5px; color: var(--muted); }
.gb-progress { display: flex; align-items: center; gap: 12px; }
.gb-progress-bar { flex: 1 1 auto; height: 4px; border-radius: 2px; background: var(--border); overflow: hidden; max-width: 320px; }
.gb-progress-fill { display: block; height: 100%; background: var(--verb); border-radius: 2px; }
.gb-progress-text { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* a shelf folded on a phone: the summary IS the shelf heading */
details.gb-shelf-fold { margin: 0 0 12px; border-top: 1px solid var(--border); padding-top: 12px; }
details.gb-shelf-fold > summary { cursor: pointer; list-style: none; }
details.gb-shelf-fold > summary::-webkit-details-marker { display: none; }
details.gb-shelf-fold > summary .gb-shelf-count::after { content: " ▸"; }
details.gb-shelf-fold[open] > summary .gb-shelf-count::after { content: " ▾"; }
details.gb-shelf-fold > .gb-shelf-blurb { margin-top: 6px; }
details.gb-shelf-fold > .gc-grid { margin-bottom: 8px; }

/* the rail: a tick after a read topic, drawn for all and shown for those */
.gd-toc-link { display: flex; align-items: center; gap: 6px; }
.gd-toc-text { flex: 1 1 auto; min-width: 0; }
.gd-toc-check { display: none; color: var(--verb); flex: none; }
.gd-toc-link.is-read .gd-toc-check { display: inline-flex; }
.gd-toc-link.is-read:not(.is-on) { color: var(--muted); }

/* the foot of a topic: where THIS learner goes next */
.gd-end { height: 1px; }
.gd-next {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  margin: 18px 0 0; padding: 12px 14px; border-radius: 10px;
  background: var(--accent-soft); border-left: 3px solid var(--accent);
}
.gd-next-label {
  font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase; font-weight: 600;
  color: var(--accent);
}
.gd-next-link { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; text-decoration: none; color: var(--text); min-width: 0; }
.gd-next-link:hover .gd-next-title { color: var(--accent); }
.gd-next-title { font-size: 15px; font-weight: 700; }
.gd-next-meta { font-size: 12px; color: var(--muted); }
.gd-next-done { font-size: 13.5px; color: var(--muted); }

/* ── Try it: three questions at the foot of a topic ────────────────────────── */
.gd-try-slot:empty { display: none; }
.gd-try {
  margin: 22px 0 0; padding: 16px 18px 18px; max-width: 62ch;
  border: 1px solid var(--border); border-radius: 14px; background: var(--card);
}
.gd-try-head { margin: 0; font-size: 16px; font-weight: 700; }
.gd-try-how { margin: 3px 0 14px; font-size: 12.5px; color: var(--muted); line-height: 1.5; }
.gd-try-list { display: flex; flex-direction: column; gap: 18px; }
.gd-try-q { display: flex; flex-direction: column; gap: 6px; }
.gd-try-n { margin: 0; font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.gd-try-cs { margin: 0; font-family: var(--serif); font-size: 19px; line-height: 1.5; }
.gd-try-blank { display: inline-block; min-width: 3.2em; border-bottom: 2px solid var(--accent); color: transparent; }
.gd-try-mark { background: var(--accent-soft); color: var(--accent); padding: 0 4px; border-radius: 4px; font-weight: 600; }
.gd-try-en { margin: 0; font-size: 13.5px; color: var(--muted); }
.gd-try-choices { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.gd-try-choice {
  font: inherit; font-size: 14px; cursor: pointer; padding: 6px 13px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text); min-height: 36px;
}
.gd-try-choice:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.gd-try-choice:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gd-try-choice:disabled { cursor: default; opacity: 0.55; }
/* the answer stays legible when the rest fade; a wrong pick is marked, not hidden */
.gd-try-choice.is-answer, .gd-try-choice.is-right { opacity: 1; border-color: var(--verb); color: var(--verb); font-weight: 600; }
.gd-try-choice.is-wrong { opacity: 1; border-color: var(--fem); color: var(--fem); text-decoration: line-through; }
.gd-try-why:empty { display: none; }
.gd-try-why { display: flex; flex-direction: column; gap: 3px; margin-top: 2px; }
.gd-try-verdict { margin: 0; font-size: 13.5px; font-weight: 600; }
.gd-try-verdict.is-right { color: var(--verb); }
.gd-try-verdict.is-wrong { color: var(--fem); }
.gd-try-reason { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.5; }
.gd-try-reason .term { font-size: 13px; }
.gd-try-result:empty { display: none; }
.gd-try-result { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--border); }
.gd-try-score { margin: 0; font-size: 14px; font-weight: 600; }

/* ── Keep this, and grammar on Today ──────────────────────────────────── */
.gd-keep {
  margin: 4px 0 16px; max-width: 62ch; padding: 12px 16px; border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--verb) 45%, var(--border));
  background: color-mix(in srgb, var(--verb) 7%, var(--card));
}
.gd-keep-label {
  display: block; font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 700; color: var(--verb); margin-bottom: 4px;
}
.gd-keep-text { margin: 0; font-size: 15px; line-height: 1.55; font-weight: 500; }

.td-grammar { margin: 18px 0 0; }
.td-grammar-card {
  border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px;
  background: var(--card); display: flex; flex-direction: column; gap: 8px;
}
.td-rule { margin: 0; font-size: 16px; line-height: 1.5; font-weight: 600; max-width: 62ch; }
.td-rule-eg {
  margin: 0; display: flex; flex-direction: column; gap: 1px;
  padding-left: 10px; border-left: 2px solid var(--border);
}
.td-rule-cs { font-family: var(--serif); font-size: 15px; }
.td-rule-en { font-size: 12.5px; color: var(--muted); }
.td-rule-link { display: inline-flex; gap: 6px; align-items: baseline; font-size: 13px; text-decoration: none; color: var(--accent); }
.td-rule-link:hover .td-rule-title { text-decoration: underline; }
.td-rule-title { color: var(--text); font-weight: 600; }
.td-grammar-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  margin-top: 4px; padding-top: 10px; border-top: 1px solid var(--border);
}
.td-next {
  display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; text-decoration: none; color: var(--text);
  padding: 6px 10px 6px 12px; border-radius: 9px; border: 1px solid var(--border); background: var(--bg);
}
.td-next:hover { border-color: var(--accent); }
.td-next .icon { color: var(--muted); }
.td-next-label { font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase; font-weight: 700; color: var(--accent); }
.td-next-title { font-weight: 600; font-size: 14px; }
.td-next-meta { font-size: 12px; color: var(--muted); }
.td-grammar-count { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ── See it in a story ────────────────────────────────────────────────────── */
.gd-stories-slot:empty { display: none; }
.gd-stories { margin: 18px 0 0; max-width: 62ch; }
.gd-stories-head { margin: 0; font-size: 15px; font-weight: 700; }
.gd-stories-how { margin: 2px 0 10px; font-size: 12.5px; color: var(--muted); }
.gd-stories-list { display: flex; flex-direction: column; gap: 6px; }
.gd-story {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: 10px; text-decoration: none; color: var(--text);
  border: 1px solid var(--border); background: var(--card); min-height: 44px;
}
.gd-story:hover { border-color: var(--accent); }
.gd-story:hover .gd-story-title { color: var(--accent); }
.gd-story-icon { color: var(--muted); display: inline-flex; }
.gd-story-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.gd-story-title { font-weight: 600; font-size: 14px; line-height: 1.3; }
.gd-story-meta { font-size: 12px; color: var(--muted); }
.gd-story-tag {
  font-size: 11px; color: var(--muted); padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--border); white-space: nowrap; max-width: 14ch; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 480px) {
  .gd-story { grid-template-columns: auto 1fr; }
  .gd-story-tag { display: none; }
}

/* ── the form you typed, found in the table ─────────────────────────────────────── */
.dc-form-line { margin: 0 0 10px; font-size: 14px; color: var(--muted); }
.dc-form-line strong { color: var(--text); font-size: 16px; }
.dc-form-line.is-missing { color: var(--fem); }
/* the second word a form belongs to (Spanish fue: ser, also ir) */
.dc-form-also .linklike {
  background: none; border: 0; padding: 0; font: inherit; color: var(--accent);
  text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
.dc-form-also .linklike:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ft-hit {
  background: color-mix(in srgb, var(--accent) 16%, var(--card));
  box-shadow: inset 0 0 0 2px var(--accent); border-radius: 6px; font-weight: 700;
  animation: ft-hit-in 900ms ease-out;
}
.ft-also { font-weight: 700; color: var(--accent); }
@keyframes ft-hit-in {
  0% { background: color-mix(in srgb, var(--accent) 42%, var(--card)); }
  100% { background: color-mix(in srgb, var(--accent) 16%, var(--card)); }
}
@media (prefers-reduced-motion: reduce) { .ft-hit { animation: none; } }

/* ── Word of the day ─────────────────────────────────────────────────────── */
/* On Today it is a card you are handed; on the dictionary it is a line at the
   foot you can close. It used to be a large filled panel above the dictionary
   search box, which put the reason people opened that page third. */
.td-wotd { margin: 18px 0 0; }
.wotd-card {
  border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px;
  background: var(--card); display: flex; flex-direction: column; gap: 6px;
}
.wotd-tag {
  font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted);
}
.wotd-word { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.wotd-headword {
  border: none; background: none; padding: 0; color: var(--text);
  font-size: 22px; font-weight: 700; line-height: 1.2;
}
.wotd-headword:hover { color: var(--accent); }
.wotd-gloss { margin: 0; font-size: 13px; color: var(--muted); }
.wotd-eg {
  margin: 2px 0 0; display: flex; flex-direction: column; gap: 1px;
  padding-left: 10px; border-left: 2px solid var(--border);
}
.wotd-eg-cs { font-size: 13.5px; }
.wotd-eg-en { font-size: 12.5px; color: var(--muted); }
.wotd-actions { display: flex; gap: 8px; flex-wrap: wrap; margin: 4px 0 0; }

/* the dictionary's closeable footer line */
.wotd-bar {
  position: sticky; bottom: 0; z-index: 2;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 24px 0 0; padding: 9px 12px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card);
}
.wotd-bar-tag {
  font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted);
}
.wotd-bar-word {
  border: none; background: none; padding: 0; color: var(--text);
  font-size: 15px; font-weight: 700;
}
.wotd-bar-word:hover { color: var(--accent); }
.wotd-bar-gloss { font-size: 12.5px; color: var(--muted); flex: 1 1 auto; min-width: 0; }
.wotd-bar-close {
  border: none; background: none; color: var(--muted); font-size: 18px;
  line-height: 1; padding: 2px 6px; border-radius: 6px;
}
.wotd-bar-close:hover { color: var(--text); background: var(--bg); }

/* ── the phrasebook, as chips ────────────────────────────────────────────── */
.dc-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 14px; }
.dc-chip {
  display: inline-flex; align-items: baseline; gap: 6px;
  border: 1px solid var(--border); background: var(--card); color: var(--muted);
  border-radius: 999px; padding: 5px 12px; font-size: 12.5px;
}
.dc-chip:hover { color: var(--text); border-color: var(--accent); }
.dc-chip.is-on {
  color: var(--accent); border-color: var(--accent); background: var(--accent-soft); font-weight: 600;
}
.dc-chip .dc-count { font-size: 11px; font-variant-numeric: tabular-nums; }

/* One real sentence inside the reading popover, and a button for another. */
.p-eg {
  display: grid; grid-template-columns: 1fr auto; gap: 1px 8px;
  margin: 8px 0 0; padding: 7px 9px;
  border-left: 2px solid var(--border); background: var(--bg); border-radius: 0 6px 6px 0;
}
.p-eg-label {
  grid-column: 1 / -1;
  font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted);
}
.p-eg-cs { font-size: 12.5px; }
.p-eg-en { font-size: 11.5px; color: var(--muted); grid-column: 1; }
.p-eg-more {
  grid-row: 2 / 4; grid-column: 2; align-self: center;
  border: 1px solid var(--border); background: var(--card); color: var(--muted);
  border-radius: 6px; padding: 3px 5px; display: inline-flex;
}
.p-eg-more:hover { color: var(--accent); border-color: var(--accent); }

/* ── card discipline ─────────────────────────────────────────────────────── */
/* A topic is a page of writing, not an object to act on. Boxing 500 words in
   a filled, bordered, shadowed rounded rectangle made every explanation look
   like a control panel and left the tables and examples inside it with no
   weight of their own to spend. */
.gd-topic.card {
  background: none; border: none; box-shadow: none;
  border-radius: 0; padding: 0;
}
.gd-topic h2 { font-size: 25px; line-height: 1.25; margin: 0 0 6px; text-wrap: balance; }
.gd-topic .gd-blurb { font-size: 14.5px; color: var(--muted); margin: 0 0 18px; max-width: 62ch; }
.gd-text, .gd-topic .gd-text { max-width: 62ch; }

/* the look-up panels keep their frame: you type into those */
.gr-section.gd-topic { padding: 0; }

/* the level word list is a tool; its two prose halves above it are not */
.lv-head h2 { font-size: 25px; }
.lv-can { color: var(--muted); max-width: 62ch; }
.lv-grammar { margin: 20px 0; }

/* a word page's blocks sit on the page; the sentence inside one is the object */
.dc-block { border: none; background: none; padding: 0; margin: 18px 0 0; }
.dc-block h4 {
  font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase; margin: 0 0 2px;
}

/* Under the word: Examples and Thesaurus, rather than three stacked sections
   and a fourth browsable one at the foot of the page. */
.dc-tabbed { margin: 16px 0 0; }
.dc-tabs { display: flex; gap: 4px; margin: 0 0 12px; border-bottom: 1px solid var(--border); }
.dc-tab {
  border: none; background: none; color: var(--muted);
  padding: 7px 12px; font-size: 13px; font-weight: 600;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.dc-tab:hover { color: var(--text); }
.dc-tab.is-on { color: var(--accent); border-bottom-color: var(--accent); }
.dc-thes-pane > .dc-block + .dc-block { margin-top: 16px; }

/* ── Grammar, where it actually happens ──────────────────────────────────── */
/* The grammar section explains thirty-four things and sat in its own corner
   while the lessons demonstrating them said nothing. These labels are read off
   the analyser features already baked into every line, so the whole library
   got them at once; they open the topic that explains them. */
.pl-gram { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 8px; margin: 10px 0 0; }
.pl-gram-head {
  font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted);
}
.pl-gram-chip {
  display: inline-flex; align-items: baseline; gap: 5px;
  border: 1px solid var(--border); background: var(--card); color: var(--muted);
  border-radius: 999px; padding: 3px 10px; font-size: 12px;
}
.pl-gram-chip:hover { color: var(--accent); border-color: var(--accent); }
.pl-gram-n { font-size: 11px; font-variant-numeric: tabular-nums; }

.rl-gram { display: flex; flex-wrap: wrap; gap: 5px; margin: 4px 0 0; grid-column: 2; }
.rl-gram-chip {
  border: none; background: none; color: var(--muted);
  font-size: 11px; padding: 1px 7px; border-radius: 999px;
  border: 1px dashed var(--border);
}
.rl-gram-chip:hover { color: var(--accent); border-color: var(--accent); border-style: solid; }
.read-lines.grammar-off .rl-gram { display: none; }
/* Chinese with the pinyin turned off: the characters alone (tokens.js ruby) */
.read-lines.readings-off rt, .read-lines.readings-off rp { display: none; }

/* ── senses, numbered ────────────────────────────────────────────────────── */
/* glosses is a LIST and was being joined into one line: "dát" carries five
   meanings and they arrived as a semicolon soup in which none was findable. */
.dc-senses { margin: 4px 0 0; padding-left: 20px; font-size: 14.5px; line-height: 1.5; max-width: 64ch; }
.dc-senses li { margin: 5px 0; }
.dc-senses li::marker { color: var(--muted); font-size: 12px; }
/* the word, then what separates this sense from the next one */
.dc-sense-row { display: flex; flex-direction: column; gap: 1px; max-width: 64ch; }
p.dc-sense-row, .dc-entry > .dc-sense-row { margin: 4px 0 0; font-size: 14.5px; }
/* the list item itself, so the number survives: see inList() in dictionary.js */
.dc-sense-li { margin: 5px 0; }
.dc-sense-word { font-size: 14.5px; }
/* two senses translating to the same word are told apart by the note alone */
.dc-sense-word.is-shared { font-weight: 600; }
.dc-sense-note { font-size: 12.5px; color: var(--muted); line-height: 1.45; }
/* The qualifier the source writes in front of a sense — "(relational) rain",
   "to start, to begin (reflexive with se)". It sits above the word rather
   than after it because it is read first: it says which of the meanings this
   is, and with five senses on `dát` that is the only way through the list. */
.dc-sense-qual {
  font-size: 10.5px; color: var(--accent); text-transform: uppercase;
  letter-spacing: 0.05em; font-weight: 600;
}
/* the word doing its job, which is worth more than another line about it */
.dc-sense-ex {
  display: flex; flex-direction: column; gap: 1px;
  margin: 3px 0 1px; padding-left: 9px; border-left: 2px solid var(--border);
}
.dc-sense-ex-l { font-size: 13.5px; }
.dc-sense-ex-t { font-size: 12.5px; color: var(--muted); }

/* ── the part of speech, as a way in ─────────────────────────────────────── */
.dc-pos-btn {
  border: none; background: none; padding: 0; cursor: pointer;
  border-bottom: 1px dotted var(--border); color: var(--muted);
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em;
}
.dc-pos-btn:hover { color: var(--accent); border-bottom-color: var(--accent); }
.dc-poscard {
  position: relative; margin: 8px 0 0; padding: 11px 32px 11px 13px;
  border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: 0 8px 8px 0; background: var(--card); max-width: 58ch;
}
.dc-poscard p { margin: 4px 0 0; font-size: 13px; color: var(--muted); line-height: 1.5; }
.dc-poscard-title {
  border: none; background: none; padding: 0; color: var(--accent);
  font-size: 14px; font-weight: 700; text-align: left;
}
.dc-poscard-title:hover { text-decoration: underline; }
.dc-poscard-go { font-weight: 400; }
.dc-poscard-close {
  position: absolute; top: 6px; right: 8px; border: none; background: none;
  color: var(--muted); font-size: 16px; line-height: 1; padding: 2px 5px; border-radius: 5px;
}
.dc-poscard-close:hover { color: var(--text); background: var(--bg); }

/* ── form tables ─────────────────────────────────────────────────────────── */
.ft-section + .ft-section { margin-top: 18px; }
.ft-head {
  font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 6px; font-weight: 600;
}
.ft-table th[scope="row"] { color: var(--muted); font-weight: 500; white-space: nowrap; }
.ft-table td { font-weight: 600; }
/* a second form of one slot says what sets it apart: tebe stressed / tě clitic */
.ft-q { margin-left: 4px; font-size: 11px; font-weight: 400; color: var(--muted); }
/* what no table cell asks for, closed until it is wanted */
.ft-more { margin-top: 18px; }
.ft-more > summary {
  cursor: pointer; font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--muted); font-weight: 600; margin-bottom: 6px;
}
.ft-more > summary:hover { color: var(--text); }
.ft-more th[scope="row"] { white-space: normal; }

/* Every word of a class, under the topic that explains the class. */
.gd-words { margin: 26px 0 0; border-top: 1px solid var(--border); padding-top: 18px; }
.gd-words-head { font-size: 14px; margin: 0 0 10px; }
.gd-words-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 2px 14px; }
.gd-word {
  display: flex; align-items: baseline; gap: 8px; padding: 4px 6px;
  border-radius: 6px; text-decoration: none; color: inherit; min-width: 0;
}
.gd-word:hover { background: var(--card); }
.gd-word-lemma { font-weight: 600; font-size: 13.5px; white-space: nowrap; }
.gd-word-gloss {
  font-size: 12px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gd-words-more { margin: 14px 0 0; }

/* A search that found nothing is still a page. */
.dc-nothing-list { margin: 6px 0 12px; padding-left: 20px; font-size: 13px; color: var(--muted); }
.dc-nothing-list li { margin: 3px 0; }

/* Definitions in the language being learned, under the translation. */
.dc-defs { margin: 9px 0 0; max-width: 64ch; padding-left: 10px; border-left: 2px solid var(--border); }
.dc-defs-head {
  margin: 0; font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--muted);
}
.dc-defs-list {
  margin: 6px 0 0; padding-left: 20px; font-size: 13px; line-height: 1.5; color: var(--muted);
}
.dc-defs-list li { margin: 3px 0; }
.dc-defs-tag { font-size: 10.5px; font-style: italic; margin-left: 6px; opacity: 0.8; }

/* ── the course: what to do now, in three options ───────────────────────────
   static/js/views/course.js. Three choices are the page; the rest of the plan
   is two hundred rows the reader did not come for, under closed level cards.

   ⚠️ Everything here is sized to be HIT, not just seen. The first version had
   14px grey rows and cards with no affordance at all, which is a problem
   before it is a style: a control you cannot tell is a control, or cannot land
   a thumb on, is not accessible to anybody having a bad day on a phone. */
/* ⚠️ ONE column width for the whole page. The three choice cards used to run
   wider than the progress card and the level cards above and below them, so
   three stacked groups had three different right edges — which reads as
   carelessness even to somebody who could not say why. */
.co { max-width: 62ch; }
.co-head h2 { margin: 0 0 4px; }
.co-why { margin: 0 0 18px; color: var(--muted); font-size: 14.5px; }

/* the level a reader is actually in, which is the honest unit of progress */
.co-bar { margin: 0 0 22px; }
.co-now {
  border: 1px solid var(--border); border-left: 4px solid var(--lv, var(--accent));
  border-radius: 12px; padding: 14px 16px; background: var(--card);
}
.co-now-top { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.co-now-title { font-size: 16px; font-weight: 700; }
.co-now-pct {
  margin-left: auto; font-size: 20px; font-weight: 700;
  color: var(--lv, var(--accent)); font-variant-numeric: tabular-nums;
}
.co-now-left { margin: 8px 0 0; font-size: 13px; color: var(--muted); }
.co-track { height: 10px; border-radius: 999px; background: var(--border); overflow: hidden; }
.co-track-sm { height: 6px; display: block; width: 100%; }
.co-fill { display: block; height: 100%; background: var(--lv, var(--accent)); border-radius: 999px; }
.co-foot { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-top: 10px; }
.co-count { font-size: 12.5px; color: var(--muted); }

/* days in a row — only ever shown from two, see streakChip() */
.co-streak {
  display: inline-flex; align-items: baseline; gap: 6px; margin-left: auto;
  padding: 4px 11px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--card);
}
.co-streak.is-today { border-color: var(--lv, var(--accent)); }
.co-streak-n { font-size: 16px; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.co-streak-l { font-size: 12px; color: var(--muted); }

/* Stacked and large, for the reason the dictionary's candidates are: if you
   have to open all three to find out which you want, it was not a choice. */
/* The ways in that are not reading (static/js/views/course.js startHere).

   Deliberately quieter than the choice cards below it: this is the part a
   learner leaves behind, and it must not compete with the piece they are
   being pointed at. A panel rather than three more cards, so the page still
   has one obvious next thing on it. */
.co-start {
  border: 1px solid var(--border); border-radius: 14px;
  background: var(--card); padding: 18px 18px 16px; margin: 0 0 22px;
}
.co-start-h { margin: 0 0 6px; font-size: 16px; }
.co-start-why { margin: 0 0 14px; font-size: 13.5px; color: var(--muted); line-height: 1.55; max-width: 60ch; }
.co-start-list { display: flex; flex-direction: column; gap: 8px; }
.co-step {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  cursor: pointer; font-family: inherit; color: inherit;
  border: 1px solid var(--border); border-radius: 12px; background: var(--bg);
  padding: 12px 14px; min-height: 56px;
  transition: border-color 120ms;
}
.co-step:hover, .co-step:focus-visible { border-color: var(--accent); }
.co-step-icon { display: inline-flex; flex: none; color: var(--accent); }
.co-step-body { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.co-step-title { font-size: 15px; font-weight: 700; line-height: 1.3; }
.co-step-blurb { font-size: 13px; color: var(--muted); line-height: 1.45; }
/* ⚠️ A done step is dimmed, never struck through or hidden: it stays somewhere
   the learner can go back to, and a list that empties itself as you work is a
   chore list. The word rides with the tick for anyone who cannot see it. */
.co-step.is-done { opacity: 0.82; }
.co-step.is-done .co-step-icon { color: var(--muted); }
.co-step-done {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  font-size: 12px; font-weight: 600; color: var(--muted);
}
.co-start-then { margin: 14px 0 0; font-size: 13px; color: var(--muted); }

.co-choices { display: flex; flex-direction: column; gap: 12px; margin-bottom: 30px; }
.co-card {
  display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  cursor: pointer; font-family: inherit; color: inherit;
  border: 1px solid var(--border); border-left: 4px solid var(--lv, var(--border));
  border-radius: 14px; background: var(--card);
  padding: 18px 18px 18px 20px; min-height: 84px;
  transition: border-color 120ms, transform 120ms;
}
.co-card:hover, .co-card:focus-visible { border-color: var(--accent); }
.co-card:hover { transform: translateY(-1px); }
.co-card:active { transform: translateY(0); }
/* the one that is actually next reads as the primary action */
.co-card.is-next { border-width: 1px 1px 1px 5px; box-shadow: 0 1px 0 var(--border); }
.co-card.is-next .co-card-title { font-size: 20px; }
.co-card-body { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
.co-card-n {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em;
  font-weight: 700; color: var(--muted);
}
.co-card.is-next .co-card-n { color: var(--lv, var(--accent)); }
.co-card-title { font-size: 17.5px; font-weight: 700; line-height: 1.3; }
.co-card-meta { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 9px; }
.co-kind, .co-mins { font-size: 12px; color: var(--muted); }
.co-audio { display: inline-flex; color: var(--muted); }
.co-card-blurb { font-size: 13.5px; color: var(--muted); line-height: 1.5; max-width: 58ch; }
/* the arrow that says "this is a door" — see choiceCard() */
.co-go {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  padding: 0 16px; min-height: 44px; border-radius: 999px;
  border: 1px solid var(--border); color: var(--muted); white-space: nowrap;
}
.co-card.is-next .co-go {
  border-color: transparent; background: var(--accent); color: var(--card);
}
.co-card:hover .co-go { border-color: var(--accent); color: var(--accent); }
.co-card.is-next:hover .co-go { color: var(--card); }
.co-go-label { font-size: 13px; font-weight: 600; }
.co-done-all { color: var(--muted); margin: 0; }

/* a level is a real place a reader goes, so it gets a card's worth of height */
.co-rest { display: flex; flex-direction: column; gap: 8px; }
.co-level {
  border: 1px solid var(--border); border-left: 4px solid var(--lv, var(--border));
  border-radius: 12px; background: var(--card);
}
.co-level > summary {
  display: flex; align-items: center; gap: 12px; cursor: pointer;
  padding: 15px 16px; list-style: none; min-height: 56px; box-sizing: border-box;
}
.co-level > summary::-webkit-details-marker { display: none; }
.co-level > summary:hover { color: var(--accent); }
.co-level-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.co-level-title { font-weight: 600; font-size: 15px; }
/* "Still being written": a level a reader can open while it is filling up.
   Quiet — it is a fact about the course, not a warning about the piece. */
.co-wip { display: inline-flex; align-items: center; gap: 4px; margin-left: 6px;
          font-size: 12px; font-weight: 500; color: var(--muted); white-space: nowrap; }
.co-wip svg { opacity: .7; }
.co-now .co-wip { margin: 6px 0 0; }
.co-level-count { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.co-level[open] > summary .icon { transform: rotate(180deg); }
.co-list { margin: 0 0 10px; padding: 0 10px; list-style: none; }
.co-row-btn {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  background: none; border: none; padding: 11px 10px; border-radius: 9px;
  cursor: pointer; font-family: inherit; font-size: 14.5px; color: inherit;
  min-height: 44px; box-sizing: border-box;
}
.co-row-btn:hover { background: var(--bg); }
.co-tick { width: 14px; color: var(--lv, var(--accent)); font-size: 13px; }
.co-row.is-done .co-row-title { color: var(--muted); }
.co-row-title { flex: 1; }

/* The level colours, which the app already uses on the band chips. One
   variable per level, read by every rule above through var(--lv). */
.lv-A1, .lv-A2 { --lv: var(--verb); }
.lv-B1, .lv-B2 { --lv: var(--neut); }
.lv-C1, .lv-C2 { --lv: var(--fem); }

@media (max-width: 620px) {
  /* the arrow keeps its size; the label is what goes, since the card title
     already says what the thing is */
  .co-go-label { display: none; }
  .co-go { padding: 12px; }
  .co-card { padding: 16px; gap: 10px; }
}

/* ── which of two words that mean the same thing to use ────────────────────
   usageBlock() in views/dictionary.js. `zde` and `tady` both mean "here" and
   the dictionary said so and stopped; this is the part that separates them. */
.dc-usage-note {
  margin: 0 0 12px; font-size: 14px; line-height: 1.55; max-width: 62ch;
  padding-left: 11px; border-left: 3px solid var(--accent);
}
.dc-usage-rows { display: flex; flex-direction: column; gap: 6px; }
.dc-usage-row {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px;
  width: 100%; text-align: left; font-family: inherit; color: inherit;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card);
  padding: 12px 14px; min-height: 48px; box-sizing: border-box; cursor: pointer;
}
.dc-usage-row:hover:not([disabled]) { border-color: var(--accent); }
/* the word you looked up, kept in the list because the question is comparative */
.dc-usage-row.is-this { cursor: default; border-style: dashed; }
.dc-usage-word { display: inline-flex; align-items: baseline; gap: 7px; }
.dc-usage-word strong { font-size: 16px; }
.dc-usage-you {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--muted);
}
.dc-usage-gloss { font-size: 13px; color: var(--muted); flex: 1; min-width: 8ch; }
.dc-usage-marks { display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: 7px; }
.dc-usage-common { font-size: 12px; color: var(--muted); }
/* the comparative fact, which is the one that answers "which do I say" */
.dc-usage-rarer { font-size: 12px; font-weight: 600; color: var(--accent); }
.dc-usage-why { margin: 10px 0 0; font-size: 12px; color: var(--muted); max-width: 62ch; line-height: 1.5; }

/* A gloss borrowed from the word a Czech-only definition pointed at. Says so
   rather than passing a derivation off as a direct translation — see
   tools/derive_glosses.py and _derived() in server/dictionary.py. */
.dc-same-as {
  font-size: 10.5px; letter-spacing: 0.03em; color: var(--muted);
  border: 1px dashed var(--border); border-radius: 999px; padding: 0 7px;
  white-space: nowrap;
}

/* voice control (static/js/voice-commands.js) */
#pl-voice.on { border-color: var(--accent); color: var(--accent); }
.pl-voice-hint { margin: 6px 0 0; font-size: .85rem; color: var(--muted); text-align: right; }

/* words you already know (static/js/cognates.js) */
.cg-card { display: flex; gap: 12px; align-items: center; justify-content: space-between; margin: 0 0 16px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 12px; }
.cg-card p { margin: 2px 0 0; font-size: .9rem; }
.cg-lead { margin: 0 0 10px; }
.cg-group { margin: 8px 0; }
.cg-group summary { cursor: pointer; padding: 6px 0; }
.cg-list { list-style: none; margin: 4px 0; padding: 0; }
.cg-row { display: flex; gap: 10px; align-items: center; padding: 5px 0; border-bottom: 1px solid var(--border); }
.cg-word { font-weight: 650; background: none; border: 0; padding: 0; cursor: pointer; color: inherit; font-size: 1rem; text-decoration: underline dotted var(--border); text-underline-offset: 3px; }
.cg-word:hover { color: var(--accent); }
.cg-hear { border: none; background: none; cursor: pointer; padding: 2px; margin-left: -6px; color: var(--muted); display: inline-flex; }
.cg-hear:hover { color: var(--accent); }
.cg-gloss { flex: 1; color: var(--muted); font-size: .92rem; }
.cg-like { font-size: .8rem; color: var(--muted); }
.cg-keep { min-width: 34px; }
.cg-more { margin: 6px 0; }

/* Cards (static/js/views/cards.js) — one thing at a time, large and centred.
   The card is the page: everything else on screen is the set it came from and
   the two verdicts. */
.fc { max-width: 620px; margin: 0 auto; display: grid; gap: 14px; }
.fc-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.fc-pick {
  font-family: inherit; font-size: 15px; font-weight: 650; color: var(--text);
  background: none; border: 0; border-bottom: 1px dashed var(--border); cursor: pointer; padding: 2px 0;
}
.fc-pick:hover { border-color: var(--accent); color: var(--accent); }
.fc-count { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.fc-stage { display: grid; gap: 14px; }
.fc-card {
  position: relative; min-height: 230px; display: grid; align-content: center; justify-items: center;
  gap: 8px; text-align: center; cursor: pointer; padding: 28px 22px;
  border: 1px solid var(--border); border-radius: 16px; background: var(--card);
  transition: transform 180ms ease, border-color 180ms ease;
}
.fc-card:hover { border-color: var(--accent); }
.fc-card.is-back { background: var(--accent-soft); border-color: var(--accent); }
.fc-word { font-size: 30px; font-weight: 600; line-height: 1.2; }
.fc-card.is-back .fc-word { font-size: 24px; }
.fc-ask { font-size: 14px; color: var(--muted); }
.fc-sub { font-size: 14.5px; color: var(--text); opacity: .85; max-width: 46ch; }
.fc-hint { font-size: 12.5px; color: var(--muted); margin: 6px 0 0; }
.fc-notes { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin-top: 4px; }
.fc-note {
  font-size: 11.5px; letter-spacing: .02em; color: var(--muted);
  border: 1px solid var(--border); border-radius: 999px; padding: 1px 8px; background: var(--card);
}
.fc-links { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 6px; }
.fc-link { font-family: inherit; font-size: 12.5px; color: var(--accent); background: none; border: 0; cursor: pointer; padding: 0; }
.fc-say {
  position: absolute; top: 12px; right: 12px; display: flex; align-items: center;
  background: none; border: 0; color: var(--muted); cursor: pointer; padding: 4px;
}
.fc-say:hover { color: var(--accent); }
.fc-verdicts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.fc-verdicts button {
  font-family: inherit; font-size: 15px; display: flex; align-items: center; justify-content: center; gap: 7px;
  padding: 12px; border-radius: 12px; border: 1px solid var(--border); background: var(--card);
  color: var(--text); cursor: pointer;
}
.fc-verdicts button:disabled { opacity: .4; cursor: default; }
.fc-again:hover:not(:disabled) { border-color: var(--warn); color: var(--warn); }
.fc-got:hover:not(:disabled) { border-color: var(--verb); color: var(--verb); }
/* the end of a run: how it went, then the ways on as a row of doors */
.fc-done { display: grid; gap: 22px; align-content: start; justify-items: center; text-align: center; padding: 26px 0 10px; }
.fc-result { display: grid; gap: 10px; justify-items: center; }
.fc-tally { font-size: 14px; margin: 0; color: var(--muted); font-variant-numeric: tabular-nums; }
/* one mark per card, in the order they came — the run at a glance */
.fc-strip { display: flex; flex-wrap: wrap; justify-content: center; gap: 5px; max-width: 440px; }
.fc-strip-mark {
  width: 16px; height: 16px; border-radius: 4px;
  background: var(--border); box-shadow: inset 0 0 0 1px var(--border);
}
.fc-strip-mark.is-got { background: var(--verb); box-shadow: none; }
/* got, after a miss: half each, split on the diagonal */
.fc-strip-mark.is-late { background: linear-gradient(135deg, var(--warn) 50%, var(--verb) 50%); }
.fc-strip-mark.is-again { background: transparent; box-shadow: inset 0 0 0 2px var(--warn); }
.fc-strip.is-small { justify-content: flex-start; gap: 3px; }
.fc-strip.is-small .fc-strip-mark { width: 7px; height: 7px; border-radius: 2px; }
.fc-strip.is-small .fc-strip-mark.is-again { box-shadow: inset 0 0 0 1.5px var(--warn); }

.fc-ways {
  width: 100%; display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
}
.fc-way {
  --way: var(--accent);
  display: grid; align-content: start; gap: 6px; min-height: 104px;
  text-align: left; font-family: inherit; cursor: pointer; color: var(--text);
  padding: 12px 13px 13px; border-radius: 14px;
  border: 1.5px solid color-mix(in srgb, var(--way) 30%, var(--border));
  background: color-mix(in srgb, var(--way) 7%, var(--card));
  transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.fc-way:hover, .fc-way:focus-visible {
  border-color: var(--way); transform: translateY(-2px); box-shadow: var(--shadow);
}
.fc-way:focus-visible { outline: 2px solid var(--way); outline-offset: 2px; }
.fc-way-top { display: flex; align-items: center; justify-content: space-between; color: var(--way); }
.fc-way-eyebrow { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.fc-way-label { font-size: 19px; font-weight: 700; letter-spacing: -.01em; line-height: 1.15; }
.fc-way-peek { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; min-width: 0; }
.fc-way-word {
  font-size: 12.5px; padding: 2px 7px; border-radius: 6px; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: color-mix(in srgb, var(--way) 12%, var(--card));
  color: var(--text);
}
.fc-way-dim { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.fc-way .fc-deck-meter { width: 100%; }
/* the way on is the one to take: filled, in the set's own colour */
.fc-way.is-next {
  background: var(--way); border-color: var(--way); color: var(--on-accent);
}
.fc-way.is-next .fc-way-top { color: inherit; opacity: .92; }
.fc-way.is-next .fc-way-word { background: color-mix(in srgb, var(--on-accent) 18%, transparent); color: inherit; }
.fc-way.is-next .fc-way-dim { color: inherit; opacity: .85; }
.fcx-tint.is-tinted .fc-way.is-next { --way: hsl(var(--fc-h) var(--tint-s) var(--tint-l)); }
.fc-way.is-missed { --way: var(--warn); }
.fc-way.is-home { --way: var(--muted); }
.fc-way.is-home .fc-way-top { color: var(--muted); }
@media (prefers-reduced-motion: reduce) { .fc-way { transition: none; } .fc-way:hover { transform: none; } }
/* the picker */
.fc-picker { display: grid; gap: 10px; }
.fc-group { font-size: 13px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin: 8px 0 0; }
.fc-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px; }
.fc-tile {
  display: grid; gap: 3px; text-align: left; font-family: inherit; cursor: pointer;
  border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 10px 12px;
}
.fc-tile:hover { border-color: var(--accent); }
.fc-tile strong { font-size: 14.5px; color: var(--text); }
.fc-why { font-size: 12px; color: var(--muted); }
.fc-opts { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.fc-opt { display: flex; align-items: center; gap: 7px; font-size: 13.5px; color: var(--muted); cursor: pointer; }
@media (max-width: 520px) {
  .fc-card { min-height: 190px; padding: 22px 16px; }
  .fc-word { font-size: 26px; }
}
/* The flip is a nicety; the card must still turn over without it. */
@media (prefers-reduced-motion: reduce) { .fc-card { transition: none; } }
/* Cards offered from elsewhere: Today's tile, the end of a piece, Saved. */
.td-cardsbox { margin-top: 4px; }
.td-cardstile {
  display: grid; gap: 4px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--card); padding: 12px 14px;
}
.td-ct-head { display: flex; align-items: center; gap: 7px; }
.td-ct-why { margin: 0; font-size: 12.5px; color: var(--muted); }
.td-ct-go {
  justify-self: start; margin-top: 6px; font-family: inherit; font-size: 13.5px; cursor: pointer;
  border: 1px solid var(--accent); color: var(--accent); background: none; border-radius: 9px; padding: 5px 12px;
}
.pl-cards { margin: 10px 0 0; }
.sv-head-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
/* a measured verdict that is not "regular" reads as a caution, not an error */
.dc-fact.warnish .dc-fact-v { color: var(--warn); }

/* Work it out (static/js/guidewidgets/workitout.js): the three rules as three
   questions, then what the pattern gives with each ending's provenance. */
.wi-steps { display: grid; gap: 10px; }
.wi-step { display: grid; gap: 5px; }
.wi-ask { margin: 0; font-size: 13.5px; font-weight: 600; }
.wi-choices { display: flex; flex-wrap: wrap; gap: 6px; }
.wi-choice {
  font: inherit; font-size: 13px; cursor: pointer; padding: 4px 12px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
}
.wi-choice:hover { border-color: var(--accent); }
.wi-choice.chosen { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.wi-choice.wrong { border-color: var(--warn); color: var(--warn); }
.wi-said { margin: 0; font-size: 12.5px; color: var(--muted); line-height: 1.5; }
.wi-wait, .wi-no { margin: 0; font-size: 13px; color: var(--muted); }
.wi-result { display: grid; gap: 8px; }
.wi-verdict { margin: 6px 0 0; font-size: 14px; }
.wi-table { border-collapse: collapse; font-size: 13.5px; width: 100%; }
.wi-table th { text-align: left; font-weight: 500; color: var(--muted); padding: 3px 8px 3px 0; white-space: nowrap; }
.wi-table thead th { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
.wi-cell { padding: 3px 8px 3px 0; }
.wi-cell.universal .wi-form { font-weight: 600; }
.wi-mark { color: var(--muted); font-size: 11px; margin-left: 5px; }
.wi-mark.universal { color: var(--accent); }
.wi-key { margin: 2px 0 0; font-size: 12px; color: var(--muted); display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.wi-changes { margin: 0; font-size: 12.5px; color: var(--muted); }

/* Decline the whole word (static/js/guidewidgets/wholeword.js). */
.ww-controls { display: flex; flex-wrap: wrap; gap: 12px; }
.ww-tabs { display: flex; gap: 4px; }
.ww-tab {
  font: inherit; font-size: 12.5px; cursor: pointer; padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--bg); color: var(--muted);
}
.ww-tab.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.ww-board { display: grid; gap: 8px; }
.ww-table { border-collapse: collapse; font-size: 13.5px; width: 100%; }
.ww-table th { text-align: left; font-weight: 500; color: var(--muted); padding: 3px 8px 3px 0; white-space: nowrap; }
.ww-table td { padding: 2px 6px 2px 0; }
.ww-num { color: var(--muted); font-size: 12px; }
.ww-input, .ww-select {
  font: inherit; font-size: 13.5px; color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: 8px; height: 28px; padding: 0 8px; width: 100%; max-width: 190px;
}
.ww-table tr.ok .ww-input, .ww-table tr.ok .ww-select { border-color: var(--verb); }
.ww-table tr.no .ww-input, .ww-table tr.no .ww-select { border-color: var(--warn); }
.ww-said { font-size: 12px; color: var(--muted); line-height: 1.45; }
.ww-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.ww-chip {
  font: inherit; font-size: 13px; cursor: pointer; width: 28px; height: 26px; border-radius: 7px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
}
.ww-chip:hover { border-color: var(--accent); color: var(--accent); }
.ww-acts { display: flex; gap: 8px; }
.ww-acts button {
  font: inherit; font-size: 13.5px; cursor: pointer; padding: 5px 13px; border-radius: 9px;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
}
.ww-mark { border-color: var(--accent) !important; color: var(--accent) !important; }
.ww-tally { margin: 0; font-size: 13.5px; font-variant-numeric: tabular-nums; }
.ww-wait, .ww-no { margin: 0; font-size: 13px; color: var(--muted); }
/* the picker: six worth doing, a box to find the rest, the lists collapsed */
.fc-search {
  font: inherit; font-size: 13.5px; width: 100%; height: 32px; padding: 0 12px;
  border: 1px solid var(--border); border-radius: 999px; background: var(--bg); color: var(--text);
}
.fc-all { border-top: 1px solid var(--border); padding-top: 8px; }
.fc-all summary {
  cursor: pointer; font-size: 13px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); padding: 4px 0;
}
.fc-all[open] summary { color: var(--text); }
.fc-all .fc-tiles { margin-top: 8px; }
/* the thesaurus, shut by default: a browse tool under a page for looking up */
details.dc-thes { border-top: 1px solid var(--border); padding-top: 10px; margin-top: 18px; }
details.dc-thes > summary {
  cursor: pointer; font-size: 17px; font-weight: 600; padding: 4px 0;
  display: flex; align-items: baseline; gap: 8px;
}
details.dc-thes > summary .dc-count { font-size: 13px; font-weight: 400; color: var(--muted); }
details.dc-thes[open] > summary { margin-bottom: 8px; }
/* the sentence a word was met in, with a button that speaks the line */
/* ── Cards, the home screen ──────────────────────────────────────────────────
   Cards opens on a page rather than a popup (static/js/views/cards.js
   showHome): Set deck first, then the learner's own decks, then recommended
   sets, then every set. A block per job, so the page reads top to bottom as
   "make one, or use one you made, or take one we suggest". */
.fc-home { display: grid; gap: 22px; padding-bottom: 8px; }
.fc-block { display: grid; gap: 10px; }
.fc-block-h { margin: 0; font-size: 16px; }
.fc-block-quiet { padding-top: 4px; border-top: 1px solid var(--border); }
.fc-pick.is-home { cursor: default; border-bottom-color: transparent; font-size: 17px; }

/* the builder — the one block with a frame, because it is the one being made */
.fc-builder {
  padding: 14px; border-radius: 14px;
  border: 1px solid var(--border); background: var(--card);
}
.fc-box { display: grid; gap: 8px; padding: 10px 0; border-top: 1px solid var(--border); }
.fc-box-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.fc-box-head strong { font-size: 13px; letter-spacing: .02em; }
.fc-add {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  font-family: inherit; font-size: 12.5px; padding: 6px 11px; border-radius: 999px;
  border: 1px solid var(--accent); background: none; color: var(--accent);
}
.fc-box.is-adding .fc-add { background: var(--accent); color: var(--card); }
.fc-add-plus { font-size: 14px; line-height: 1; }
.fc-chips { display: flex; flex-wrap: wrap; gap: 6px; min-height: 28px; align-items: center; }
.fc-ing {
  display: inline-flex; align-items: center; gap: 4px; font-size: 13px;
  padding: 4px 4px 4px 10px; border-radius: 999px;
  background: var(--accent-soft); border: 1px solid var(--accent);
}
.fc-ing-x {
  display: grid; place-items: center; width: 22px; height: 22px; border-radius: 999px;
  border: 0; background: none; color: var(--muted); cursor: pointer;
}
.fc-ing-x:hover { color: var(--text); background: var(--bg); }
.fc-ing-empty { font-size: 12.5px; color: var(--muted); }

/* the list to add from, opened in place under the box it feeds */
.fc-chooser {
  display: grid; gap: 8px; padding: 10px; border-radius: 10px;
  background: var(--bg); border: 1px solid var(--border);
  max-height: 46vh; overflow-y: auto; overscroll-behavior: contain;
}
.fc-choose-search {
  font-family: inherit; font-size: 14px; padding: 8px 10px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
}
.fc-choose-list { display: grid; gap: 8px; }
.fc-choose-h { margin: 4px 0 0; font-size: 11px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.fc-choose-group summary { cursor: pointer; font-size: 13px; padding: 4px 0; color: var(--muted); }
.fc-choices { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 0; }
.fc-choice {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  font-family: inherit; font-size: 12.5px; padding: 6px 10px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
}
.fc-choice:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.fc-choice.is-in, .fc-choice:disabled { opacity: .5; cursor: default; }

/* ⚠️ fc-deck-count, not fc-count: the header's "3 of 20" is already .fc-count,
   and a shared class put the builder's margins and warning colour on it */
.fc-deck-count { margin: 4px 0 0; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.fc-deck-count.is-empty { color: var(--warn); }
.fc-builder-go { display: grid; gap: 8px; margin-top: 4px; }
.fc-deck-name {
  font-family: inherit; font-size: 14px; padding: 9px 11px; border-radius: 9px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
}
.fc-builder-buttons { display: flex; gap: 8px; justify-content: flex-end; }
.fc-builder-buttons button {
  font-family: inherit; font-size: 14px; padding: 9px 16px; border-radius: 9px; cursor: pointer;
}
.fc-builder-buttons button:disabled { opacity: .45; cursor: default; }

/* how many words in each set — the slider and what it means */
.fc-size-row { display: grid; gap: 6px; }
.fc-size-label { font-size: 13px; font-weight: 600; }
.fc-size { width: 100%; accent-color: var(--accent); }
.fc-size-says { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* one chip per set of a saved deck: a map of the deck, not a list of numbers */
.fc-set-row { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 2px 2px; }
.fc-set {
  display: inline-flex; align-items: baseline; gap: 5px; cursor: pointer;
  font-family: inherit; padding: 6px 10px; border-radius: 9px; min-height: 32px;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
}
.fc-set:hover { border-color: var(--accent); }
.fc-set-n { font-weight: 700; font-size: 13px; }
.fc-set-of { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
/* a set left half done, and a set fully known — said in the border as well
   as the number, so it reads at a glance */
.fc-set.is-open { border-color: var(--accent); }
.fc-set.is-done { border-color: var(--verb); background: color-mix(in srgb, var(--verb) 12%, var(--card)); }

/* your decks: how much of each is known, and where the last run was left */
.fc-deck-tile { position: relative; display: grid; }
.fc-deck-open { padding-right: 38px; }
.fc-deck-meter {
  display: block; height: 3px; border-radius: 999px; background: var(--border);
  overflow: hidden; margin-top: 4px;
}
.fc-deck-meter-fill { display: block; height: 100%; background: var(--verb); }
.fc-deck-state { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.fc-deck-x {
  position: absolute; top: 8px; right: 8px; display: grid; place-items: center;
  width: 26px; height: 26px; border-radius: 999px; cursor: pointer;
  border: 0; background: none; color: var(--muted);
}
.fc-deck-x:hover { color: var(--warn); background: var(--bg); }

/* a note under an answer that opens something — see cards.js noteRow */
.fc-note.is-open {
  font-family: inherit; cursor: pointer; background: none;
  border-color: var(--accent); color: var(--accent);
  /* a label can be small; a button has to be big enough to hit on a phone */
  padding: 5px 11px; min-height: 28px;
}
.fc-note.is-open:hover { background: var(--accent-soft); }
.fc-explain { display: grid; gap: 12px; }
.fc-explain-said { margin: 0; font-size: 14px; line-height: 1.55; max-width: 60ch; }
.fc-explain-word { margin: 4px 0 0; font-size: 18px; font-weight: 600; }
.fc-explain-topic { justify-self: start; }

/* the group chips in All sets */
.fc-filters { display: flex; flex-wrap: wrap; gap: 6px; }
.fc-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: inherit; font-size: 12.5px; cursor: pointer; white-space: nowrap;
  padding: 6px 11px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--card); color: var(--muted);
}
.fc-chip:hover { border-color: var(--accent); color: var(--accent); }
.fc-chip.is-on { border-color: var(--accent); background: var(--accent); color: var(--card); }

/* ── Cards, the eight features ───────────────────────────────────────────────
   Every rule below is scoped under `.fcx-<flag>`, which the view puts on its
   root for each flag that is on (static/js/cardfeatures.js). Turn a flag off
   and its stylesheet stops applying; delete a block and nothing else moves. */

/* 1. room — the card takes the screen, the verdicts sit under the thumb.
   The stage becomes two rows: the card takes whatever is going, the buttons
   take what they need, and they land at the bottom where the hand already is.
   ⚠️ dvh, not vh: on a phone the address bar makes vh a promise the browser
   does not keep, and the buttons ended up under it. */
.fcx-room .fc { display: flex; flex-direction: column; }
.fcx-room .fc-stage {
  grid-template-rows: 1fr auto; align-content: stretch;
  min-height: calc(100vh - 230px); min-height: calc(100dvh - 230px);
}
.fcx-room .fc-card { height: 100%; }
.fcx-room .fc-verdicts { position: sticky; bottom: 0; }
.fcx-room .fc-verdicts button { padding: 15px 12px; font-size: 16px; }
@media (min-width: 721px) {
  /* a desktop window is not a phone held at arm's length: tall, not endless */
  .fcx-room .fc-stage { min-height: min(72vh, 760px); }
}
/* Stepping through the deck without answering for it. Small and quiet on
   purpose: the verdicts are the point of the screen and these are a way to
   look around, not a second pair of them. */
.fc-step { display: flex; align-items: center; gap: 2px; margin-left: auto; }
.fc-stepper {
  display: grid; place-items: center; width: 30px; height: 30px; border-radius: 8px;
  font-family: inherit; font-size: 17px; line-height: 1; cursor: pointer;
  border: 1px solid transparent; background: none; color: var(--muted);
}
.fc-stepper:hover:not(:disabled) { border-color: var(--border); color: var(--accent); }
.fc-stepper:disabled { opacity: 0.3; cursor: default; }

.fc-bar { height: 3px; border-radius: 999px; background: var(--border); overflow: hidden; margin: 0 0 12px; }
.fc-bar-fill {
  display: block; height: 100%; width: 0;
  background: var(--accent); transition: width 260ms ease;
}

/* 2. flip — both faces in one grid cell, so the card is as tall as the taller
   of them and the turn has something to turn. This is also what settles the
   190px-to-203px jump the instant swap used to make. */
/* ⚠️ The card is a grid that packs its rows to the CENTRE, so the flipper's
   `height: 100%` was resolving against a content-sized row: on a 549px card
   both faces were 205px, and the back's colour was a band floating in the
   middle of it rather than the face of a card. One stretched row fixes it.

   The padding moves onto the faces at the same time, and has to: a face that
   fills the card is what lets its colour reach the card's own rounded edge,
   and padding left on the card would have held it off by 22px all round. */
.fcx-flip .fc-card { perspective: 1200px; grid-template-rows: 1fr; align-content: stretch; padding: 0; }
/* the card's own radius, so a face cannot show a corner the card does not */
.fcx-flip .fc-side { padding: 28px 22px; border-radius: 16px; }
@media (max-width: 520px) {
  .fcx-flip .fc-side { padding: 22px 16px; }
}
.fcx-flip .fc-flipper {
  display: grid; width: 100%; height: 100%;
  transform-style: preserve-3d; transition: transform 460ms cubic-bezier(.2, .7, .3, 1);
}
.fcx-flip .fc-card.is-back .fc-flipper { transform: rotateY(180deg); }
.fcx-flip .fc-side {
  grid-area: 1 / 1; display: grid; align-content: center; justify-items: center;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
}
.fcx-flip .fc-side-back { transform: rotateY(180deg); }
/* the card's own colour change belongs to the face, not the box, or it would
   swap at the halfway point of a turn that has not finished */
.fcx-flip .fc-card.is-back { background: var(--card); border-color: var(--border); }
.fcx-flip .fc-side-back { background: var(--accent-soft); border-radius: 16px; }
@media (prefers-reduced-motion: reduce) {
  .fcx-flip .fc-flipper { transition: none; }
}

/* 3. drag — the card follows the thumb and shows where the threshold is. */
.fcx-drag .fc-card { touch-action: pan-y; will-change: transform; }
.fcx-drag .fc-card.is-dragging { transition: none; cursor: grabbing; }
.fcx-drag .fc-card.to-again { border-color: var(--warn); }
.fcx-drag .fc-card.to-got { border-color: var(--verb); }
.fcx-drag .fc-card.to-again::after,
.fcx-drag .fc-card.to-got::after {
  content: ""; position: absolute; inset: 0; border-radius: 16px; pointer-events: none;
  background: currentColor; opacity: .07;
}
.fcx-drag .fc-card.to-again::after { color: var(--warn); }
.fcx-drag .fc-card.to-got::after { color: var(--verb); }

/* 4. back — the word, the answer, the sentence, then the small print. */
.fcx-back .fc-asked { font-size: 15px; color: var(--muted); letter-spacing: .01em; }
.fcx-back .fc-answer { font-size: 23px; font-weight: 600; line-height: 1.25; max-width: 30ch; }
.fcx-back .fc-side-back .fc-sub { font-size: 13.5px; opacity: .88; }
.fcx-back .fc-example {
  border: 1px solid var(--border); border-radius: 12px; padding: 12px 13px;
  background: var(--card); margin-top: 4px;
}

/* 5. source — where the word was met, and the way back to it. */
.fc-source {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 8px;
  font-family: inherit; font-size: 12px; color: var(--muted); cursor: pointer;
  background: none; border: 0; padding: 0; text-align: left;
}
.fc-source:hover { color: var(--accent); }

/* 6. typing — the box, and what it made of the answer. */
.fc-type-row { display: grid; gap: 8px; justify-items: center; width: 100%; max-width: 20rem; }
.fc-type-line { display: flex; gap: 8px; width: 100%; }
.fc-type {
  flex: 1; min-width: 0; font-family: inherit; font-size: 17px; text-align: center;
  padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--bg); color: var(--text);
}
.fc-type:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.fc-type-go {
  font-family: inherit; font-size: 14px; padding: 0 15px; border-radius: 10px; cursor: pointer;
  border: 1px solid transparent; background: var(--accent); color: var(--card);
}
.fc-type-skip {
  font-family: inherit; font-size: 12.5px; color: var(--muted); cursor: pointer;
  background: none; border: 0; padding: 2px;
}
.fc-type-skip:hover { color: var(--accent); }
.fc-typed { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; align-items: baseline; font-size: 13px; }
.fc-typed-verdict { font-weight: 600; }
.fc-typed.is-right .fc-typed-verdict { color: var(--verb); }
.fc-typed.is-near .fc-typed-verdict { color: var(--neut); }
.fc-typed.is-wrong .fc-typed-verdict { color: var(--muted); font-weight: 400; }
.fc-typed-was { text-decoration: line-through; opacity: .82; }
/* the verdict the typing points at — offered, never taken */
.fc-verdicts .is-likely { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }

/* 7. listen — the clip is the question. */
.fc-hear {
  display: grid; place-items: center; width: 84px; height: 84px; border-radius: 999px;
  cursor: pointer; color: var(--accent);
  border: 1px solid var(--border); background: var(--card);
}
.fc-hear:hover { border-color: var(--accent); }

/* 8. tint — the set's own light.
   ⚠️ Gated on `is-tinted`, which the view adds only once a set has actually
   set a hue. Leaning on a `var(--fc-h, 0)` fallback instead would paint every
   untinted card red, hue 0 being a colour rather than an absence. */
.fcx-tint.is-tinted .fc-card { border-color: hsl(var(--fc-h) 40% 58% / .55); }
.fcx-tint.is-tinted .fc-card:hover { border-color: hsl(var(--fc-h) 55% 52%); }
.fcx-tint.is-tinted .fc-side-back { background: hsl(var(--fc-h) 55% 50% / .10); }
.fcx-tint.is-tinted .fc-bar-fill { background: hsl(var(--fc-h) 55% 48%); }

.fc-example { display: flex; align-items: flex-start; gap: 8px; max-width: 46ch; text-align: left; }
.fc-play {
  flex: 0 0 auto; margin-top: 2px; display: flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border); background: var(--card); color: var(--muted);
}
.fc-play:hover { border-color: var(--accent); color: var(--accent); }
.fc-lines { display: grid; gap: 2px; }
.fc-line { font-size: 14.5px; }
.fc-line-en { font-size: 13px; color: var(--muted); }

/* ---------- the phone's five ---------- */
/* Hidden on a laptop, where the rail is a real sidebar and fits. */
.tabbar { display: none; }
/* what a view has to keep clear of on a phone; zero where there is no bar */
:root { --tabbar-h: 0px; }
/* a tab or rail group of the section not on screen (shell.js applySection) */
.tab[hidden], .rail-group[hidden] { display: none !important; }

@media (max-width: 720px) {
  /* the ten-chip strip goes; its header (name, language, menu) stays */
  .rail-nav { display: none; }
  :root { --tabbar-h: 62px; }
  .tabbar {
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
    background: var(--card); border-top: 1px solid var(--border);
    padding: 4px 2px calc(4px + env(safe-area-inset-bottom));
  }
  .tab {
    display: grid; justify-items: center; gap: 2px; padding: 6px 2px;
    font: inherit; background: none; border: 0; cursor: pointer; color: var(--muted);
  }
  .tab-label { font-size: 10.5px; letter-spacing: .01em; }
  .tab.active { color: var(--accent); }
  .tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  /* room for the bar, so the last line of a piece is not under it */
  .main { padding-bottom: calc(var(--tabbar-h) + 14px); }
}
/* a sitting: one button to begin it, one line to close it */
.td-session-slot { margin-top: 2px; }
.td-session {
  display: inline-flex; align-items: center; gap: 8px; font: inherit; font-size: 14px; cursor: pointer;
  padding: 9px 15px; border-radius: 999px;
  border: 1px solid var(--accent); background: var(--accent-soft); color: var(--accent);
}
.td-session:hover { background: var(--accent); color: var(--on-accent); }
.pl-next { display: block; font-size: 13.5px; color: var(--muted); margin-bottom: 6px; }
.fc-sitting { margin: 0; font-size: 15px; max-width: 42ch; }
.td-session { align-items: center; text-align: left; padding: 10px 16px; }
.td-session-text { display: grid; gap: 1px; }
.td-session-text strong { font-size: 14.5px; }
.td-session-sub { font-size: 12.5px; opacity: .8; }

/* the Culture shelf's way into the Atlas (views/library.js syncAtlas) */
.lib-history { margin: 4px 0 22px; }

/* ── the practice widgets (static/js/guidewidgets/*: choose, order, judge,
   type, ending, spot, sort, match, switch, scale, explore, flip, count,
   clock). One vocabulary for all of them — a sentence, choices, a verdict
   with its reason, a Next — so fourteen different exercises still read as
   one book. ── */
.gw-run { display: grid; gap: 10px; }
.gw-dots { display: flex; flex-wrap: wrap; gap: 4px; }
.gw-dot { width: 18px; height: 5px; border-radius: 999px; background: var(--border); }
.gw-dot.is-here { background: var(--accent); }
.gw-dot.is-right { background: var(--verb); }
.gw-dot.is-wrong { background: var(--warn); }
.gw-stage, .gw-item { display: grid; gap: 10px; }
.gw-end { display: grid; gap: 8px; justify-items: start; padding: 4px 0; }
.gw-end-line { margin: 0; font-size: 15px; font-weight: 600; }
.gw-btn {
  font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
  padding: 7px 14px; border-radius: 9px; border: 1px solid var(--accent);
  background: var(--accent); color: var(--on-accent);
}
.gw-btn:hover { filter: brightness(1.08); }
.gw-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gw-after { display: grid; gap: 8px; }
.gw-after-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.gw-next { margin-left: auto; }
.gw-hear {
  display: inline-grid; place-items: center; width: 30px; height: 30px; flex: none; cursor: pointer;
  border-radius: 999px; border: 1px solid var(--border); background: var(--card); color: var(--accent);
}
.gw-hear:hover { border-color: var(--accent); }
.gw-why { margin: 0; font-size: 13.5px; line-height: 1.5; padding: 8px 11px; border-radius: 9px; background: var(--panel); }
.gw-why.is-right { background: color-mix(in srgb, var(--verb) 11%, var(--card)); }
.gw-why.is-right::before { content: "✓ "; color: var(--verb); font-weight: 700; }
.gw-why.is-wrong { background: color-mix(in srgb, var(--warn) 10%, var(--card)); }
.gw-why.is-wrong::before { content: "✗ "; color: var(--warn); font-weight: 700; }
.gw-why[hidden] { display: none; }
.gw-fix { margin: 0; font-family: var(--serif); font-size: 17px; }
.gw-fix-label { font-family: inherit; font-size: 12px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--verb); }
.gw-also { margin: 0; font-size: 13px; color: var(--muted); }
.gw-also [lang] { font-family: var(--serif); font-size: 15px; color: var(--text); }
.gw-prompt { margin: 0; font-family: var(--serif); font-size: 19px; }

/* choices: forms to pick from */
.gw-choices { display: flex; flex-wrap: wrap; gap: 7px; }
.gw-choice {
  font: inherit; font-size: 15px; cursor: pointer; min-height: 36px;
  padding: 6px 14px; border-radius: 10px; border: 1.5px solid var(--border); background: var(--bg); color: var(--text);
}
.gw-choice[lang] { font-family: var(--serif); font-size: 17px; }
.gw-choice:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.gw-choice:disabled { cursor: default; }
.gw-choice.is-right { border-color: var(--verb); background: color-mix(in srgb, var(--verb) 12%, var(--card)); color: var(--text); font-weight: 600; }
.gw-choice.is-wrong { border-color: var(--warn); background: color-mix(in srgb, var(--warn) 10%, var(--card)); text-decoration: line-through; }
.gw-two .gw-choice { flex: 1 1 0; font-family: inherit; font-size: 15px; font-weight: 600; }
.gw-gap-fill {
  display: inline-block; min-width: 3.2em; padding: 0 6px; margin: 0 2px; text-align: center;
  border-bottom: 2px dashed var(--accent); color: var(--accent);
}
.gw-gap-fill.is-right { border-bottom: 2px solid var(--verb); color: var(--verb); font-weight: 700; }
.gw-gap-fill.is-wrong { border-bottom: 2px solid var(--warn); color: var(--warn); text-decoration: line-through; }

/* build the sentence */
.gw-build {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0; min-height: 50px;
  padding: 8px 10px; border-radius: 10px; border: 1.5px dashed var(--border); font-family: var(--serif); font-size: 18px;
}
.gw-build.is-right { border-style: solid; border-color: var(--verb); background: color-mix(in srgb, var(--verb) 7%, var(--card)); }
.gw-build.is-wrong { border-style: solid; border-color: var(--warn); }
.gw-build-empty { font-family: inherit; font-size: 13px; color: var(--muted); }
.gw-tile {
  font: inherit; font-family: var(--serif); font-size: 17px; cursor: pointer;
  padding: 4px 11px; border-radius: 8px; border: 1px solid var(--border); background: var(--card); color: var(--text);
  box-shadow: 0 1px 0 var(--border);
}
.gw-tile:hover:not(:disabled) { border-color: var(--accent); }
.gw-tile:disabled:not(.is-placed) { opacity: .3; cursor: default; }
.gw-tile.is-placed { background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); }

/* right or wrong */
.gw-judged { padding: 10px 12px; border-radius: 10px; background: var(--bg); border: 1px solid var(--border); margin: 0; }
.gw-judged.is-good { border-color: var(--verb); }
.gw-judged.is-bad { border-color: var(--warn); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--warn) 60%, transparent); }

/* type it */
.gw-type-row { display: flex; gap: 8px; }
.gw-type {
  flex: 1; min-width: 0; font: inherit; font-family: var(--serif); font-size: 18px; color: var(--text);
  padding: 7px 12px; border-radius: 10px; border: 1.5px solid var(--border); background: var(--bg);
}
.gw-type:focus-visible { outline: none; border-color: var(--accent); }
.gw-type.is-right { border-color: var(--verb); }
.gw-type.is-near { border-color: var(--neut); }
.gw-type.is-wrong { border-color: var(--warn); }
.gw-letters { display: flex; flex-wrap: wrap; gap: 4px; }
.gw-letter {
  font: inherit; font-family: var(--serif); font-size: 15px; width: 32px; height: 32px; cursor: pointer;
  border-radius: 7px; border: 1px solid var(--border); background: var(--card); color: var(--text);
}
.gw-letter:hover { border-color: var(--accent); color: var(--accent); }

/* add the ending */
.gw-ending-line { margin: 0; }
.gw-stemmed { white-space: nowrap; }
.gw-stem { font-weight: 600; }
.gw-end-slot {
  display: inline-block; min-width: 1.4em; padding: 0 3px; text-align: center; font-weight: 700;
  color: var(--accent); border-bottom: 2px dashed var(--accent);
}
.gw-end-slot.is-right { color: var(--verb); border-bottom: 2px solid var(--verb); }
.gw-end-slot.is-fixed { color: var(--warn); border-bottom: 2px solid var(--warn); }
.gw-ending { min-width: 56px; text-align: center; }

/* find it: every word is a button */
.gw-spot .gw-tok { border-bottom-style: dotted; }
.gw-tok.is-picked { background: var(--accent-soft); color: var(--accent); font-weight: 600; border-bottom-color: transparent; }
.gw-tok.is-right { background: color-mix(in srgb, var(--verb) 15%, transparent); color: var(--text); border-bottom: 2px solid var(--verb); }
.gw-tok.is-wrong { background: color-mix(in srgb, var(--warn) 12%, transparent); border-bottom: 2px solid var(--warn); text-decoration: line-through; }
.gw-tok.is-missed { outline: 2px dashed var(--verb); outline-offset: 1px; }
.gw-tok:disabled { cursor: default; }

/* sort them */
.gw-sort { display: grid; gap: 10px; }
.gw-sortable { font-family: var(--serif); font-size: 16px; }
.gw-bins { display: grid; gap: 8px; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
.gw-bin {
  display: grid; align-content: start; gap: 4px; min-height: 92px; text-align: left; cursor: pointer; font: inherit;
  padding: 10px; border-radius: 12px; border: 1.5px dashed var(--border); background: var(--bg); color: var(--text);
}
.gw-bin.is-ready { border-color: var(--accent); background: var(--accent-soft); }
.gw-bin.is-shake { animation: gw-shake .35s; border-color: var(--warn); }
.gw-bin-label { font-size: 13px; font-weight: 700; }
.gw-bin-hint { font-size: 11.5px; color: var(--muted); }
.gw-bin-list { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.gw-binned {
  font-family: var(--serif); font-size: 14px; padding: 1px 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--verb) 14%, var(--card)); border: 1px solid color-mix(in srgb, var(--verb) 40%, var(--border));
}
@keyframes gw-shake { 0%, 100% { transform: none; } 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }

/* match them */
.gw-match { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.gw-match-col { display: grid; gap: 6px; align-content: start; }
.gw-match-h { margin: 0; font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.gw-match-cell {
  font: inherit; font-size: 14px; text-align: left; cursor: pointer; min-height: 40px;
  padding: 7px 11px; border-radius: 10px; border: 1.5px solid var(--border); background: var(--bg); color: var(--text);
}
.gw-match-cell[lang] { font-family: var(--serif); font-size: 16px; }
.gw-match-cell:hover:not(:disabled) { border-color: var(--accent); }
.gw-match-cell.is-on { border-color: var(--accent); background: var(--accent-soft); }
.gw-match-cell.is-joined {
  --pair: hsl(var(--pair-h) var(--tint-s) var(--tint-l));
  border-color: var(--pair); background: color-mix(in srgb, var(--pair) 14%, var(--card)); cursor: default;
}
.gw-match-cell.is-shake { animation: gw-shake .35s; border-color: var(--warn); }

/* switch it */
.gw-segs { display: inline-flex; flex-wrap: wrap; gap: 3px; padding: 3px; border-radius: 11px; background: var(--panel); justify-self: start; }
.gw-seg {
  font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
  padding: 5px 14px; border-radius: 8px; border: 0; background: none; color: var(--muted);
}
.gw-seg.is-on { background: var(--card); color: var(--text); box-shadow: var(--shadow); }
.gw-switch-rows { display: grid; gap: 8px; }
.gw-switch-row { padding: 8px 10px; border-radius: 10px; background: var(--bg); border: 1px solid var(--border); }
.gw-switch-main { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.gw-switch-line { margin: 0; font-family: var(--serif); font-size: 18px; }
.gw-changed { background: color-mix(in srgb, var(--neut) 22%, transparent); color: inherit; border-radius: 4px; padding: 0 2px; }
.gw-switch-note { margin: 2px 0 0; font-size: 12.5px; color: var(--muted); }
.gw-switch-row .gw-meaning { margin: 2px 0 0; font-size: 13px; }

/* slide along / count them */
.gw-scale-box { display: grid; gap: 4px; padding: 12px 14px; border-radius: 12px; background: var(--bg); border: 1px solid var(--border); }
.gw-scale-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.gw-scale-word { margin: 0; font-family: var(--serif); font-size: 28px; font-weight: 700; }
.gw-scale { width: 100%; accent-color: var(--accent); }
.gw-scale-ends { display: flex; justify-content: space-between; font-size: 12px; color: var(--muted); margin-top: -6px; }
.gw-scale-ticks { display: flex; flex-wrap: wrap; gap: 5px; }
.gw-scale-tick {
  font: inherit; font-family: var(--serif); font-size: 14px; cursor: pointer;
  padding: 2px 9px; border-radius: 999px; border: 1px solid var(--border); background: var(--card); color: var(--text);
}
.gw-scale-tick.is-on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.gw-count-top { display: flex; align-items: center; gap: 14px; }
.gw-count-n { flex: none; min-width: 2.2ch; font-size: 34px; font-weight: 700; font-variant-numeric: tabular-nums; text-align: right; }
.gw-count-line { margin: 0; font-size: 21px; }
.gw-count-line .gw-changed { font-weight: 600; }

/* explore */
.gw-explore-chip { display: inline-flex; align-items: baseline; gap: 6px; }
.gw-chip-tag { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-size: 11px; color: var(--muted); }
.gw-explore-chip.is-on .gw-chip-tag { color: inherit; opacity: .9; }
.gw-explore-panel { display: grid; gap: 6px; padding: 12px 14px; border-radius: 12px; background: var(--bg); border: 1px solid var(--border); }
.gw-explore-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.gw-explore-label { font-family: var(--serif); font-size: 22px; }
.gw-explore-tag { font-size: 12px; font-weight: 700; padding: 2px 8px; border-radius: 999px; background: var(--accent-soft); color: var(--accent); }
.gw-explore-body { margin: 0; font-size: 14px; line-height: 1.55; }
.gw-explore-egs { list-style: none; margin: 2px 0 0; padding: 0; display: grid; gap: 5px; }
.gw-explore-egs li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 9px; }
.gw-explore-cs { font-family: var(--serif); font-size: 16px; }
.gw-explore-en { font-size: 13px; color: var(--muted); }

/* flip cards */
.gw-flips { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); }
.gw-flip-cell { position: relative; }
.gw-flip-cell > .gw-hear { position: absolute; top: 6px; right: 6px; z-index: 2; width: 26px; height: 26px; }
.gw-flip { display: block; width: 100%; min-height: 108px; padding: 0; border: 0; background: none; cursor: pointer; perspective: 800px; font: inherit; color: var(--text); }
.gw-flip-inner { position: relative; display: block; min-height: 108px; transition: transform .45s cubic-bezier(.2, .7, .2, 1); transform-style: preserve-3d; }
.gw-flip.is-flipped .gw-flip-inner { transform: rotateY(180deg); }
.gw-flip-face {
  position: absolute; inset: 0; display: grid; align-content: center; gap: 4px; padding: 12px 14px; text-align: left;
  border-radius: 12px; border: 1.5px solid var(--border); backface-visibility: hidden; -webkit-backface-visibility: hidden;
}
.gw-flip-front { background: var(--card); }
.gw-flip-back { background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); transform: rotateY(180deg); }
.gw-flip-cs { font-family: var(--serif); font-size: 17px; font-weight: 600; padding-right: 22px; }
.gw-flip-en { font-size: 14px; font-weight: 600; }
.gw-flip-extra { font-size: 12.5px; color: var(--muted); }
.gw-flip-all { align-self: flex-start; background: var(--card); color: var(--accent); }
@media (prefers-reduced-motion: reduce) { .gw-flip-inner { transition: none; } }

/* tell the time */
.gw-clock { display: grid; grid-template-columns: 130px 1fr; gap: 16px; align-items: center; }
@media (max-width: 480px) { .gw-clock { grid-template-columns: 1fr; justify-items: center; } }
.gw-clock-face { width: 130px; height: 130px; }
.gw-clock-rim { fill: var(--bg); stroke: var(--border); stroke-width: 2; }
.gw-clock-tick { stroke: var(--muted); stroke-width: 1.5; }
.gw-clock-tick.is-main { stroke: var(--text); stroke-width: 2.5; }
.gw-clock-hour { stroke: var(--text); stroke-width: 5; stroke-linecap: round; }
.gw-clock-min { stroke: var(--accent); stroke-width: 3; stroke-linecap: round; }
.gw-clock-pin { fill: var(--accent); }
.gw-clock-side { display: grid; gap: 6px; min-width: 0; }
.gw-clock-digital { font-size: 28px; font-weight: 700; font-variant-numeric: tabular-nums; }
.gw-clock-said { margin: 0; font-size: 21px; font-weight: 600; }
.gw-clock-rows { display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; margin: 0; font-size: 13.5px; }
.gw-clock-rows dt { color: var(--muted); }
.gw-clock-rows dd { margin: 0; font-family: var(--serif); font-size: 15px; }

/* every table and every set of examples can test you (views/guide.js) */
.gd-table-foot { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 12px; max-width: none; }
.gd-table-foot:empty { display: none; }
.gd-cap-text { flex: 1 1 280px; min-width: 0; max-width: 62ch; }
.gd-cover {
  flex: none; font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; margin-left: auto;
  padding: 4px 11px; border-radius: 999px; border: 1px solid var(--border); background: var(--card); color: var(--accent);
}
.gd-cover:hover { border-color: var(--accent); }
.gd-cover[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.gd-table.is-covered td:not(.is-shown) {
  cursor: pointer; color: transparent; background: repeating-linear-gradient(135deg, var(--panel), var(--panel) 6px, var(--bg) 6px, var(--bg) 12px);
}
.gd-table.is-covered td:not(.is-shown) * { color: transparent !important; border-color: transparent !important; }
.gd-table.is-covered td.is-shown { background: color-mix(in srgb, var(--verb) 9%, transparent); }
.gd-eg-top { display: flex; align-items: baseline; gap: 7px; }
.gd-eg-say {
  flex: none; display: inline-grid; place-items: center; width: 24px; height: 24px; align-self: center; cursor: pointer;
  border-radius: 999px; border: 1px solid var(--border); background: var(--card); color: var(--accent);
}
.gd-eg-say:hover { border-color: var(--accent); }
.gd-egs.is-covered .gd-eg-en:not(.is-shown) {
  cursor: pointer; color: transparent; border-radius: 5px; user-select: none;
  background: repeating-linear-gradient(135deg, var(--panel), var(--panel) 6px, var(--bg) 6px, var(--bg) 12px);
}

/* practice widgets: the details a first look found */
.gw-pool[hidden], .gw-after[hidden] { display: none; }
.gw-why.is-near { background: color-mix(in srgb, var(--neut) 12%, var(--card)); }
.gw-why.is-near::before { content: "≈ "; color: var(--neut); font-weight: 700; }
.gw-end-slot { min-width: 1em; padding: 0 1px; text-align: left; }
.gw-spot .gw-tok { border-radius: 0; border-bottom: 2px dotted color-mix(in srgb, var(--muted) 70%, transparent); padding: 1px 2px; }
.gw-spot .gw-tok.is-picked { border-radius: 4px; }

/* ── Loading, slow, failed (static/js/loading.js) ──────────────────────────

   Skeletons shaped like the view they stand in for, a "still loading" line
   after a few seconds, and an error with Retry. Theme tokens only: --panel and
   --border for the bones, --card for the sheen over them, --warn for the error's
   edge — so light, dark and the feed's own dark scene all come out right
   without a colour of their own. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* What a box already held is hidden, not removed, while the skeleton or the
   error stands in for it — and only while one is actually there, so a render
   that clears the box brings its content straight back. */
.is-loading:has(> .sk) > :not(.sk),
.load-failed:has(> .load-error) > :not(.load-error) { display: none !important; }
.sk, .load-error { grid-column: 1 / -1; list-style: none; }
.sk { padding: 4px 0; }
.sk-body { display: flex; flex-direction: column; gap: 12px; }
.sk-bone {
  display: block; border-radius: 8px; background: color-mix(in srgb, var(--border) 45%, var(--panel));
  background-image: linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--card) 70%, transparent) 50%, transparent 100%);
  background-size: 200% 100%; background-repeat: no-repeat;
  animation: sk-sheen 1.4s ease-in-out infinite;
}
@keyframes sk-sheen { from { background-position: 150% 0; } to { background-position: -50% 0; } }
@media (prefers-reduced-motion: reduce) { .sk-bone { animation: none; background-image: none; } }
.sk-line { height: 12px; max-width: 100%; }
.sk-line.sk-small { height: 9px; }
.sk-line.sk-title { height: 18px; }
.sk-line.sk-big { height: 30px; }
.sk-bone.w20 { width: 20%; } .sk-bone.w25 { width: 25%; } .sk-bone.w30 { width: 30%; } .sk-bone.w40 { width: 40%; } .sk-bone.w50 { width: 50%; }
.sk-bone.w60 { width: 60%; } .sk-bone.w65 { width: 65%; } .sk-bone.w70 { width: 70%; } .sk-bone.w75 { width: 75%; } .sk-bone.w80 { width: 80%; }
.sk-bone.w85 { width: 85%; } .sk-bone.w90 { width: 90%; } .sk-bone.w95 { width: 95%; } .sk-bone.w100 { width: 100%; }
.sk-chip { width: 44px; height: 18px; border-radius: 999px; }
.sk-pill { width: 96px; height: 36px; border-radius: 999px; flex: none; }
.sk-pills { display: flex; flex-wrap: wrap; gap: 10px; }
.sk-pills.sk-center { justify-content: center; }
.sk-pills.sk-tabs .sk-pill { width: 84px; height: 30px; }
.sk-cats .sk-pill { width: 120px; height: 44px; border-radius: 12px; }
.sk-bar { height: 56px; border-radius: 12px; }
.sk-block { height: 150px; border-radius: 12px; }
.sk-block.sk-short { height: 90px; }
.sk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.sk-card, .sk-head, .sk-widget {
  display: flex; flex-direction: column; gap: 10px;
  border: 1px solid var(--border); border-radius: 14px; background: var(--card); padding: 16px 18px;
}
.sk-card { min-height: 132px; }
.sk-card.sk-wide { min-height: 84px; }
.sk-rows { display: flex; flex-direction: column; gap: 14px; }
.sk-row { display: flex; align-items: center; gap: 12px; }
.sk-stack { flex: 1; display: flex; flex-direction: column; gap: 7px; }
.sk-dot { width: 26px; height: 26px; border-radius: 50%; flex: none; }
.sk-lines { padding: 8px 4px; }
.sk-bands { display: flex; gap: 4px; }
.sk-band { flex: 1; height: 46px; border-radius: 6px; }
.sk-split { display: grid; grid-template-columns: 220px 1fr; gap: 24px; }
.sk-rail, .sk-article { display: flex; flex-direction: column; gap: 12px; }
@media (max-width: 720px) { .sk-split { grid-template-columns: 1fr; } .sk-rail { display: none; } }
.sk-widget { min-height: 260px; }
.gd-widget > .sk { min-height: 290px; }
.gd-widget[data-name="secondposition"] > .sk { min-height: 400px; }
.gd-widget[data-name="negate"] > .sk { min-height: 280px; }
.sk-flash {
  align-items: center; justify-content: center; gap: 14px; min-height: 280px; margin: 8px auto 18px;
  max-width: 520px; width: 100%; border: 1px solid var(--border); border-radius: 18px; background: var(--card);
}
.sk-flash .sk-line { margin: 0 auto; }
/* Tune In: the stream is a dark scene in either theme, and .fd-card's own
   tokens (shared below) are what make the bones show on it */
.sk-feed { padding: 24px 22px 18px; }
.sk-feed .sk-body { flex: 1; justify-content: flex-end; }
.sk-feed-foot { display: flex; flex-direction: column; gap: 12px; }
.sk-feed .sk-note { text-align: center; }
.sk-note { margin: 12px 0 0; font-size: 13px; color: var(--muted); }

.load-error {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  margin: 8px 0 16px; padding: 14px 16px; border-radius: 12px;
  border: 1px solid var(--border); border-left: 4px solid var(--warn); background: var(--card); color: var(--text);
}
.load-error-msg { margin: 0; font-size: 14px; font-weight: 600; }
.load-error-detail { margin: 0; font-size: 12px; color: var(--muted); }
.load-error .load-retry { margin-top: 6px; }
.fd-stream > .load-error { margin: 24px 18px; }

/* ── native reviewers (static/js/review.js, views/reviewer.js, Admin → Reviews)
   Small on purpose: a reviewer's button sits with the line's other buttons
   and shows on hover like them, unless a question is waiting on that line.
   Colours are the theme's tokens only. */
.t-review.has-q { opacity: 1 !important; color: var(--neut); border-color: var(--neut); }
.t-review.has-q span { font-variant-numeric: tabular-nums; font-weight: 600; }
.sent-pop .t-review, #sent-pop .t-review { margin-left: 6px; }
.pop-review { margin-top: 8px; }
.rv-form { gap: 10px; }
.rv-form textarea.auth-input { font-size: 15px; resize: vertical; min-height: 44px; }
.rv-select { font-size: 15px; padding: 8px 10px; }
.rv-quoted { margin: 0; padding: 8px 10px; border-left: 3px solid var(--border); font-family: var(--serif);
  font-size: 15px; line-height: 1.45; color: var(--text); background: var(--panel); border-radius: 0 8px 8px 0; }
.rv-question { font-size: 13.5px; }
.rv-more { margin: 10px 0 0; font-size: 13px; }
.rv-own { margin-top: 10px; font-size: 13px; }
.rvw-row { align-items: flex-start; gap: 12px; }
.rvw-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; padding: 8px 0; }
.rvw-q { margin: 0; font-size: 14px; line-height: 1.45; }
.rvw-note { margin: 0; font-size: 12.5px; }
.rvw-acts { display: flex; flex-direction: column; gap: 6px; padding-top: 8px; }
.rvw-status { align-self: center; }
.rvw-status.accepted { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.rvw-status.rejected { background: color-mix(in srgb, var(--muted) 12%, transparent); color: var(--text); }
.primary-btn.tiny { padding: 3px 10px; font-size: 12px; }
.adm-rv { border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; margin: 8px 0; background: var(--card);
  display: flex; flex-direction: column; gap: 6px; }
.adm-rv-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.adm-rv-q, .adm-rv-note, .adm-rv-done { margin: 0; font-size: 13px; line-height: 1.45; }
.adm-rv-quoted { margin: 0; font-family: var(--serif); font-size: 14.5px; padding-left: 8px; border-left: 3px solid var(--border); }
.adm-rv-text { width: 100%; font-size: 13.5px; }
.adm-check { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; color: var(--muted); }

/* ── The learner loop (Lane E): the day's goal, words known, the level test ──
   Theme tokens only, the level colours from .lv-* (the stripe IS the level),
   and the tile shapes Today already uses (.wotd-card, .td-cardstile). */

/* Today's heading carries the day on its right; on a phone it drops below */
.td-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px 20px; flex-wrap: wrap; }
.td-head-main { flex: 1 1 320px; min-width: 0; }
.td-day[hidden] { display: none; }
.td-day { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; margin-bottom: 14px; }
.td-goal {
  display: inline-flex; align-items: center; gap: 10px; font: inherit; color: var(--text); cursor: pointer;
  padding: 4px 14px 4px 4px; border-radius: 999px; border: 1px solid var(--border); background: var(--card);
  text-align: left;
}
.td-goal:hover { border-color: var(--accent); }
.td-goal:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.td-ring-box { position: relative; display: inline-flex; width: 48px; height: 48px; flex: none; }
.td-ring { display: block; }
.td-ring-track { fill: none; stroke: var(--border); stroke-width: 5; }
.td-ring-fill { fill: none; stroke: var(--accent); stroke-width: 5; stroke-linecap: round; transition: stroke-dasharray .4s ease-out; }
.td-goal.is-met .td-ring-fill { stroke: var(--verb); }
.td-ring-n {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.td-goal.is-met .td-ring-n { color: var(--verb); }
.td-goal-text { display: grid; gap: 1px; }
.td-goal-text strong { font-size: 14px; font-variant-numeric: tabular-nums; }
.td-goal-text span { font-size: 12px; color: var(--muted); }
.td-streak { display: inline-flex; align-items: baseline; gap: 6px; font-size: 12px; color: var(--muted); padding-right: 6px; }
.td-streak-n { font-size: 15px; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.td-goal-sheet p { margin: 0 0 14px; font-size: 14px; line-height: 1.55; }
.td-goal-sheet .td-goal-how { margin: 14px 0 0; font-size: 12.5px; color: var(--muted); }
.td-goal-choices { display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: 8px; }
.td-goal-choice {
  display: grid; justify-items: center; gap: 0; font: inherit; cursor: pointer; min-height: 56px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card); color: var(--text); padding: 6px 4px;
}
.td-goal-choice strong { font-size: 18px; font-variant-numeric: tabular-nums; }
.td-goal-choice span { font-size: 11.5px; color: var(--muted); }
.td-goal-choice:hover { border-color: var(--accent); }
.td-goal-choice.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
@media (max-width: 620px) {
  .td-day { flex-direction: row; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
}

/* words you know, or the way into the level test */
.td-words:empty { display: none; }
.td-words-card {
  border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px;
  background: var(--card); display: flex; flex-direction: column; gap: 6px;
}
.td-words-card .wotd-tag { margin: 0; }
.td-words-ask { font-size: 16px; line-height: 1.4; }
.td-words-n { margin: 0; display: flex; align-items: baseline; gap: 6px; }
.td-words-n strong { font-size: 24px; font-variant-numeric: tabular-nums; }
.td-words-n span { font-size: 14px; color: var(--muted); }
.td-words-why { margin: 0; font-size: 12.5px; color: var(--muted); line-height: 1.5; max-width: 62ch; }
.td-words-card .td-ct-go { justify-self: start; align-self: flex-start; }
.td-words-foot { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 13px; margin-top: 2px; }
.td-wbands { display: grid; gap: 6px; margin: 4px 0 2px; max-width: 420px; }
.td-wb { display: grid; grid-template-columns: 34px 1fr 38px; align-items: center; gap: 10px; }
.td-wb .dc-band { justify-self: start; }
.td-wb-n { font-size: 12px; color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }

/* the Course page: words met per level, under the level's own bar */
.co-words { display: grid; gap: 4px; margin: 10px 0 0; }
.co-words-track { max-width: 100%; position: relative; }
.co-words-track .co-fill { position: absolute; left: 0; top: 0; }
.co-fill-est { opacity: 0.35; }
.co-words-l { font-size: 12.5px; color: var(--muted); }
.co-level-words { padding: 2px 14px 6px; }

/* the level test (static/js/views/placement.js) */
.pt { max-width: 62ch; }
.pt-head h2 { margin: 0 0 4px; }
.pt-why { margin: 0 0 18px; color: var(--muted); font-size: 14.5px; line-height: 1.5; }
.pt-loading { color: var(--muted); font-size: 14px; }
.pt-card {
  border: 1px solid var(--border); border-left: 4px solid var(--lv, var(--accent)); border-radius: 12px;
  background: var(--card); padding: 16px 18px 18px; display: flex; flex-direction: column; gap: 12px;
}
.pt-intro { border-left-color: var(--accent); }
.pt-intro-line { margin: 0; font-size: 15px; line-height: 1.5; }
.pt-intro-line.muted { font-size: 13.5px; color: var(--muted); }
.pt-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 4px; }
.pt-progress { display: grid; grid-template-columns: auto auto 1fr; align-items: center; gap: 10px; }
.pt-count { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.pt-word { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 4px; }
.pt-headword { font-family: var(--serif); font-size: 34px; font-weight: 600; line-height: 1.15; }
.pt-hear { min-height: 32px; }
.pt-ask { margin: 0; font-size: 13px; color: var(--muted); }
.pt-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 8px; }
.pt-option {
  display: flex; align-items: center; gap: 10px; text-align: left; font: inherit; font-size: 15px; cursor: pointer;
  min-height: 48px; padding: 8px 12px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--card); color: var(--text);
}
.pt-option:hover, .pt-option:focus-visible { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px var(--accent-soft); }
.pt-key {
  flex: none; display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px;
  border-radius: 6px; background: var(--panel); color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums;
}
.pt-dunno { align-self: flex-start; font-size: 13.5px; }
.pt-tag { margin: 0; font-size: 10.5px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted); }
.pt-level { display: flex; align-items: center; gap: 10px; }
.pt-level strong { font-size: 22px; }
.pt-says, .pt-words { margin: 0; font-size: 14.5px; line-height: 1.55; }
.pt-words span { font-weight: 600; }
.pt-bands { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.pt-band { display: flex; align-items: center; gap: 10px; font-size: 13.5px; }
.pt-band-score { font-variant-numeric: tabular-nums; }
.pt-band.is-untested .pt-band-score { color: var(--muted); }
.pt-band-ok { display: inline-flex; align-items: center; gap: 4px; color: var(--verb); font-size: 12.5px; }
.pt-missed h3 { margin: 4px 0 6px; font-size: 14px; }
.pt-missed ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.pt-missed li { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; font-size: 14px; }
.pt-missed-word { font-family: var(--serif); font-size: 15.5px; text-decoration: none; color: var(--text); font-weight: 600; }
.pt-missed-word:hover { color: var(--accent); text-decoration: underline; }
.pt-missed-gloss { color: var(--muted); }
.pt-note { margin: 0; font-size: 12.5px; color: var(--muted); }
@media (max-width: 560px) {
  .pt-headword { font-size: 28px; }
  .pt-options { grid-template-columns: 1fr; }
}

/* ── The reader's listening drills (Lane E, static/js/listening.js) ─────────
   Dictation hides the line until it is checked; a pronunciation score colours
   the line's own words. Theme tokens only: the verb/neuter/feminine hues are
   the same green/amber/red the levels already use for easy/middling/hard. */
/* while dictating, nothing on the line gives the words away: not the text,
   not the translation, not the teacher's note that quotes them */
.rl.dictating .rl-text, .rl.dictating .rl-sub { visibility: hidden; }
.rl.dictating .rl-note, .rl.dictating .rl-gram { display: none; }
.rl.dictating .rl-head .t-btn, .rl-head .t-score { opacity: 1; }
.t-score { color: var(--accent); border-color: var(--accent); }
.t-score.busy { opacity: .6; cursor: wait; }
.dt-box {
  margin: 8px 0 2px; padding: 10px 12px; border-radius: 10px; background: var(--panel);
  display: grid; gap: 8px; cursor: default;
}
.dt-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dt-input {
  flex: 1 1 220px; min-width: 0; font: inherit; font-family: var(--serif); font-size: 17px;
  padding: 7px 10px; border-radius: 8px; border: 1px solid var(--border); background: var(--card); color: var(--text);
}
.dt-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.dt-close { font-size: 12.5px; }
.dt-result:empty { display: none; }
.dt-verdict { margin: 0; font-size: 13.5px; font-weight: 600; }
.dt-verdict.is-got { color: var(--verb); }
.dt-verdict.is-near { color: var(--neut); }
.dt-verdict.is-again { color: var(--text); }
.dt-words { margin: 0; display: flex; flex-wrap: wrap; gap: 4px 8px; font-family: var(--serif); font-size: 16px; }
.dt-w { border-bottom: 2px solid transparent; }
.dt-w.is-ok { border-bottom-color: color-mix(in srgb, var(--verb) 55%, transparent); }
.dt-w.is-near { border-bottom-color: var(--neut); color: var(--neut); }
.dt-w.is-wrong { border-bottom-color: var(--warn); color: var(--warn); }
.dt-w.is-missed { color: var(--muted); border-bottom: 2px dotted var(--muted); }
.dt-w.is-extra { color: var(--muted); text-decoration: line-through; }

/* a pronunciation score: each word of the line marked in place, and one line
   under it. A tint and an underline, never the text colour: the text colour
   is already the word's gender (body.colored), and a red feminine noun must
   not read as a badly said one. */
.rl-text .word.pr-good { background: color-mix(in srgb, var(--verb) 14%, transparent); border-bottom-color: var(--verb); }
.rl-text .word.pr-fair { background: color-mix(in srgb, var(--neut) 16%, transparent); border-bottom-color: var(--neut); }
.rl-text .word.pr-poor { background: color-mix(in srgb, var(--warn) 16%, transparent); border-bottom-color: var(--warn); }
.rl-text .word.pr-miss { border-bottom: 2px dotted var(--muted); }
.pr-strip {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px; margin: 8px 0 0;
  font-size: 12.5px; color: var(--muted);
}
.pr-strip .icon { align-self: center; color: var(--accent); }
.pr-score { font-size: 15px; font-variant-numeric: tabular-nums; }
.pr-score.pr-good { color: var(--verb); }
.pr-score.pr-fair { color: var(--neut); }
.pr-score.pr-poor { color: var(--warn); }
.pr-left { margin-left: auto; font-variant-numeric: tabular-nums; }
/* five reading toggles now, not four: they wrap rather than squeeze each
   label into a column a word wide */
.srow-toggles { flex-wrap: wrap; gap: 8px 16px; }
.srow-toggles .toggle { white-space: nowrap; }
/* ── Lane F (p7-billing): the Account view and the plan sheet ─────────────
   static/js/views/account.js and shell.js showPlanSheet. Cards of the same
   shape as the rest of the app; nothing here is new type or colour. */
.acct { max-width: 640px; }
.acct-body { display: flex; flex-direction: column; gap: 14px; }
.acct-card { padding: 16px 20px 18px; }
.acct-card .sv-title { margin-bottom: 10px; }
.acct-card > p { margin: 0 0 12px; }
.acct-card > p:last-child { margin-bottom: 0; }
.acct-card .auth-actions { margin-top: 4px; }
.acct-card .close-account .muted { font-size: 13px; margin: 8px 0 0; }
.acct-plan { margin: 0 0 12px; }
.acct-plan p { margin: 0; }
.acct-plan-name { display: flex; align-items: center; gap: 8px; font-family: var(--serif); font-size: 22px; line-height: 1.25; }
.acct-plan-name .icon { color: var(--accent); }
.acct-plan .muted { margin-top: 4px; font-size: 14px; }
.acct-receipts { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; }
.acct-receipts li { display: grid; grid-template-columns: 1fr auto minmax(0, 9rem); gap: 12px; align-items: baseline; padding: 8px 0; border-top: 1px solid var(--border); font-size: 14px; }
.acct-receipts li > :last-child { text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-card a.ghost-btn { text-decoration: none; color: var(--text); }
.acct-card > p.muted { font-size: 14px; }
.acct-receipts li:first-child { border-top: 0; padding-top: 0; }
.acct-receipt-amount { font-variant-numeric: tabular-nums; }
.acct-receipts a { color: var(--accent); }
#acct-notice:not(:empty) { margin-bottom: 14px; }
#acct-notice .notice { margin: 0; }
.plan-sheet { display: flex; flex-direction: column; gap: 12px; }
.plan-sheet p { margin: 0; }
.plan-what { font-family: var(--serif); font-size: 19px; line-height: 1.3; }
.plan-list { display: flex; flex-direction: column; gap: 8px; }
.plan-row { display: grid; grid-template-columns: 1fr auto auto; gap: 12px; align-items: center; padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--card); }
.plan-row.is-best { border: 2px solid var(--accent); background: var(--accent-soft); }
.plan-row-name { font-weight: 600; }
.plan-row-price { color: var(--muted); font-size: 14px; font-variant-numeric: tabular-nums; }
@media (max-width: 420px) {
  .plan-row { grid-template-columns: 1fr auto; }
  .plan-row button { grid-column: 1 / -1; justify-content: center; }
  .acct-receipts li { grid-template-columns: 1fr auto; }
  .acct-receipts li > :last-child { grid-column: 1 / -1; text-align: left; }
}

/* ── Lane T1: the tutor (static/js/views/tutor.js, static/js/tutor/board.js) ──
   Two panes: the conversation, and the board the tutor puts things on. The
   board only takes room once something is on it (.has-board); on a phone it
   sits under the conversation. */
.tutor { display: flex; flex-direction: column; gap: 12px; max-width: 1180px; }
.tutor-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.tutor-head h2 { margin: 0; }
/* the fox (static/js/tutor/mascot.js): data-state idle | listening | thinking
   | speaking; --fox-open (0..1) is how far the snout is open. Flat shapes in
   the palette's warm orange; still under prefers-reduced-motion */
.tutor-title { display: flex; align-items: center; gap: 10px; min-width: 0; }
.tutor-fox { --fox-fur: #d9692a; --fox-cream: #f8e7cf; --fox-ink: #2b211b; --fox-open: 0;
  display: flex; flex-direction: column; align-items: center; gap: 0; flex: none; }
.tutor-fox[hidden] { display: none; }
.tutor-fox-name { font-size: 12px; font-weight: 600; color: var(--muted); line-height: 1.1; }
.fox { width: 64px; height: 64px; display: block; overflow: visible; }
.fox .fox-fur { fill: var(--fox-fur); }
.fox .fox-cream { fill: var(--fox-cream); }
.fox .fox-ink, .fox .fox-mouth, .fox .fox-dots { fill: var(--fox-ink); }
.fox .fox-dots { fill: var(--muted); opacity: 0; }
.fox-all { transform-origin: 60px 118px; transform-box: view-box; }
.fox-ear { transform-box: view-box; transition: transform .25s ease; }
.fox-ear-l { transform-origin: 40px 40px; }
.fox-ear-r { transform-origin: 80px 40px; }
.fox-tail { transform-box: view-box; transform-origin: 80px 104px; }
.fox-mouth { transform-box: view-box; transform-origin: 60px 73px; transform: scaleY(var(--fox-open)); }
.fox-jaw { transform: translateY(calc(var(--fox-open) * 7px)); }
.tutor-fox[data-state="idle"] .fox-all { animation: fox-breathe 4s ease-in-out infinite; }
.tutor-fox[data-state="listening"] .fox-ear-l { transform: translateY(-4px) rotate(-8deg); }
.tutor-fox[data-state="listening"] .fox-ear-r { transform: translateY(-4px) rotate(8deg); }
.tutor-fox[data-state="thinking"] .fox-tail { animation: fox-swish 1.2s ease-in-out infinite; }
.tutor-fox[data-state="thinking"] .fox-dots { opacity: 1; }
.tutor-fox[data-state="thinking"] .fox-dots circle { animation: fox-dot 1.2s ease-in-out infinite; }
.tutor-fox[data-state="thinking"] .fox-dots circle:nth-child(2) { animation-delay: .2s; }
.tutor-fox[data-state="thinking"] .fox-dots circle:nth-child(3) { animation-delay: .4s; }
@keyframes fox-breathe { 0%, 100% { transform: scale(1, 1); } 50% { transform: scale(1.012, 1.03); } }
@keyframes fox-swish { 0%, 100% { transform: rotate(0deg); } 50% { transform: rotate(-12deg); } }
@keyframes fox-dot { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .tutor-fox { --fox-fur: #e98a4c; --fox-cream: #f3dcc0; --fox-ink: #1d1712; }
}
:root[data-theme="dark"] .tutor-fox { --fox-fur: #e98a4c; --fox-cream: #f3dcc0; --fox-ink: #1d1712; }
@media (prefers-reduced-motion: reduce) {
  .tutor-fox .fox-all, .tutor-fox .fox-tail, .tutor-fox .fox-dots circle { animation: none !important; }
  .tutor-fox .fox-ear { transition: none; }
  .tutor-fox .fox-mouth { transform: scaleY(0); }
  .tutor-fox .fox-jaw { transform: none; }
}
.tutor-panes { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
.tutor.has-board .tutor-panes { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
.tutor-talk { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.tutor-log { display: flex; flex-direction: column; gap: 8px; max-height: 62vh; overflow-y: auto; padding: 2px; }
.tutor-msg { max-width: 88%; padding: 9px 13px; border-radius: 14px; line-height: 1.45; }
.tutor-msg p { margin: 0; white-space: pre-wrap; }
.tutor-tutor { align-self: flex-start; background: var(--card); border: 1px solid var(--border); }
.tutor-learner { align-self: flex-end; background: var(--accent-soft); }
.tutor-msg.is-live p::after { content: "▍"; color: var(--muted); margin-left: 2px; }
.tutor-status { min-height: 1.2em; font-size: 13px; }
/* the dev timing line (TUTOR_DEBUG_TIMING=1): red past the 1.5 s goal */
.tutor-timing { font: 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--muted, #888);
  padding: 2px 6px; border-radius: 6px; background: var(--card); border: 1px dashed var(--border); overflow-wrap: anywhere; }
.tutor-timing.is-slow { color: #c0392b; border-color: #c0392b; }
.tutor-input { display: flex; flex-direction: column; gap: 8px; }
.tutor-input textarea { width: 100%; resize: vertical; font: inherit; padding: 9px 11px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--card); color: var(--text); }
.tutor-buttons { display: flex; gap: 8px; justify-content: flex-end; }
.tutor-gate { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.tutor-summary { margin-top: 6px; }
/* Stage G: the paywall card and the minutes / trial notices (static/js/tutor/paywall.js) */
.tutor-paywall { display: flex; flex-direction: column; gap: 6px; max-width: 520px; width: 100%; margin: 8px 0; }
.tutor-paywall h4 { margin: 0; }
.tutor-paywall p { margin: 0; }
.tutor-paywall .tp-trial { font-weight: 600; }
.tutor-paywall .tp-buttons { justify-content: flex-start; flex-wrap: wrap; margin-top: 4px; }
.tutor-paywall .tp-refund, .tutor-paywall .tp-topup-note { font-size: 13px; }
.tutor-paywall .tp-cancel-line a, .tutor-paywall .tp-cancel-line .linkish { color: var(--accent); font-size: 14px; }
.tutor-paywall .tp-error:empty { display: none; }
.tutor-notices:empty { display: none; }
.tutor-notices { display: flex; flex-direction: column; gap: 6px; margin: 6px 0; }
.tutor-notice { margin: 0; }
.tutor-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.tutor-chips .chip:disabled { opacity: .5; cursor: default; }
.tutor-hint { font-size: 13px; }
.tutor-summary h4 { margin: 0 0 4px; }
/* Stage E: the end-of-lesson recap (static/js/tutor/summary.js) */
.ts-recap { display: flex; flex-direction: column; gap: 10px; margin: 8px 0 10px; }
.ts-part h5 { margin: 0 0 4px; font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.ts-part ul { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; }
.ts-fix s { color: var(--muted); }
.ts-word-list { flex-direction: row !important; flex-wrap: wrap; gap: 6px 12px !important; list-style: none; padding-left: 0 !important; }
.ts-word { display: inline-flex; align-items: center; gap: 4px; }
.ts-add { font-size: 12px; padding: 2px 8px; display: inline-flex; align-items: center; gap: 3px; vertical-align: middle; }
.ts-add:disabled { opacity: .65; cursor: default; }
@media (pointer: fine) { .ts-add { min-height: 30px; } }
.ts-error:empty { display: none; }
.ts-error { margin: 0; font-size: 12.5px; }
.tutor-board { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.tutor-board:empty { display: none; }
/* the lessons (views/tutor.js, tutor/lessons.js) */
.tutor-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin: 6px 0 4px; }
.tutor-tab { font: inherit; font-size: 14px; padding: 7px 14px; border: 0; background: none; color: var(--muted);
  border-bottom: 2px solid transparent; margin-bottom: -1px; cursor: pointer; }
.tutor-tab[aria-selected="true"] { color: var(--text); border-bottom-color: var(--accent); font-weight: 600; }
.tutor-unit { padding: 10px 14px; }
.tutor-unit p { margin: 4px 0 0; font-size: 13.5px; }
.tutor-unit-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tutor-unit-step { font-size: 13px; }
.tutor-lessons { display: flex; flex-direction: column; gap: 14px; }
.tl-note:empty { display: none; }
.tl-next { padding: 14px 16px; }
.tl-next h4 { margin: 2px 0 4px; }
.tl-next p { margin: 0 0 8px; }
.tl-group h3 { margin: 0 0 6px; font-size: 15px; }
.tl-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.tl-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--border);
  border-radius: 10px; background: var(--card); }
.tl-title { display: flex; flex-direction: column; flex: 1; min-width: 0; font-size: 14px; }
.tl-title .muted { font-size: 12.5px; }
.tl-tick { display: inline-flex; width: 18px; justify-content: center; color: var(--accent); }
.tl-custom { display: flex; flex-direction: column; gap: 8px; padding: 14px 16px; align-items: flex-start; }
.tl-custom h4 { margin: 0; }
.tl-custom label { display: flex; flex-direction: column; gap: 3px; font-size: 13px; width: 100%; max-width: 420px; }
.tl-custom input { font: inherit; padding: 7px 10px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--card); color: var(--text); }
.tl-free { align-self: flex-start; }
.tutor-score { display: flex; align-items: center; gap: 4px; margin: 0 0 4px; font-weight: 600; }
/* Today's tutor cards (views/today.js) */
.td-tutor { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; margin: 18px 0 0; }
.td-tutor-card { padding: 14px 16px; display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.td-tutor-card h4 { margin: 0; display: flex; align-items: center; gap: 6px; }
.td-tutor-card p { margin: 0; font-size: 13.5px; }
.td-tutor-card .tl-tick { width: auto; }
.td-word { font-family: var(--serif); font-size: 20px; }
/* the voice (views/tutor.js): --tutor-in is the mic's level, --tutor-out the tutor's, 0..1 */
.tutor-voice { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; justify-content: space-between; font-size: 13px; }
.tutor-voice[hidden], .tutor-mic[hidden], .tutor-out[hidden] { display: none; }
.tutor-mic, .tutor-out { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.tutor-mic-btn { display: inline-flex; align-items: center; gap: 4px; padding: 8px 14px; border-radius: 999px; font: inherit;
  border: 1px solid var(--border); background: var(--card); color: inherit; cursor: pointer; touch-action: none;
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.tutor-mic-btn.is-on { background: var(--accent-soft); border-color: var(--accent);
  box-shadow: 0 0 0 calc(var(--tutor-in, 0) * 8px) var(--accent-soft); }
.tutor-mic-btn:disabled { opacity: .5; cursor: default; }
.tutor-voice select { font: inherit; }
.tutor-voice-pick[hidden] { display: none; }
.tutor-speak { display: inline-flex; gap: 4px; align-items: center; }
.tutor.is-speaking .tutor-tutor:last-child { box-shadow: 0 0 0 calc(var(--tutor-out, 0) * 4px) var(--accent-soft); }
.tb-item { padding: 12px 14px; overflow: auto; max-height: 72vh; }
.tb-title { margin: 0 0 8px; font-size: 14px; }
.tb-forms .paradigm h3 { display: none; }
.tb-hit { outline: 2px solid var(--accent); border-radius: 4px; background: var(--accent-soft); }
.tb-options { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.tb-line { font-size: 16px; margin: 0 0 4px; }
.tb-item .gd-topic { box-shadow: none; border: 0; padding: 0; margin: 0; }
/* the tutor's feedback (static/js/tutor/feedback.js) */
.tutor-msg .tf-trans { color: var(--muted); font-size: 13.5px; margin-top: 3px; }
.tf-reveal { font-size: 12.5px; margin-top: 3px; padding: 0; }
.tf-line { display: flex; align-items: baseline; gap: 8px; }
.tf-ask { flex: none; width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--accent); background: var(--card);
  color: var(--accent); font: inherit; font-size: 12px; font-weight: 700; line-height: 1; cursor: pointer; padding: 0; }
.tf-ask:disabled { opacity: .5; cursor: default; }
.tf-card { margin-top: 8px; padding: 9px 11px; border-radius: 10px; background: var(--card); border: 1px solid var(--border);
  border-left: 3px solid var(--warn); display: flex; flex-direction: column; gap: 4px; color: var(--text); }
.tf-card[data-kind="word"], .tf-card[data-kind="register"] { border-left-color: var(--neut); }
.tutor-msg .tf-card p { white-space: normal; }
.tf-said { color: var(--muted); }
.tf-wrong { color: var(--warn); text-decoration-thickness: 2px; }
.tf-better { font-size: 15.5px; font-weight: 600; }
.tf-arrow { color: var(--muted); font-weight: 400; }
.tf-tap { border: 0; background: none; font: inherit; color: inherit; padding: 0 1px; cursor: pointer; border-bottom: 1px dotted var(--accent); }
.tf-tap:hover { color: var(--accent); }
.tf-why { font-size: 13.5px; }
.tf-tools { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.tf-tools .ghost-btn { display: inline-flex; align-items: center; gap: 3px; font-size: 12.5px; }
.tf-table { margin-top: 4px; overflow-x: auto; }
.tf-score { margin-top: 6px; display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.tf-words { display: flex; flex-wrap: wrap; gap: 4px 6px; }
.tf-word { padding: 0 4px; border-radius: 4px; border-bottom: 2px solid currentColor; }
.tf-word.pr-good { color: var(--verb); }
.tf-word.pr-fair { color: var(--neut); }
.tf-word.pr-poor, .tf-word.pr-miss { color: var(--warn); }
.tf-word.pr-miss { text-decoration: line-through; }
.tf-prefs { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; font-size: 13px; }
.tf-pref { display: inline-flex; gap: 4px; align-items: center; }
.tf-pref select { font: inherit; }
.tf-note { flex-basis: 100%; margin: 0; font-size: 12.5px; }
.tf-note:empty { display: none; }
.tf-memory { flex-basis: 100%; display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  border-top: 1px solid var(--border); padding-top: 8px; }
.tf-memory h5 { margin: 0; font-size: 13px; }
.tf-memory-text { margin: 0; white-space: pre-line; }
@media (max-width: 720px) {
  .tutor.has-board .tutor-panes { grid-template-columns: minmax(0, 1fr); }
  .tutor-log { max-height: 50vh; }
  .tutor-msg { max-width: 94%; }
  .fox { width: 52px; height: 52px; }
}

/* ---------- collapsible sections (static/js/collapsible.js; timeline + atlas) ---------- */
.cl { border-top: 1px solid var(--border); }
.cl:last-child { border-bottom: 1px solid var(--border); }
.cl-head { margin: 0; font-size: 15px; font-weight: 600; }
.cl-toggle {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px;
  padding: 10px 4px; background: none; border: 0; color: var(--text);
  font: inherit; text-align: left; cursor: pointer;
}
.cl-toggle:hover .cl-title { color: var(--accent); }
.cl-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.cl-title { flex: 1 1 auto; min-width: 0; }
.cl-sum { flex: 0 0 auto; color: var(--muted); font-weight: 400; font-size: 13px; }
.cl-chev {
  flex: 0 0 auto; width: 9px; height: 9px; margin-right: 4px;
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: rotate(45deg) translate(-2px, -2px);
}
.cl-open > .cl-head .cl-chev { transform: rotate(225deg) translate(-2px, -2px); }
.cl-body { padding: 2px 4px 14px; }
.cl-body > .cl-empty { margin: 4px 0; }
.cl .cl { margin-left: 4px; }
.cl .cl-head { font-size: 14px; }
@media (prefers-reduced-motion: no-preference) {
  .cl-chev { transition: transform .18s ease; }
  .cl-open > .cl-body { animation: cl-in .18s ease; }
  @keyframes cl-in { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
}

/* ---------- the culture atlas's maps (static/js/atlas/map.js): a topic's small map in the
   Atlas is still drawn with them (explore/topic.js locator). ---------- */
.atlas-map { margin: 0; }
.am-stage {
  position: relative; width: 100%; overflow: hidden; border-radius: 16px;
  background: color-mix(in srgb, var(--accent-soft) 55%, var(--card));
  border: 1px solid var(--border); box-shadow: var(--shadow);
}
.am-stage svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.am-c { fill: var(--panel); stroke: var(--border); stroke-width: 0.6; vector-effect: non-scaling-stroke; transition: fill 0.2s; }
.am-reach { fill: color-mix(in srgb, var(--accent) 10%, var(--panel)); }
.am-area { fill: color-mix(in srgb, var(--accent) 24%, var(--card)); stroke: color-mix(in srgb, var(--accent) 45%, var(--border)); cursor: pointer; }
.am-area.hot { fill: color-mix(in srgb, var(--accent) 42%, var(--card)); }
.am-fine .am-c { stroke-width: 0.8; }
.am-labels { position: absolute; inset: 0; pointer-events: none; }
.am-label {
  position: absolute; display: inline-flex; align-items: center; gap: 6px; pointer-events: auto;
  translate: -7px -50%; padding: 3px 9px 3px 4px; border-radius: 999px; min-height: 30px;
  background: color-mix(in srgb, var(--card) 88%, transparent); border: 1px solid var(--border);
  color: var(--text); font-size: 13px; font-weight: 600; text-decoration: none; white-space: nowrap;
  box-shadow: var(--shadow); transition: background 0.15s, color 0.15s, opacity 0.25s; cursor: pointer;
  font-family: inherit;
}
.am-label:hover, .am-label.hot, .am-label:focus-visible {
  background: var(--accent); color: var(--on-accent); border-color: var(--accent); outline: none; z-index: 2;
}
.am-label:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent); }
.am-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--accent); border: 2px solid var(--card); flex: none; }
.am-label.hot .am-dot, .am-label:hover .am-dot { background: var(--on-accent); border-color: var(--accent); }
.am-point { font-size: 12px; font-weight: 500; min-height: 26px; }
.am-point.am-still { cursor: default; background: color-mix(in srgb, var(--card) 70%, transparent); box-shadow: none; }
.am-point.am-still:hover { background: color-mix(in srgb, var(--card) 70%, transparent); color: var(--text); border-color: var(--border); }
.am-point.am-still .am-dot { background: var(--muted); }
.am-own { font-weight: 700; }
.am-stage.zooming .am-label:not(.hot) { opacity: 0; }
.am-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-top: 8px; font-size: 12px; color: var(--muted); }
.am-key { width: 12px; height: 12px; border-radius: 3px; border: 1px solid var(--border); }
.am-key + span { margin-right: 10px; }
.am-key-area { background: color-mix(in srgb, var(--accent) 24%, var(--card)); }
.am-key-reach { background: color-mix(in srgb, var(--accent) 10%, var(--panel)); }
.am-locator { border-radius: 12px; }
.am-pin { fill: var(--accent); stroke: var(--card); stroke-width: 2; vector-effect: non-scaling-stroke; }

@media (prefers-reduced-motion: reduce) {
  .am-c, .am-label { transition: none; }
}

@media (max-width: 720px) {
  .am-label { font-size: 12px; min-height: 26px; padding: 2px 8px 2px 3px; }
  .am-point .am-name { display: none; }
  .am-point.am-own .am-name { display: inline; }
}
/* easily confused words (static/engine/confusables.js): why this word is not the other one */
.popover .cf-note { margin-top: 9px; padding: 8px 10px; border-radius: 8px; background: var(--card2, rgba(0,0,0,.04)); border: 1px solid var(--border); font-size: 13.5px; line-height: 1.4; max-width: 320px; }
.popover .cf-note .cf-head { display: block; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin-bottom: 3px; }
.popover .cf-note p { margin: 0; }
.popover .cf-note p + p { margin-top: 6px; }
.popover .cf-note b { font-family: var(--serif); }
