/* Dark, full-screen vertical feed in a developer-tool look: charcoal ground, hairline borders, square corners, one accent,
   monospace labels. Every colour comes from the token block of the active theme (<html data-theme>, see theme.ts); the rules
   below use tokens only, so a new theme is one more block here. Original styling; no third-party name, logo, mascot or text. */
@font-face { font-family: Inter; font-weight: 100 900; font-display: swap; src: url(/fonts/inter-latin-wght-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family: Inter; font-weight: 100 900; font-display: swap; src: url(/fonts/inter-vietnamese-wght-normal.woff2) format("woff2");
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB; }
@font-face { font-family: "JetBrains Mono"; font-weight: 100 800; font-display: swap; src: url(/fonts/jetbrains-mono-latin-wght-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family: "JetBrains Mono"; font-weight: 100 800; font-display: swap; src: url(/fonts/jetbrains-mono-vietnamese-wght-normal.woff2) format("woff2");
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB; }
@font-face { font-family: Archivo; font-weight: 100 900; font-display: swap; src: url(/fonts/archivo-latin-wght-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family: Archivo; font-weight: 100 900; font-display: swap; src: url(/fonts/archivo-vietnamese-wght-normal.woff2) format("woff2");
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB; }

/* Themes. bg ground, card panel, mass raised tile, line hairline border, fg text, dim/muted/faint greys (faint is the smallest
   text and still 4.5:1 on bg and card), spot the one accent with on-spot text on it, ok/warn/bad/done the exercise states. */
:root, :root[data-theme="lavender"] { color-scheme: dark;
  --bg: #17171a; --card: #1e1e22; --mass: #26262b; --line: #35353d; --grid: #1c1c20;
  --fg: #eae8ee; --dim: #cdccd2; --muted: #b0afb6; --faint: #908f96;
  --spot: #cba6f7; --on-spot: #17171a; --ok: #a6e3a1; --warn: #f9e2af; --bad: #f38ba8; --done: #94e2d5; }
:root[data-theme="blue"] { color-scheme: dark;
  --bg: #0c0c0b; --card: #131312; --mass: #191918; --line: #2e2e2b; --grid: #121211;
  --fg: #f0ece0; --dim: #dedad0; --muted: #a8a89e; --faint: #8a8a80;
  --spot: #4a9eff; --on-spot: #0c0c0b; --ok: #52c97a; --warn: #e6b84a; --bad: #e05a5a; --done: #5ec4b6; }
/* True black for OLED screens: the ground is #000000; the panels are only just above it. */
:root[data-theme="black"] { color-scheme: dark;
  --bg: #000000; --card: #0a0a0a; --mass: #141414; --line: #2a2a2a; --grid: #080808;
  --fg: #f2f2f2; --dim: #d6d6d6; --muted: #a8a8a8; --faint: #8c8c8c;
  --spot: #ffb454; --on-spot: #000000; --ok: #52c97a; --warn: #e6b84a; --bad: #ee6b6b; --done: #5ec4b6; }
:root[data-theme="paper"] { color-scheme: light;
  --bg: #f6f3ec; --card: #fffdf8; --mass: #ebe6da; --line: #cfc8b8; --grid: #efebe1;
  --fg: #1d1c1a; --dim: #3a3833; --muted: #55524a; --faint: #68645a;
  --spot: #7a2fd6; --on-spot: #ffffff; --ok: #1a6b27; --warn: #8a5a00; --bad: #bf1f45; --done: #0f766e; }
/* Not colours of a theme: type, corner, and tints derived from the theme's tokens. */
:root { --tabbar: calc(56px + env(safe-area-inset-bottom)); --r: 2px;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, "Roboto Mono", monospace;
  --body: Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --disp: Archivo, Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ok-bg: color-mix(in srgb, var(--ok) 8%, transparent); --bad-bg: color-mix(in srgb, var(--bad) 8%, transparent);
  --glass: color-mix(in srgb, var(--card) 94%, transparent);
  /* Google's light sign-in button, the same in every theme: not part of a theme. */
  --google-bg: #ffffff; --google-hover: #f2f2f2; --google-fg: #1f1f1f; --google-line: #747775; }
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--fg);
  font: 18px/1.45 var(--body); }
[hidden] { display: none !important; }
button { font: inherit; color: inherit; cursor: pointer; }
:focus-visible { outline: 3px solid var(--spot); outline-offset: 2px; }
input, textarea { font: inherit; width: 100%; padding: 14px 16px; border-radius: var(--r); border: 1px solid var(--line); background: var(--card); color: var(--fg); margin-bottom: 10px; }
input::placeholder, textarea::placeholder { color: var(--faint); }
button:not(.link):not(.icon):not(.pill):not(.seg):not(.opt):not(.lang):not(.tab):not(.tab-add):not(.ptab):not(#menu-btn):not(#mute-btn):not(#sheet-close) {
  background: var(--spot); color: var(--on-spot); border: 0; border-radius: var(--r); padding: 13px 22px; font: 600 14px var(--mono); text-transform: uppercase; letter-spacing: .08em; }
button:disabled { opacity: .4; cursor: default; }

#boot { max-width: 420px; margin: 0 auto; padding: 16vh 22px 20px; }
#boot.failed p { color: var(--bad); }
.empty { margin: auto; padding: 0 28px; text-align: center; color: var(--muted); }
/* A notice that stands in for the feed (nothing to show, a custom feed not yet picked) is centered on the screen, clear of the header. */
#feed > .empty:only-child { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; margin: 0; }
#feed > .empty:only-child p { margin: 0; }

#login { max-width: 420px; margin: 0 auto; padding: 16vh 22px 20px; }
#login h1 { margin: 0 0 8px; font: 800 34px/1.2 var(--disp); letter-spacing: -.02em; background: linear-gradient(90deg, var(--fg), var(--spot)); -webkit-background-clip: text; background-clip: text; color: transparent; }
.msg { color: var(--spot); min-height: 1.4em; }
/* Continue with Google: Google's light button (white, dark text, the four-colour G), the same in every theme so the mark is never recoloured. */
.google-btn { display: flex; align-items: center; justify-content: center; gap: 12px; min-height: 48px; padding: 0 20px; margin-bottom: 4px; border: 1px solid var(--google-line); border-radius: var(--r); background: var(--google-bg); color: var(--google-fg); font: 500 15px var(--body); text-decoration: none; }
.google-btn:hover { background: var(--google-hover); }
.or { display: flex; align-items: center; gap: 12px; margin: 14px 0; color: var(--muted); font: 12px var(--mono); text-transform: uppercase; letter-spacing: .14em; }
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.fine { color: var(--muted); font-size: 14px; }
a.fine { display: inline-block; padding: 12px 0; }

header { position: fixed; top: 0; left: 0; right: 0; z-index: 5; display: flex; justify-content: space-between;
  align-items: center; padding: calc(4px + env(safe-area-inset-top)) 12px 4px; min-height: 48px; pointer-events: none;
  background: linear-gradient(var(--bg) 55%, transparent); }
header > * { pointer-events: auto; }
.logo { font: 800 18px var(--disp); letter-spacing: -.02em; }
/* The feed switch: two segments in the header; the active one is filled. */
#mode-switch { display: flex; padding: 0; border-radius: var(--r); background: var(--bg); border: 1px solid var(--line); }
.seg { background: none; border: 0; color: var(--faint); font: 500 12px var(--mono); text-transform: uppercase; letter-spacing: .12em; padding: 6px 12px; min-height: 44px; border-radius: 0; white-space: nowrap; }
.seg + .seg { border-left: 1px solid var(--line); }
.seg[aria-pressed="true"] { background: var(--fg); color: var(--bg); }
/* The logo, the switch and the gear no longer fit side by side on a phone: the switch keeps its labels on one line instead. */
@media (max-width: 430px) { .logo { display: none; } }
@media (max-width: 380px) { .seg { padding: 6px 10px; } }
#mute-btn, #menu-btn { background: none; border: 0; color: var(--muted); display: inline-flex; align-items: center; justify-content: center; padding: 4px 10px; min-width: 44px; min-height: 44px; }

.sound-hint { font: 500 12px var(--mono); color: var(--faint); margin-left: 8px; }
.sound-hint[hidden] { display: none; }
.head-tools { display: flex; align-items: center; }
#mute-btn[aria-pressed="true"] { color: var(--fg); }

#feed, #library-feed { height: 100dvh; overflow-y: scroll; scroll-snap-type: y mandatory; scroll-behavior: smooth; overscroll-behavior-y: contain; scrollbar-width: none; }
#feed::-webkit-scrollbar, #library-feed::-webkit-scrollbar { display: none; }
.card { height: 100dvh; scroll-snap-align: start; scroll-snap-stop: always; display: flex; flex-direction: column;
  padding: 0 0 calc(44px + env(safe-area-inset-bottom)) 0; max-width: 640px; margin: 0 auto; position: relative;
  background: linear-gradient(var(--grid) 1px, transparent 1px) 0 0 / 100% 32px, linear-gradient(90deg, var(--grid) 1px, transparent 1px) 0 0 / 32px 100%, var(--bg); }
/* The content is centered between two equal flexible spacers, on a learn card and an exercise card alike, so both start at the same
   place. The spacers shrink to nothing when the content is tall, so the body still scrolls from the top and nothing is unreachable. */
.card-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior-y: auto; scrollbar-width: none; display: flex; flex-direction: column; gap: 14px;
  margin-top: calc(60px + env(safe-area-inset-top)); padding: 4px 84px 8px 20px; }
.card-body::before, .card-body::after { content: ""; flex: 1 0 0; }
/* An answer adds lines below the options. app.ts then pins the top spacer (--lead) at its current height, so the card grows downward and
   nothing above the answer moves. */
.card-body::before { flex: var(--lead, 1 0 0); }
/* The header floats over the top of the screen, so the scroll area starts below it: scrolled text is cut at the header, not hidden under it.
   `.more` (set by app.ts) says there is more below: the bottom edge fades out. */
.card-body.more { -webkit-mask-image: linear-gradient(#000 calc(100% - 48px), transparent); mask-image: linear-gradient(#000 calc(100% - 48px), transparent); }
.card-body::-webkit-scrollbar { display: none; }
.tags { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* The topic is an eyebrow: a short line, then the name in the accent. */
.chip { align-self: flex-start; display: inline-flex; align-items: center; gap: 10px; font: 500 12px var(--mono); text-transform: uppercase; letter-spacing: .18em; color: var(--spot); }
.chip::before { content: ""; width: 28px; height: 1px; background: var(--spot); opacity: .7; }
/* An exercise label is a state: a dot and a lower-case status. The dot is CSS only; the text stays as written. */
.badge { font: 12px var(--mono); text-transform: lowercase; color: var(--muted); letter-spacing: .02em; }
.badge::before { content: "● "; color: var(--warn); }
.badge[data-i18n="badge.retry"]::before { content: "◉ "; color: var(--bad); }
.badge[data-i18n="badge.review"]::before { content: "○ "; color: var(--ok); }
.badge[data-i18n="badge.soft"]::before { content: "● "; color: var(--done); }
.phrase { font: 800 clamp(30px, 9vw, 44px)/1.05 var(--disp); letter-spacing: -.035em; margin: 0; }
/* The example and the explanation are panes: a hairline box with its title (data-title, translated) on the top border. The explanation is the focused one. */
.pron { display: flex; align-items: center; gap: 12px; margin: 0; }
.ipa { font: 500 20px/1.2 var(--mono); color: var(--dim); }
.play { display: grid; place-items: center; width: 44px; height: 44px; cursor: pointer; }
.play svg { width: 22px; height: 22px; }
.example, .vi { position: relative; background: var(--bg); border: 1px solid var(--line); border-radius: var(--r); padding: 16px 16px 12px; margin: 0; }
.example::before, .vi::before { content: attr(data-title); position: absolute; top: -9px; left: 10px; padding: 0 6px; background: var(--bg); font: 500 12px/1.4 var(--mono); color: var(--faint); }
.example { font-size: 18px; color: var(--dim); }
.example em { display: block; color: var(--faint); font-style: normal; font-size: 16px; margin-top: 6px; border-top: 1px solid var(--line); padding-top: 8px; }
.vi { border-color: var(--spot); }
.vi::before { color: var(--spot); }
.vi .en { color: var(--fg); }
.reveal { padding: 8px 0; min-height: 44px; font-size: 15px; text-align: left; }
.reveal::before { content: "+ "; }
.reveal[aria-expanded="true"]::before { content: "− "; }
.vi small { display: block; color: var(--dim); margin-top: 6px; font-size: 15px; }

/* action rail on the right edge, bottom-anchored */
.row { position: absolute; right: 6px; bottom: calc(96px + env(safe-area-inset-bottom)); display: flex; flex-direction: column; gap: 18px; align-items: center; }
.pill { background: none; border: 0; padding: 0; width: 72px; display: flex; flex-direction: column; align-items: center; gap: 4px; font-size: 12px; font-weight: 500; color: var(--muted); }
.pill .ico { width: 52px; height: 52px; border-radius: 4px; background: var(--glass); border: 1px solid var(--line); color: var(--fg); display: grid; place-items: center; transition: background .15s, border-color .15s, transform .15s; }
.pill .ico svg { width: 26px; height: 26px; fill: none; transition: fill .15s; }
.pill.on .ico svg { fill: currentColor; }
.pill:active .ico { transform: scale(.92); }
.pill.on .ico { background: var(--spot); border-color: var(--spot); color: var(--on-spot); }
.pill.on { color: var(--spot); }
.pill[data-reaction="dislike"].on .ico { background: var(--mass); border-color: var(--faint); color: var(--fg); }
/* Five buttons on the rail: tighten it on short screens so the top one stays below the header. */
.row { gap: 12px; }
@media (max-height: 640px) { .row { gap: 6px; bottom: calc(60px + env(safe-area-inset-bottom)); } .pill .ico { width: 44px; height: 44px; } .pill .ico svg { width: 22px; height: 22px; } }
/* The exercise has no frame of its own: its prompt starts where a learn card's phrase does, and the options are as wide as its panes. */
.ex { padding: 0; }
.ex p { margin: 0 0 10px; font-weight: 600; }
/* The prompt line starts with the terminal prompt. */
.ex > p:first-child::before { content: "❯ "; color: var(--spot); font-family: var(--mono); }
.ex-msg { min-height: 1.4em; color: var(--dim); font-weight: 500; font-size: 16px; }
.ex-msg.right { color: var(--ok); }
.ex-msg.right::before { content: "● "; font-family: var(--mono); }
.ex-msg[data-answer]::before { content: "◉ "; color: var(--bad); font-family: var(--mono); }
.ex-msg:empty { min-height: 0; margin: 0; }
.ex-cheer { margin: 0 0 8px; color: var(--warn); font-weight: 500; font-size: 15px; }
.ex-cheer:empty { display: none; }
.ex-tools { display: flex; gap: 18px; }
.ex-tools .link { padding: 6px 0; min-height: 44px; min-width: 44px; font-size: 12px; text-transform: uppercase; letter-spacing: .14em; text-decoration: none; color: var(--muted); }
.ex-tools .link:disabled { opacity: .4; cursor: default; }
.ex-hint { letter-spacing: .12em; font-size: 20px; color: var(--spot); }
/* The answer box and its Check button stack, so a long placeholder is never squeezed into half a row. */
.typebox { display: flex; flex-direction: column; gap: 8px; }
.typebox input { margin: 0; background: var(--card); font-family: var(--mono); caret-color: var(--spot); }
.typebox input:focus { outline: 1px solid var(--spot); outline-offset: 0; border-color: var(--spot); }
.typebox input.right { border-color: var(--ok); background: var(--ok-bg); }
.typebox input.wrong { border-color: var(--bad); background: var(--bad-bg); }
button.go:disabled { opacity: .4; cursor: default; }
.opt:disabled { opacity: .85; }
/* Options are an agent list: ○ idle, ● a right pick (green), ◉ a wrong pick (red). */
.opt { display: block; width: 100%; text-align: left; margin-bottom: 8px; background: var(--card); color: var(--dim); border: 1px solid var(--line); border-radius: var(--r); padding: 13px 14px; min-height: 48px; font-size: 17px; }
.opt::before { content: "○ "; font-family: var(--mono); color: var(--faint); }
.opt:not(:disabled):active { border-color: var(--spot); }
.opt.right { border-color: var(--ok); background: var(--ok-bg); color: var(--fg); }
.opt.right::before { content: "● "; color: var(--ok); }
.opt.wrong { border-color: var(--bad); background: var(--bad-bg); }
.opt.wrong::before { content: "◉ "; color: var(--bad); }
.hint { position: absolute; bottom: calc(8px + env(safe-area-inset-bottom)); left: 0; right: 0; text-align: center; color: var(--faint); font: 12px var(--mono); text-transform: uppercase; letter-spacing: .14em; }

.sheet { position: fixed; inset: 0; z-index: 10; background: rgba(0,0,0,.7); display: flex; align-items: flex-end; }
#add-sheet { z-index: 11; }
#save-form label { display: block; margin: 4px 0 6px; color: var(--muted); font-size: 14px; }
#save-form label small { color: var(--faint); }
#save-form textarea { resize: vertical; min-height: 64px; }
#save-form [aria-invalid="true"] { border-color: var(--bad); background: var(--bad-bg); }
.field-error { margin: -4px 0 10px; color: var(--bad); font-size: 14px; }
.sheet-body { background: var(--card); width: 100%; max-width: 640px; margin: 0 auto; max-height: 85dvh; overflow-y: auto;
  border-radius: 6px 6px 0 0; padding: 20px 20px calc(24px + env(safe-area-inset-bottom)); position: relative; border-top: 2px solid var(--spot); }
#sheet-close { position: sticky; float: right; top: 0; z-index: 1; margin: -12px -12px 0 0; background: none; border: 0; font-size: 22px; min-width: 44px; min-height: 44px; }
.grid, #admin-screen ol { padding-left: 18px; color: var(--muted); }
.grid li, #admin-screen li { cursor: pointer; margin-bottom: 6px; }
.grid b, #admin-screen b { color: var(--fg); font-weight: 600; }
/* The hearted cards as a compact grid; a tap opens the viewer (a full-screen feed of the same cards). */
.grid { list-style: none; padding-left: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; }
.grid li { margin: 0; padding: 10px 12px; min-height: 64px; min-width: 0; overflow-wrap: anywhere; background: var(--card); border: 1px solid var(--line); border-radius: var(--r); }
.grid li:not([tabindex]) { grid-column: 1 / -1; min-height: 0; border-style: dashed; cursor: default; }
.grid small { display: block; font-size: 12px; }
#library { position: fixed; inset: 0; z-index: 12; background: var(--bg); }
#library-back { position: fixed; top: calc(4px + env(safe-area-inset-top)); left: 12px; z-index: 13; min-height: 44px; padding: 8px 16px !important; }
.screen h3, #admin-screen h4 { margin: 16px 0 4px; }
.link { background: none; border: 0; text-decoration: underline; padding: 10px 0; display: block; color: var(--spot); }
.danger { color: var(--bad); }
.lang-label { margin: 12px 0 6px; color: var(--muted); font-size: 14px; }
.lang-switch { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 14px; }
.lang { background: none; border: 1px solid var(--line); border-radius: var(--r); padding: 8px 16px; min-height: 44px; font: 500 14px var(--mono); }
.lang[aria-pressed="true"] { background: var(--spot); border-color: var(--spot); color: var(--on-spot); font-weight: 600; }
@media (prefers-reduced-motion: reduce) { #feed, #library-feed { scroll-behavior: auto; } }

/* public text pages (/privacy), served without the app */
.doc { height: auto; padding: 24px 16px 48px; }
.doc main { max-width: 640px; margin: 0 auto; }
.doc h1 { margin: 0 0 8px; font: 800 30px/1.25 var(--disp); letter-spacing: -.03em; }
.doc h2 { font-size: 20px; margin: 28px 0 6px; }
.doc ul, .doc ol { padding-left: 20px; }
.doc .updated { margin: 0 0 12px; color: var(--muted); font-size: 13px; }
.doc li { margin-bottom: 6px; }
.doc a:not(.lang):not(.shared-cta) { color: var(--accent); }
.doc .shared-cta { display: block; margin-top: 12px; }
a.lang { color: var(--fg); text-decoration: none; display: inline-flex; align-items: center; }
a.lang[aria-current="page"] { background: var(--spot); border-color: var(--spot); color: var(--on-spot); font-weight: 600; }
/* public page of a shared phrase (/c/<id>), served without the app */
.shared { display: grid; place-items: center; min-height: 100%; height: auto; padding: 24px 16px; }
.shared-card { width: 100%; max-width: 520px; display: flex; flex-direction: column; gap: 14px; }
.shared-card h1 { margin: 0; font: 800 30px/1.25 var(--disp); letter-spacing: -.03em; }
.shared-card p { margin: 0; }
.shared-vi { color: var(--muted); }
.shared-card .pron { flex-wrap: wrap; }
.shared-card audio { max-width: 100%; }
.shared-cta { align-self: stretch; text-align: center; background: var(--spot); color: var(--on-spot); font: 600 14px var(--mono); text-transform: uppercase; letter-spacing: .08em; text-decoration: none; padding: 14px 16px; border-radius: var(--r); min-height: 48px; }

/* Guest save-progress prompt: one slim row (44px) just above the tab bar, in the strip each card keeps free at its bottom (the hint's), so it
   never covers a card or blocks scrolling. */
#save-prompt { position: fixed; left: 0; right: 0; bottom: var(--tabbar); height: 44px; z-index: 4; display: flex; align-items: center; gap: 8px;
  padding: 0 12px; background: var(--card); border-top: 1px solid var(--line); font-size: 14px; }
#save-prompt[hidden] { display: none; }
#save-prompt span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#save-prompt button { padding: 0 14px; min-height: 44px; white-space: nowrap; }
#save-prompt .link { padding: 0 4px; display: inline-block; }
#login-back { margin-top: 8px; }
.consent { display: flex; align-items: flex-start; gap: 10px; margin: 14px 0 4px; font-size: 14px; line-height: 1.4; color: var(--muted); }
.consent input { flex: none; width: 22px; height: 22px; margin: 0; }
.consent a { color: inherit; text-decoration: underline; display: inline-block; padding: 12px 4px; margin: -12px 0; }
.consent.need { color: var(--fg); }
/* Guest start notice: a short bar in the same strip above the tab bar as the save prompt; shown until the guest taps OK. */
#guest-notice { position: fixed; left: 0; right: 0; bottom: var(--tabbar); z-index: 5; display: flex; align-items: center; gap: 8px;
  padding: 6px 12px; background: var(--card); border-top: 1px solid var(--line); font-size: 13px; line-height: 1.35; }
#guest-notice[hidden] { display: none; }
#guest-notice > span { flex: 1 1 auto; min-width: 0; }
#guest-notice a { color: inherit; text-decoration: underline; display: inline-block; padding: 12px 4px; margin: -12px 0; white-space: nowrap; }
/* The notice may be two or three lines tall (app.ts shares its height as --notice-h): the rail lifts clear of it and the text ends above it. */
html:has(#guest-notice:not([hidden])) #feed .row { transform: translateY(calc(-1 * var(--notice-h, 0px))); }
html:has(#guest-notice:not([hidden])) #feed .card-body { margin-bottom: var(--notice-h, 0px); }
#guest-notice button { padding: 0 14px; min-height: 44px; white-space: nowrap; }
#toast { position: fixed; left: 50%; bottom: calc(var(--tabbar) + 12px); transform: translateX(-50%); z-index: 12; max-width: calc(100% - 32px);
  padding: 10px 16px; border-radius: var(--r); background: var(--card); border: 1px solid var(--spot); color: var(--fg); font-family: var(--mono); font-size: 15px; text-align: center; pointer-events: none; }

/* The custom feed picker: a searchable checklist on its own full screen; only the list scrolls. */
#custom-search { width: 100%; box-sizing: border-box; margin: 6px 0; }
.custom-tools { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
#custom-cats { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 8px; flex: none; }
#custom-cats button { flex: none; min-height: 44px; padding: 0 14px; white-space: nowrap; background: var(--mass); color: var(--fg); border: 1px solid var(--line); }
#custom-cats button[aria-pressed="true"] { background: var(--spot); color: var(--on-spot); border-color: var(--spot); }
#custom-list { list-style: none; padding: 0; margin: 0; flex: 1; min-height: 0; overflow-y: auto; }
#custom-list li { margin: 0 0 6px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r); }
#custom-list label { display: flex; gap: 10px; align-items: center; padding: 10px 12px; min-height: 44px; cursor: pointer; }
#custom-list input { width: 22px; height: 22px; flex: none; }
#custom-list b { color: var(--fg); font-weight: 600; }
#custom-list small { display: block; color: var(--muted); font-size: 12px; }

/* Bottom tab bar (Feed, +, Profile): the feed and the pages end where it starts. */
#tabbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 6; display: flex; padding-bottom: env(safe-area-inset-bottom);
  background: var(--bg); border-top: 1px solid var(--line); }
.tab { flex: 1; min-height: 56px; background: none; border: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  font: 500 12px var(--mono); text-transform: uppercase; letter-spacing: .12em; color: var(--faint); }
.tab .ico { line-height: 0; }
.tab-add .ico, #menu-btn .ico { line-height: 0; }
.tab .ico svg, .ptab .ico svg, .tab-add .ico svg, #mute-btn svg, #menu-btn .ico svg { width: 24px; height: 24px; }
.tab-add { flex: none; align-self: center; width: 56px; height: 44px; margin: 6px 12px; padding: 0; border: 1px solid var(--line); border-radius: var(--r); font: 400 26px/1 var(--mono);
  color: var(--spot); background: var(--bg); }
.tab[aria-current="page"] { color: var(--fg); box-shadow: inset 0 2px 0 var(--spot); }
.tab[aria-current="page"] .ico svg { fill: currentColor; }
#feed { height: calc(100dvh - var(--tabbar)); }
#feed .card { height: 100%; padding-bottom: 44px; }
#feed .row { bottom: 56px; }
#feed .hint { bottom: 8px; }
@media (max-height: 640px) { #feed .row { bottom: 40px; } }

/* Pages above the feed (Profile) and full screens above the tab bar (picker, admin). 16px gutters. */
.screen { position: fixed; inset: 0 0 var(--tabbar) 0; z-index: 3; overflow-y: auto; overscroll-behavior: contain; background: var(--bg);
  padding: calc(60px + env(safe-area-inset-top)) 16px 24px; }
.screen > * { max-width: 640px; margin-left: auto; margin-right: auto; }
.screen-head, .panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.screen-head h2 { margin: 0; font-size: 24px; }
.panel-head { margin: 4px 0 8px; color: var(--muted); }
.icon { width: 44px; height: 44px; padding: 0; border-radius: var(--r); border: 1px solid var(--line); background: var(--card); color: var(--fg); font-size: 26px; line-height: 1; flex: none; }
.form-actions { display: flex; align-items: center; gap: 16px; }
#profile-email { margin: 4px auto 12px; color: var(--muted); font-size: 15px; overflow-wrap: anywhere; }
#profile-tabs { display: flex; border-bottom: 1px solid var(--line); margin-bottom: 12px; }
.ptab { flex: 1; min-height: 56px; background: none; border: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  font: 500 13px var(--mono); color: var(--muted); }
.ptab .ico { line-height: 0; }
.ptab[aria-selected="true"] .ico svg { fill: currentColor; }
.ptab[aria-selected="true"] { color: var(--fg); box-shadow: inset 0 -2px 0 var(--spot); }
.overlay { position: fixed; inset: 0; z-index: 11; background: var(--bg); padding: calc(12px + env(safe-area-inset-top)) 16px calc(16px + env(safe-area-inset-bottom)); }
.overlay-col { max-width: 640px; height: 100%; margin: 0 auto; display: flex; flex-direction: column; }
.overlay-col.scroll { display: block; overflow-y: auto; }
.overlay .screen-head { margin-bottom: 8px; }
.overlay .screen-head button { padding: 10px 18px; min-height: 44px; flex: none; }

/* Short phones (360x640, 375x667): tighter exercise and no "swipe up" strip, so the options, Hint and Show me fit more often.
   The strip comes back while the guest bar sits in it. */
@media (max-height: 700px) {
  .card-body { gap: 10px; }
  .ex p, .opt { font-size: 16px; }
  .opt { padding: 10px 12px; margin-bottom: 6px; }
  #feed .card { padding-bottom: 8px; }
  #feed .hint { display: none; }
  #feed .row { bottom: 8px; }
  html:has(#save-prompt:not([hidden])) #feed .card { padding-bottom: 44px; }
  html:has(#save-prompt:not([hidden])) #feed .row { bottom: 48px; }
}
/* Narrow phones: a slimmer rail gives the text about 20px more per line. */
@media (max-width: 400px) {
  .card-body { padding-left: 16px; padding-right: 68px; }
  .pill { width: 64px; font-size: 11px; }
  .pill > span:last-child { white-space: nowrap; }
}
/* Phone landscape: the rail is icons only, anchored in the card so it clears the header, and the text keeps a narrow strip for it. */
@media (orientation: landscape) and (max-height: 500px) {
  .card-body { padding-right: 64px; }
  #feed .row { bottom: 4px; gap: 4px; }
  .pill { width: 48px; }
  .pill .ico { width: 44px; height: 44px; }
  .pill .ico svg { width: 20px; height: 20px; }
  .pill > span:last-child { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  html:has(#save-prompt:not([hidden])) #feed .row { bottom: 48px; }
}
