/* ---- tokens ---- */
:root {
  color-scheme: dark;
  --bg: #14161a; --panel: #1f2228; --panel-2: #262a31; --line: #3a3e46; --text: #e8e6e1; --muted: #8a8f98; --accent: #f2c14e;
  --on-accent: #14161a; --danger: #ff8a80; --done: #6fd99a;
  --r-sm: 6px; --r: 10px; --r-lg: 14px;
  --side: 220px; --tabs: 58px; --mini: 64px;
  --shadow: 0 8px 30px #0009;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html { scrollbar-color: var(--line) transparent; }
* { scrollbar-width: thin; }
/* Settings → Font (`<html data-font>`); the bundled fonts load only when a page uses them. */
@font-face { font-family: "Atkinson Hyperlegible"; src: url(/fonts/atkinson-hyperlegible-regular.woff2) format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Atkinson Hyperlegible"; src: url(/fonts/atkinson-hyperlegible-bold.woff2) format("woff2"); font-weight: 700; font-display: swap; }
@font-face { font-family: "JetBrains Mono"; src: url(/fonts/jetbrains-mono-regular.woff2) format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "JetBrains Mono"; src: url(/fonts/jetbrains-mono-bold.woff2) format("woff2"); font-weight: 700; font-display: swap; }
@font-face { font-family: OpenDyslexic; src: url(/fonts/opendyslexic-regular.woff2) format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: OpenDyslexic; src: url(/fonts/opendyslexic-bold.woff2) format("woff2"); font-weight: 700; font-display: swap; }
:root { --font: system-ui, -apple-system, "Segoe UI", sans-serif; }
:root[data-font="serif"] { --font: ui-serif, Georgia, "Noto Serif", "Times New Roman", serif; }
:root[data-font="atkinson"] { --font: "Atkinson Hyperlegible", system-ui, sans-serif; }
:root[data-font="jetbrains"] { --font: "JetBrains Mono", ui-monospace, monospace; }
:root[data-font="dyslexic"] { --font: OpenDyslexic, system-ui, sans-serif; }
body { -webkit-user-select: none; user-select: none; margin: 0; background: var(--bg); color: var(--text); font: 16px/1.5 var(--font); -webkit-font-smoothing: antialiased; }
a { color: inherit; text-decoration: none; }
h1 { font-size: 24px; line-height: 1.2; margin: 8px 0 16px; letter-spacing: -0.01em; }
h2 { font-size: 15px; margin: 28px 0 12px; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }
.muted { color: var(--muted); font-size: 14px; }
.error { color: var(--danger); }
.error:empty { display: none; }
.link { color: var(--accent); }
.link:hover { text-decoration: underline; }
.grow { flex: 1; }
.icon { width: 22px; height: 22px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* ---- controls ---- */
input, textarea { -webkit-user-select: text; user-select: text; }
button, input, select { font: inherit; color: inherit; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); padding: 10px 14px; }
button { cursor: pointer; transition: background .15s, border-color .15s, color .15s; }
button:hover, select:hover { border-color: #565b65; }
button.primary, .play-btn { background: var(--accent); color: var(--on-accent); border-color: var(--accent); font-weight: 600; }
button.primary:hover, .play-btn:hover { filter: brightness(1.06); }
button.quiet { background: none; border: none; color: var(--muted); padding: 6px 8px; }
button.quiet:hover { color: var(--text); }
.icon-btn { background: none; border: none; padding: 8px; color: var(--muted); display: inline-flex; }
.icon-btn:hover { color: var(--text); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
input:focus { border-color: var(--accent); outline: none; }

/* ---- shell ---- */
main { padding: 16px; padding-top: calc(16px + env(safe-area-inset-top)); padding-bottom: calc(var(--mini) + var(--tabs) + 32px + env(safe-area-inset-bottom)); }
.side { display: none; }
.account-menu { position: fixed; z-index: 8; right: 8px; bottom: calc(var(--tabs) + env(safe-area-inset-bottom) + 8px); min-width: 180px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow); padding: 6px; display: grid; }
.account-menu a, .account-menu button { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: none; background: none; border-radius: var(--r); text-align: left; color: var(--text); }
.account-menu a:hover, .account-menu button:hover { background: var(--panel-2); }
.tabs { position: fixed; left: 0; right: 0; bottom: 0; z-index: 6; height: calc(var(--tabs) + env(safe-area-inset-bottom)); padding-bottom: env(safe-area-inset-bottom); display: grid; grid-template-columns: repeat(5, 1fr); background: var(--panel); border-top: 1px solid var(--line); }
.tabs button.tab { background: none; border: none; border-radius: 0; padding: 0; }
.menu-scrim { position: fixed; inset: 0; z-index: 7; }
.tab { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 11px; color: var(--muted); }
.tab.active { color: var(--accent); }
.mini { position: fixed; left: 0; right: 0; bottom: calc(var(--tabs) + env(safe-area-inset-bottom)); z-index: 5; display: flex; align-items: center; gap: 10px; height: var(--mini); padding: 8px 12px; background: var(--panel-2); border-top: 1px solid var(--line); }
.mini-open { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; }
.mini-open img { width: 46px; height: 46px; border-radius: var(--r-sm); object-fit: cover; }
.mini-open .title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 500; }
.mini-play { background: var(--accent); color: var(--on-accent); border-color: var(--accent); min-width: 80px; font-weight: 600; }

@media (min-width: 900px) {
  h1 { font-size: 30px; margin: 4px 0 20px; }
  .tabs, .account-menu, .menu-scrim { display: none; }
  .side { display: flex; flex-direction: column; gap: 4px; position: fixed; left: 0; top: 0; bottom: 0; width: var(--side); padding: 28px 14px 18px; background: #181a1f; border-right: 1px solid var(--line); z-index: 6; }
  .side nav { display: grid; gap: 2px; }
  .side-link { display: flex; align-items: center; gap: 12px; width: 100%; padding: 10px 12px; border: none; border-radius: var(--r); background: none; color: var(--muted); font-weight: 500; text-align: left; }
  .side-link:hover { background: var(--panel); color: var(--text); }
  .side-link.active { background: var(--panel-2); color: var(--text); }
  .side-link.active .icon { color: var(--accent); }
  .app:not(.on-player) .content { margin-left: var(--side); }
  main { padding: 28px 40px; padding-bottom: calc(var(--mini) + 40px); max-width: 1600px; }
  .mini { left: var(--side); bottom: 0; height: 72px; padding: 10px 24px; }
}

/* ---- login ---- */
.login { min-height: 100vh; display: grid; place-items: center; padding: 16px; }
.login-card { display: grid; gap: 12px; width: min(360px, 100%); padding: 28px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow); }
.login-card h1 { margin: 0; }
.login-card p { margin: 0 0 6px; }

/* ---- player page ---- */
/* Pinned to the visible screen: the page never scrolls, so browser toolbars can't push the controls under the text. */
.player { position: fixed; inset: 0; max-width: 760px; margin: 0 auto; display: flex; flex-direction: column; padding-bottom: 0; }
.player header { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.player .meta { flex: 1; min-width: 0; }
.player .meta .title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* position: relative → sentence offsetTop is measured inside the scroller (the glide needs it). */
.lyrics { scrollbar-width: none; position: relative; flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 0 4px; }
/* Room to centre the first/last sentence, as scrollable content (box padding can't shrink and pushed the controls off-screen). */
.lyrics::before, .lyrics::after { content: ""; display: block; height: 40vh; }
.sentence { font-size: calc(24px * var(--lyrics-scale, 1)); line-height: 1.4; margin: 0 0 18px; color: #6c7079; transition: color .2s; cursor: pointer; border-radius: 8px; padding: 2px 6px; }
.sentence:hover { background: #ffffff08; }
.sentence.past { color: #4f535b; }
.sentence { animation: fade-in .5s ease both; }
@keyframes fade-in { from { opacity: 0; } }
.sentence.current { color: var(--text); }
.sentence .word-on { color: var(--accent); }
.lyrics .status { text-align: center; font-size: 16px; }
/* Until the first text is in and centred on the spoken sentence. */
/* Hidden, not removed: the text must be laid out to scroll to the spoken sentence before it is revealed. */
.lyrics.loading .sentence, .lyrics.loading .status { visibility: hidden; }
.lyrics-loading { position: absolute; top: 40%; left: 0; right: 0; margin: 0; text-align: center; font-size: 16px; }
.back-to-now { position: relative; z-index: 3; align-self: center; margin: -56px 0 12px; background: var(--accent); color: var(--on-accent); border-color: var(--accent); box-shadow: 0 4px 16px #0008; }
@media (max-width: 600px) { .sentence { font-size: calc(21px * var(--lyrics-scale, 1)); } }
.controls { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 12px 0 calc(12px + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); }
.controls button, .controls select { padding: 10px; }
.controls .play { min-width: 76px; background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
/* ---- seek bar: only the thumb is interactive, so a stray tap or scroll never moves the book ---- */
.seek { position: relative; padding: 4px 10px 0; }
.seek-track { position: relative; height: 4px; margin: 20px 0 6px; background: var(--line); border-radius: 2px; }
.seek-fill { height: 100%; background: var(--accent); border-radius: 2px; }
.seek-thumb { position: absolute; top: 50%; width: 44px; height: 44px; margin: -22px 0 0 -22px; touch-action: none; cursor: grab; display: grid; place-items: center; outline: none; }
.seek-thumb::after { content: ""; width: 14px; height: 14px; border-radius: 50%; background: var(--accent); transition: transform .1s; }
.seek-thumb:focus-visible::after, .dragging .seek-thumb::after { transform: scale(1.5); }
.seek-tip { position: absolute; bottom: 100%; padding: 2px 8px; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; font-size: 13px; font-variant-numeric: tabular-nums; white-space: nowrap; pointer-events: none; }
.seek-times { display: flex; justify-content: space-between; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.dragging .seek-times span:first-child { color: var(--text); }
.seek-line { text-align: center; font-size: 12px; padding-bottom: 6px; }
.undo-pill { position: absolute; left: 50%; bottom: 22px; transform: translateX(-50%); padding: 2px 10px; border-radius: 14px; font-size: 12px; background: var(--panel); border: 1px solid var(--accent); color: var(--text); z-index: 2; white-space: nowrap; }
/* Desktop volume: speaker (click = mute) + slim slider filled to --v. Phones use the hardware buttons. */
.volume { display: none; align-items: center; gap: 2px; margin-left: 4px; flex: 0 1 140px; min-width: 0; }
@media (hover: hover) and (pointer: fine) { .volume { display: inline-flex; } }
.volume .icon-btn { padding: 6px; border-radius: 8px; }
.volume input[type=range] { -webkit-appearance: none; appearance: none; flex: 1; width: 100%; min-width: 40px; height: 22px; padding: 0; margin: 0; border: none; background: none; cursor: pointer; }
.volume input[type=range]::-webkit-slider-runnable-track { height: 4px; border-radius: 2px; background: linear-gradient(to right, var(--accent) var(--v, 100%), var(--line) var(--v, 100%)); }
.volume input[type=range]::-moz-range-track { height: 4px; border-radius: 2px; background: linear-gradient(to right, var(--accent) var(--v, 100%), var(--line) var(--v, 100%)); }
.volume input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; margin-top: -4px; border-radius: 50%; background: var(--text); border: none; transform: scale(0); transition: transform .12s; }
.volume input[type=range]::-moz-range-thumb { width: 12px; height: 12px; border-radius: 50%; background: var(--text); border: none; transform: scale(0); transition: transform .12s; }
.volume:hover input[type=range]::-webkit-slider-thumb, .volume input[type=range]:focus-visible::-webkit-slider-thumb { transform: scale(1); }
.volume:hover input[type=range]::-moz-range-thumb, .volume input[type=range]:focus-visible::-moz-range-thumb { transform: scale(1); }
.volume input[type=range]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.up-next { position: absolute; left: 0; right: 0; bottom: 100%; margin-bottom: 6px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 14px; background: var(--panel); border: 1px solid var(--accent); border-radius: 12px; box-shadow: var(--shadow); z-index: 3; }
.up-next .actions { display: flex; gap: 8px; }
.up-next .play { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.marks { padding-bottom: 6px; }
.marks .add { display: block; width: calc(100% - 24px); margin: 12px; }
.marks h3 { margin: 10px 14px 2px; font-size: 12px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.marks ul { list-style: none; margin: 0; padding: 0; }
.marks li { padding: 0; }
.marks .go { flex: 1; min-width: 0; display: flex; justify-content: space-between; gap: 12px; padding: 12px 14px; background: none; border: none; color: inherit; font: inherit; text-align: left; }
.marks .x { background: none; border: none; color: var(--muted); padding: 0 14px; }
.marks .error { margin: 0 14px; }
.subbar { position: relative; display: flex; flex-direction: column; gap: 6px; padding: 6px 0 0; font-size: 13px; }
.subbar-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.panel-scrim { position: fixed; inset: 0; z-index: 1; }
.panel-icons { position: relative; z-index: 2; }
.subbar select { flex: 1 1 0; min-width: 0; }
.subbar .chapter { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.subbar select, .subbar button { font-size: 13px; padding: 6px 8px; }
.chapter-list { position: absolute; left: 0; right: 0; bottom: 100%; max-height: 50vh; overflow-y: auto; margin: 0 0 6px; padding: 0; list-style: none; background: var(--panel); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow); z-index: 2; }
.chapter-list li { display: flex; justify-content: space-between; gap: 12px; padding: 12px 14px; border-bottom: 1px solid var(--line); cursor: pointer; }
.chapter-list li.current { color: var(--accent); }

/* ---- lists, cards ---- */
.shelf { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 6px; scroll-snap-type: x proximity; }
.shelf .card { flex: 0 0 140px; scroll-snap-align: start; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 20px 14px; }
@media (min-width: 900px) { .shelf .card { flex-basis: 168px; } .grid { grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 26px 18px; } }
.card { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.card .cover { position: relative; aspect-ratio: 1; border-radius: var(--r); overflow: hidden; background: var(--panel); box-shadow: 0 2px 10px #0006; transition: transform .2s; }
.card:hover .cover { transform: translateY(-2px); }
.card .cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.card .title { font-size: 14px; line-height: 1.3; margin-top: 4px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.card .muted { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card .seq { position: absolute; top: 6px; left: 6px; background: #000b; border-radius: var(--r-sm); padding: 1px 7px; font-size: 12px; }
.card .bar { position: absolute; left: 0; right: 0; bottom: 0; height: 4px; background: #0008; }
.card .bar div { height: 100%; background: var(--accent); }
.card .bar.done div { background: var(--done); }
.finished { color: var(--done); font-weight: 600; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip { border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; background: var(--panel); font-size: 14px; }
.chip:hover { border-color: #565b65; }
.search-box { width: 100%; margin: 8px 0 4px; font-size: 17px; }

/* ---- book page ---- */
.book-head { display: grid; grid-template-columns: minmax(120px, 200px) 1fr; gap: 16px; margin-top: 8px; }
.big-cover { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--r); background: var(--panel); box-shadow: var(--shadow); }
.book-meta h1 { margin: 0 0 6px; font-size: 21px; line-height: 1.25; }
.book-meta p { margin: 4px 0; }
.play-btn { display: inline-block; border-radius: var(--r); padding: 11px 26px; text-align: center; }
.book-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-top: 14px; }
@media (max-width: 600px) {
  .book-actions { flex-direction: column; align-items: stretch; }
}
.confirm { width: min(420px, calc(100vw - 32px)); padding: 20px; color: var(--text); background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow); }
.confirm::backdrop { background: #0009; }
.confirm h2 { margin: 0 0 8px; }
.confirm-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
button.danger { color: var(--on-accent); background: var(--danger); border-color: var(--danger); font-weight: 600; }
button.danger:disabled { opacity: .6; cursor: default; }
.desc { white-space: pre-line; color: #c9c7c2; display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; margin: 18px 0 4px; }
.desc.open { display: block; }
.chapters { list-style: none; padding: 0; margin: 0; }
.chapters a { display: flex; justify-content: space-between; gap: 12px; padding: 10px 4px; border-bottom: 1px solid var(--line); }
.chapters a:hover { color: var(--accent); }


/* ---- shelves, series stacks, covers ---- */
.shelf-wrap { position: relative; }
.shelf { scrollbar-width: none; }
.shelf::-webkit-scrollbar { display: none; }
.shelf-arrow { display: none; }
@media (hover: hover) and (pointer: fine) {
  .shelf-arrow { display: grid; place-items: center; position: absolute; top: 0; z-index: 2; width: 44px; height: calc(100% - 46px); padding: 0; border: none; border-radius: 0; font-size: 34px; color: var(--text); opacity: 0; transition: opacity .2s; }
  .shelf-arrow.left { left: 0; background: linear-gradient(to right, var(--bg) 20%, transparent); }
  .shelf-arrow.right { right: 0; background: linear-gradient(to left, var(--bg) 20%, transparent); }
  .shelf-wrap:hover .shelf-arrow { opacity: .9; }
  .shelf-wrap.at-start .shelf-arrow.left, .shelf-wrap.at-end .shelf-arrow.right { opacity: 0; pointer-events: none; }
}
.shelf-wrap:not(.at-end)::after { content: ""; position: absolute; top: 0; right: 0; width: 28px; height: calc(100% - 46px); background: linear-gradient(to left, var(--bg), transparent); pointer-events: none; }
.shelf .series-card { flex-basis: 210px; }
@media (min-width: 900px) { .shelf .series-card { flex-basis: 250px; } }
/* isolation: the covers' z-indexes stay inside the stack, so it never paints over the fixed bars. */
.stack { position: relative; aspect-ratio: 1.5; isolation: isolate; }
.stack img { position: absolute; top: 0; height: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--r-sm); background: var(--panel);
  left: calc(var(--i) * (100% - 100% / 1.5) / max(var(--n) - 1, 1)); z-index: calc(20 - var(--i)); box-shadow: -3px 0 12px #000a; }
.stack .count { position: absolute; top: 6px; right: 6px; z-index: 30; min-width: 26px; height: 26px; padding: 0 7px; display: grid; place-items: center; border-radius: 999px; background: var(--accent); color: var(--on-accent); font-size: 13px; font-weight: 700; }
.series-card:hover .stack { transform: translateY(-2px); }
.stack { transition: transform .2s; }
.cover img, .stack img, .big-cover, .mini-open img { opacity: 0; transition: opacity .35s; }
.cover img.loaded, .stack img.loaded, .big-cover.loaded, .mini-open img.loaded { opacity: 1; }

/* ---- book page, wide ---- */
@media (max-width: 600px) { .book-head { grid-template-columns: 1fr; } .big-cover { max-width: 280px; } }
@media (min-width: 900px) {
  .book-page { max-width: 1200px; }
  .book-head { grid-template-columns: minmax(260px, 340px) 1fr; gap: 44px; margin-top: 12px; align-items: start; }
  .big-cover { position: sticky; top: 28px; }
  .book-meta h1 { font-size: 32px; margin-bottom: 10px; }
  .book-meta .desc { margin-top: 26px; max-width: 72ch; }
}

/* ---- library / list pages ---- */
.page-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.page-head h1 { margin-right: auto; }
.filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 6px; }
.filters select, .filters input, .filters button { padding: 8px 12px; font-size: 14px; }
.filters .filter-value { min-width: 220px; flex: 0 1 320px; }
.filters .dir { min-width: 40px; }
.count { margin: 6px 0 16px; }
.empty { padding: 40px 0; text-align: center; }
.skeleton .cover { background: linear-gradient(100deg, var(--panel) 40%, var(--panel-2) 50%, var(--panel) 60%) 0 0 / 200% 100%; animation: shimmer 1.4s linear infinite; }
@keyframes shimmer { to { background-position: -200% 0; } }
@media (max-width: 600px) { .filters .grow { display: none; } .filters .filter-value { flex: 1 1 100%; } }
.series-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
@media (min-width: 900px) { .series-grid { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 30px 22px; } }
.page-head .dir, .page-head select { padding: 8px 12px; font-size: 14px; }
.page-head select + .dir { margin-left: -8px; }

/* ---- stats ---- */
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; margin-bottom: 8px; }
.tile { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 16px 18px; }
.tile-value { font-size: 26px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.2; }
.panel { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 4px 18px 18px; margin-top: 16px; }
.panel h2 { margin-top: 16px; }
.days-chart { position: relative; }
.days-max { position: absolute; top: -2px; left: 0; font-size: 12px; }
.days-bars { display: flex; align-items: flex-end; gap: 3px; height: 160px; padding-top: 18px; border-bottom: 1px solid var(--line); }
.day { position: relative; flex: 1; height: 100%; display: flex; align-items: flex-end; justify-content: center; cursor: default; }
.day-bar { width: 100%; max-width: 24px; min-height: 2px; background: var(--accent); border-radius: 4px 4px 0 0; transition: filter .15s; }
.day:hover .day-bar { filter: brightness(1.2); }
.day:hover::after { content: attr(data-tip); position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%); white-space: nowrap; background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 4px 8px; font-size: 12px; color: var(--text); box-shadow: var(--shadow); z-index: 3; pointer-events: none; }
.days-axis { display: flex; gap: 3px; font-size: 12px; margin-top: 6px; }
.days-axis span { flex: 1; text-align: center; white-space: nowrap; overflow: visible; }
.days-axis span:first-child { text-align: left; }
.days-axis span:last-child { text-align: right; }
.week-plot { position: relative; display: flex; height: 142px; margin-top: 18px; border-bottom: 1px solid var(--line); }
.week-plot svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.week-plot polyline { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.week-dot { position: absolute; left: 50%; width: 10px; height: 10px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--panel); transform: translate(-50%, 50%); transition: transform .15s; }
.day:hover .week-dot { transform: translate(-50%, 50%) scale(1.3); }
.week-axis { display: flex; font-size: 12px; margin-top: 8px; }
.week-axis span { flex: 1; text-align: center; }
.weekdays { display: grid; gap: 8px; }
.wd { display: grid; grid-template-columns: 40px 1fr 70px; align-items: center; gap: 10px; font-size: 14px; }
.wd-track { height: 14px; }
.wd-bar { height: 100%; min-width: 2px; background: var(--accent); border-radius: 0 4px 4px 0; }
.wd-val { text-align: right; font-variant-numeric: tabular-nums; }
.sessions { list-style: none; margin: 0; padding: 0; }
.sessions a { display: grid; grid-template-columns: 44px 1fr auto; align-items: center; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.sessions li:last-child a { border-bottom: none; }
.sessions img { width: 44px; height: 44px; border-radius: var(--r-sm); object-fit: cover; opacity: 0; transition: opacity .35s; }
.sessions img.loaded { opacity: 1; }
.sessions .what { display: grid; min-width: 0; }
.sessions .title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sessions .when { font-size: 13px; white-space: nowrap; }
@media (min-width: 900px) { .stats { max-width: 1100px; } .tiles { grid-template-columns: repeat(5, 1fr); } }
@media (max-width: 600px) { .sessions a { grid-template-columns: 44px 1fr; } .sessions .when { grid-column: 2; } }

/* ---- admin ---- */
@media (min-width: 900px) { .admin { max-width: 1100px; } .admin .tiles { grid-template-columns: repeat(3, 1fr); } }
.admin .now { margin: 0 0 16px; }
.admin .now p { margin: 6px 0; }
.admin .gpu-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.admin .gpu-row .gpu-switch { padding: 6px 10px; font-size: 13px; flex: none; }
.mono { font-family: ui-monospace, monospace; font-size: 13px; white-space: pre-wrap; word-break: break-word; }
.dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 10px; background: var(--muted); vertical-align: middle; }
.dot.on { background: #7ee2a8; position: relative; }
/* The ring pulses with transform/opacity only: the compositor runs it, no repaint every frame (box-shadow did). */
.dot.on::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; background: #7ee2a822; animation: pulse 1.6s ease-in-out infinite; }
.dot.wait { background: var(--accent); }
.dot.bad { background: var(--danger); }
@keyframes pulse { 50% { transform: scale(1.35); opacity: .5; } }
.show-all { margin-top: 12px; }
.cov-rows { list-style: none; margin: 0; padding: 0; }
.cov-rows a { display: grid; grid-template-columns: 44px 1fr auto; align-items: center; gap: 14px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.cov-rows li:last-child a { border-bottom: none; }
.cov-rows img { width: 44px; height: 44px; border-radius: var(--r-sm); object-fit: cover; opacity: 0; transition: opacity .35s; }
.cov-rows img.loaded { opacity: 1; }
.cov-rows .what { display: grid; gap: 6px; min-width: 0; }
.cov-rows .title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cov-track { display: block; height: 6px; border-radius: 3px; background: var(--panel-2); overflow: hidden; }
.cov-bar { display: block; height: 100%; background: var(--accent); border-radius: 3px; }
.cov-rows li.current .cov-bar { background: #7ee2a8; }
.queue-rows .cov-bar { background: #7ee2a8; }
.cov-rows .when { text-align: right; font-size: 13px; white-space: nowrap; }

/* ---- player, wide: controls + cover left, lyrics right ---- */
.player-cover { display: none; }
@media (min-width: 900px) {
  .player { max-width: 1500px; display: grid; grid-template-columns: minmax(300px, 380px) 1fr; grid-template-rows: 1fr auto auto auto auto auto auto 1fr; column-gap: 56px; padding: 0 48px; }
  .player > header { grid-column: 1; grid-row: 2; padding-bottom: 14px; }
  .player-cover { display: block; grid-column: 1; grid-row: 3; width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--r-lg); box-shadow: var(--shadow); background: var(--panel); }
  .player > .error { grid-column: 1; grid-row: 4; }
  .player > .subbar { grid-column: 1; grid-row: 5; --subbar-pad: 14px; }
  .player > .seek { grid-column: 1; grid-row: 6; }
  .player > .controls { grid-column: 1; grid-row: 7; border-top: none; padding-bottom: 12px; }
  .player .lyrics { grid-column: 2; grid-row: 1 / -1; padding: 0 12px; }
  .player .sentence { font-size: calc(28px * var(--lyrics-scale, 1)); }
  .back-to-now { position: fixed; align-self: auto; margin: 0; transform: translateX(-50%); left: calc(48px + 380px + 56px + (100% - 48px - 380px - 56px - 48px) / 2); bottom: 32px; }
}

/* ---- library select mode (admins) ---- */
.card.ticked .cover { outline: 3px solid var(--accent); outline-offset: -3px; }
.card .tick { position: absolute; top: 6px; right: 6px; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 50%; background: var(--accent); color: var(--on-accent); font-weight: 700; }
.selecting .card { cursor: pointer; }
.select-bar { position: fixed; left: 8px; right: 8px; bottom: calc(var(--tabs) + var(--mini) + 8px + env(safe-area-inset-bottom)); z-index: 7; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 12px; background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow); }
.select-bar span { margin-right: auto; font-weight: 600; }
.select-bar button { padding: 8px 12px; font-size: 14px; }
.select-bar button:disabled { opacity: .5; cursor: default; }
.toast { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(var(--tabs) + var(--mini) + 16px + env(safe-area-inset-bottom)); z-index: 7; padding: 10px 18px; background: var(--panel-2); border: 1px solid var(--line); border-radius: 999px; box-shadow: var(--shadow); }
@media (min-width: 900px) {
  .select-bar { left: calc(var(--side) + 24px); right: 24px; bottom: 88px; max-width: 760px; }
  .toast { bottom: 96px; left: calc(50% + var(--side) / 2); }
}

/* ---- admin v2: queue rows ---- */
.admin .plain { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.queue-rows li { display: flex; align-items: center; gap: 8px; border-bottom: 1px solid var(--line); }
.queue-rows li:last-child { border-bottom: none; }
.queue-rows li > a { flex: 1; min-width: 0; border-bottom: none; }
.queue-rows .row-btns { display: flex; gap: 4px; flex: none; }
.queue-rows .row-btns button { padding: 6px 10px; font-size: 14px; min-width: 36px; }
.queue-rows .row-btns button:disabled { opacity: .35; cursor: default; }
@media (max-width: 600px) { .queue-rows li { flex-wrap: wrap; } .queue-rows li > a { flex: 1 1 100%; padding-bottom: 4px; } .queue-rows .row-btns { margin-left: 58px; padding-bottom: 8px; } }
.admin .tiles { margin-top: 16px; }

.seg { display: inline-flex; margin-top: 8px; }
.seg button { border-radius: 0; }
.seg button:first-child { border-radius: 8px 0 0 8px; }
.seg button:last-child { border-radius: 0 8px 8px 0; }
.seg button.on { font-weight: 600; background: var(--accent); color: var(--on-accent); }
.text-size { display: inline-flex; }
.text-size button { font-weight: 600; padding: 6px 7px; }
.text-size button:disabled { opacity: .35; cursor: default; }

/* ---- word lookup (long-press a lyrics word) ---- */
.lyrics .sentence { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.sentence .word-held { background: var(--accent); color: var(--on-accent); border-radius: 4px; }
.define-layer { display: contents; }
.define-backdrop { position: fixed; inset: 0; z-index: 20; background: #0007; }
.define { position: fixed; left: 0; right: 0; bottom: 0; z-index: 21; max-height: 70vh; overflow-y: auto; padding: 14px 18px calc(18px + env(safe-area-inset-bottom)); background: var(--panel); border-top: 1px solid var(--line); border-radius: var(--r-lg) var(--r-lg) 0 0; box-shadow: var(--shadow); animation: sheet-up .18s ease-out; }
@keyframes sheet-up { from { transform: translateY(24px); opacity: 0; } }
.define header { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.define h2 { margin: 0; font-size: 22px; text-transform: none; letter-spacing: normal; color: var(--text); }
.define .close { padding: 6px 10px; }
.define h2 { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.define .copy { padding: 6px 10px; font-size: 13px; }
.define .headword { margin: 2px 0 0; font-size: 18px; }
.define .form-of { margin: 8px 0 0; font-style: italic; }
.define .entry h4 { margin: 14px 0 4px; font-size: 13px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.define ol { margin: 0; padding-left: 22px; line-height: 1.45; }
.define li + li { margin-top: 4px; }
.define .example { margin: 6px 0 0; color: var(--muted); font-style: italic; }
.define .source { display: inline-block; margin-top: 14px; font-size: 12px; }
@media (min-width: 900px) {
  .define-backdrop { background: transparent; }
  .define { left: auto; right: auto; bottom: auto; width: 360px; max-height: 50vh; border: 1px solid var(--line); border-radius: var(--r-lg); }
}

/* ---- settings ---- */
.settings label { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 16px; flex-wrap: wrap; }
.settings select { min-width: 12em; }

/* ---- immersive lock (player) ---- */
.player.locked { display: flex; flex-direction: column; padding: 0; max-width: none; }
.player.locked > header, .player.locked > .player-cover, .player.locked > .error, .player.locked > .seek, .player.locked > .controls, .player.locked .back-to-now { display: none; }
.player.locked .lyrics { grid-column: auto; grid-row: auto; overflow: hidden; padding: 0 16px; max-width: 760px; width: 100%; margin: 0 auto; }
.player.locked .subbar { position: fixed; left: 0; right: 0; bottom: calc(12px + env(safe-area-inset-bottom)); padding: 0 12px; z-index: 30; }
.player.locked .subbar > :not(.up-next) { display: none; }
.lock-overlay { position: fixed; inset: 0; z-index: 20; touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.lock-paused { position: fixed; z-index: 21; left: 50%; transform: translateX(-50%); bottom: calc(24px + env(safe-area-inset-bottom)); margin: 0; padding: 6px 14px; background: var(--panel); border: 1px solid var(--line); border-radius: 999px; text-align: center; color: var(--muted); font-size: 14px; letter-spacing: .08em; pointer-events: none; }
.unlock { position: fixed; z-index: 25; top: calc(10px + env(safe-area-inset-top)); right: calc(12px + env(safe-area-inset-right)); width: 48px; height: 48px; padding: 0; display: grid; place-items: center; overflow: hidden; background: none; border: 1px solid transparent; color: var(--muted); opacity: .4; touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.unlock.holding { opacity: .9; }
.unlock-fill { position: absolute; left: 0; bottom: 0; height: 4px; width: 0; background: var(--accent); }
.unlock.holding .unlock-fill { animation: unlock-fill 1s linear forwards; }
@keyframes unlock-fill { to { width: 100%; } }
.unlock-hint { position: fixed; z-index: 26; top: calc(66px + env(safe-area-inset-top)); right: calc(12px + env(safe-area-inset-right)); margin: 0; padding: 4px 10px; border-radius: 14px; font-size: 13px; background: var(--panel); border: 1px solid var(--line); color: var(--text); pointer-events: none; }

/* ---- admin tabs + people ---- */
.admin-tabs { margin: 0 0 8px; }
.admin-tabs a { padding: 8px 16px; border: 1px solid var(--line); background: var(--panel); }
.admin-tabs a:first-child { border-radius: 8px 0 0 8px; }
.admin-tabs a:last-child { border-radius: 0 8px 8px 0; border-left: none; }
.admin-tabs a.on { font-weight: 600; background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.small { font-size: 13px; }
.badge { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; padding: 1px 6px; margin-left: 8px; border-radius: 6px; background: var(--line); color: var(--muted); vertical-align: middle; }
.people-rows { list-style: none; margin: 0; padding: 0; }
.person { border-bottom: 1px solid var(--line); }
.person:last-child { border-bottom: none; }
.person.inactive { opacity: .5; }
.person-row { all: unset; box-sizing: border-box; cursor: pointer; width: 100%; display: grid; grid-template-columns: minmax(0, 1fr) repeat(4, auto); gap: 18px; align-items: center; padding: 12px 0; }
.person-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
.person .who { display: grid; gap: 4px; min-width: 0; }
.person .who > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.person .num { display: grid; text-align: right; white-space: nowrap; min-width: 64px; }
.sessions { list-style: none; margin: 0 0 12px; padding: 0 0 0 14px; border-left: 2px solid var(--line); }
.sessions li { display: grid; gap: 2px; padding: 6px 0; }
.sessions .title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.app-row { display: grid; grid-template-columns: 80px 1fr auto; gap: 12px; align-items: center; padding: 8px 0; }
.two-col { display: grid; gap: 0 16px; }
@media (min-width: 900px) { .two-col { grid-template-columns: 2fr 1fr; } .people .tiles { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 600px) {
  .person-row { grid-template-columns: minmax(0, 1fr) auto auto; gap: 12px; }
  .person .num.wide, .person .num:nth-child(2) { display: none; }
}
.earlier { border-top: 1px solid var(--line); padding-top: 10px; }
.people-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.people-head button { padding: 6px 12px; font-size: 14px; margin-top: 8px; }
.user-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 8px; }
.user-actions button { padding: 6px 10px; font-size: 14px; }
.user-actions button:disabled { opacity: .4; cursor: default; }
.user-actions + .muted { margin: 0 0 8px; }
.user-form .settings label { padding-top: 10px; }
.user-form .settings input, .user-form .settings select { flex: 1 1 12em; min-width: 0; }
.user-form > form > input { width: 100%; box-sizing: border-box; }
.user-form .features { margin-top: 16px; }
.user-form .picks { max-height: 200px; overflow-y: auto; margin-left: 30px; }
.earlier summary { cursor: pointer; padding: 4px 0 8px; }

/* ---- keyboard shortcuts (settings) ---- */
.keys { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px 18px; margin: 0; }
.keys dt { white-space: nowrap; }
.keys kbd { font-family: inherit; font-weight: 600; font-size: 14px; line-height: 1; padding: 3px 7px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 6px; background: var(--panel); }
.keys dd { margin: 0; color: var(--muted); overflow-wrap: anywhere; }
/* Desktop two-column player: the control column is ~380 px, too narrow for a usable slider in the button row. */
@media (min-width: 900px) {
  .player .controls { flex-wrap: wrap; row-gap: 6px; }
  .player .controls .volume { flex: 0 0 100%; justify-content: center; margin: 0; }
  .player .controls .volume input[type=range] { flex: 0 1 200px; }
}

/* ---- optional features + collections/playlists ---- */
.features { display: grid; gap: 12px; }
.feature { display: flex; gap: 12px; align-items: flex-start; cursor: pointer; }
.feature input { margin-top: 4px; accent-color: var(--accent); width: 18px; height: 18px; padding: 0; }
.feature > span { display: grid; gap: 2px; }
.list-page .book-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 8px 0 18px; }
button.play-btn { border: none; }
.danger-text { color: var(--danger) !important; }
.list-book { position: relative; }
.remove-from-list { position: absolute; top: 6px; right: 6px; width: 30px; height: 30px; padding: 0; border-radius: 50%; background: #000a; border: none; color: #fff; opacity: 0; transition: opacity .15s; }
.list-book:hover .remove-from-list, .remove-from-list:focus-visible { opacity: 1; }
@media (hover: none) { .remove-from-list { opacity: 1; } }
.add-to { margin-top: 10px; max-width: 420px; }
.add-to h3 { margin: 14px 0 6px; font-size: 14px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.checks li label { display: flex; gap: 10px; align-items: center; padding: 5px 0; cursor: pointer; }
.checks input { accent-color: var(--accent); width: 17px; height: 17px; padding: 0; }
.new-list { display: flex; gap: 8px; margin-top: 6px; }
.new-list input { flex: 1; min-width: 0; padding: 8px 10px; }
.new-list button { padding: 8px 12px; }

/* ---- sync badge + two-positions banner ---- */
.seek-line-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.sync-badge-wrap { position: relative; display: inline-flex; }
.sync-badge { display: inline-flex; align-items: center; gap: 5px; background: none; border: none; padding: 2px 4px; color: var(--muted); font-size: 12px; border-radius: 6px; }
.sync-badge .icon { width: 16px; height: 16px; }
.sync-badge.warn { color: var(--accent); }
.sync-badge:hover { color: var(--text); }
.mini .sync-badge .icon { width: 18px; height: 18px; }
.sync-details { position: absolute; right: 0; bottom: calc(100% + 6px); z-index: 20; width: min(300px, 80vw); background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 10px 14px; box-shadow: 0 8px 24px #0008; font-size: 14px; }
.sync-details p { margin: 4px 0; }
.choice-banner { margin: 8px 0; padding: 10px 14px; border: 1px solid var(--accent); border-radius: var(--r-lg); background: var(--panel); font-size: 14px; }
.choice-banner p { margin: 0 0 6px; }
.choice-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 4px 0; }
.choice-row.current span { color: var(--text); font-weight: 600; }
.choice-row button { padding: 6px 10px; font-size: 13px; white-space: nowrap; }
.choice-row button.primary { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
/* Downloads */
.card.unavailable { opacity: .4; }
.download { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.check { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.download-list { list-style: none; padding: 0; margin: 0 0 16px; display: flex; flex-direction: column; gap: 10px; }
.download-list li { display: flex; align-items: center; gap: 12px; }
.download-cover { flex: 0 0 56px; }
.download-cover img { width: 56px; height: 56px; object-fit: cover; border-radius: 6px; }
.download-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.download-text .title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Book page action row: Play · Download · ⋯ */
.book-actions { position: relative; flex-wrap: nowrap; width: fit-content; max-width: 100%; }
@media (max-width: 699px) { .book-actions { width: auto; } }
.secondary-btn { display: inline-flex; align-items: center; gap: 8px; padding: 10px 16px; border-radius: var(--r); background: var(--panel-2); border: 1px solid var(--line); color: var(--text); white-space: nowrap; font-variant-numeric: tabular-nums; }
.secondary-btn .icon { width: 18px; height: 18px; }
.secondary-btn.done { color: var(--muted); }
.secondary-btn.busy .icon { color: var(--accent); }
.icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; padding: 0; border-radius: var(--r); background: none; border: 1px solid var(--line); color: var(--muted); }
.icon-btn:hover, .secondary-btn:hover { color: var(--text); }
.icon-btn .icon { width: 22px; height: 22px; stroke-width: 3; }
.more-menu { position: absolute; z-index: 8; top: calc(100% + 6px); right: 0; min-width: 210px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow); padding: 6px; display: grid; }
.more-menu button { padding: 10px 12px; border: none; background: none; border-radius: var(--r); text-align: left; color: var(--text); }
.more-menu button:hover { background: var(--panel-2); }
@media (max-width: 699px) {
  .book-actions { flex-direction: row; align-items: center; }
  .book-actions .play-btn { flex: 1; }
}
/* Player: one short line under the seek bar; the sync state is an icon (tap for details) */
.seek-line-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.seek-line { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.toast { position: fixed; z-index: 20; left: 50%; transform: translateX(-50%); bottom: calc(var(--tabs, 0px) + env(safe-area-inset-bottom) + 84px); max-width: calc(100vw - 32px); padding: 10px 16px; border-radius: var(--r-lg); background: var(--panel); border: 1px solid var(--line); box-shadow: var(--shadow); color: var(--text); font-size: 14px; }
.offer-delete { position: fixed; z-index: 21; left: 50%; transform: translateX(-50%); bottom: calc(var(--tabs, 0px) + env(safe-area-inset-bottom) + 16px); width: min(420px, calc(100vw - 32px)); padding: 16px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow); }
.offer-delete p { margin: 0; }

/* ---- listen together (spec §14): one quiet icon, no animation ---- */
.subbar .together { position: relative; display: inline-flex; }
.together.on { color: var(--text); }
.together.catching::after { content: ""; position: absolute; top: 4px; right: 4px; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
/* Dimmed only after 3 s of reconnecting: a delayed step (0 s duration), no timer and no animation. */
.together.offline { opacity: .4; transition: opacity 0s 3s; }
.together.held { outline: 1px solid currentColor; outline-offset: -2px; border-radius: 8px; }
.together.blocked { color: var(--accent); }
.install-banner { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 14px; padding: 10px 12px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg); }
.install-banner > span:first-child { flex: 1; }
.together-sheet { display: grid; gap: 10px; padding: 12px 14px; }
.together-sheet p { margin: 0; }
.together-sheet .feature { align-items: center; }
.together-sheet .feature input { margin-top: 0; }
.together-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

/* ---- popups come out of what opened them (owner 2026-11-05, like DankMaterialShell): the popup and its anchor
   are one shape, joined by curved corners (same colours, no blur). Open unrolls out of the anchor, close rolls back
   in (AnimatedShow keeps it mounted for POP_OUT_MS). Compositor-cheap and only while opening or closing. ---- */
:root { --pop-r: 10px; }
.pop-in, .pop-out { display: contents; }
.pop-in > .pop { animation: pop-up-in .2s cubic-bezier(.2, .9, .3, 1); }
.pop-out > .pop { animation: pop-up-out .13s ease-in forwards; pointer-events: none; }
.pop-in > .pop.down { animation-name: pop-dn-in; }
.pop-out > .pop.down { animation-name: pop-dn-out; }
/* The popup grows out of its anchor edge (scale, not a clip), so its shadow is drawn the whole way. */
.pop { transform-origin: 50% 100%; }
.pop.down { transform-origin: 50% 0; }
@keyframes pop-up-in { from { transform: scaleY(.3); opacity: 0; } 35% { opacity: 1; } to { transform: none; opacity: 1; } }
@keyframes pop-up-out { from { transform: none; opacity: 1; } 65% { opacity: 1; } to { transform: scaleY(.3); opacity: 0; } }
@keyframes pop-dn-in { from { transform: scaleY(.3); opacity: 0; } 35% { opacity: 1; } to { transform: none; opacity: 1; } }
@keyframes pop-dn-out { from { transform: none; opacity: 1; } 65% { opacity: 1; } to { transform: scaleY(.3); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .pop-in > .pop, .pop-out > .pop { animation: none; }
  .pop-out > .pop { visibility: hidden; }
}
/* Each popup overlaps its anchor by 1px (drawn on top, same colour): edges that fall between device pixels leave
   no hairline. Shadows are one-sided (negative spread), away from the anchor, so none darkens the join. */
/* The anchor: panel-coloured while open, with a curved corner on each side where it meets the popup. `up`: the popup
   is above it; `dn`: below. `edge`: the popup is flush with its right side (no right curve); `edge-l`: left side. */
.anchor { position: relative; transition: background-color .13s, color .13s, border-color .13s; }
.anchor.open { background: var(--panel); color: var(--text); border-color: transparent; }
.anchor.up.open { border-radius: 0 0 var(--r) var(--r); }
.anchor.dn.open { border-radius: var(--r) var(--r) 0 0; }
.anchor::before, .anchor::after { content: ""; position: absolute; width: var(--pop-r); height: var(--pop-r); opacity: 0; transition: opacity .13s; pointer-events: none; }
.anchor.open::before, .anchor.open::after { opacity: 1; }
.anchor::before { left: calc(-1 * var(--pop-r)); }
.anchor::after { right: calc(-1 * var(--pop-r)); }
.anchor.up::before { top: 0; background: radial-gradient(circle at 0 100%, transparent calc(var(--pop-r) - .5px), var(--panel) var(--pop-r)); }
.anchor.up::after { top: 0; background: radial-gradient(circle at 100% 100%, transparent calc(var(--pop-r) - .5px), var(--panel) var(--pop-r)); }
.anchor.dn::before { bottom: 0; background: radial-gradient(circle at 0 0, transparent calc(var(--pop-r) - .5px), var(--panel) var(--pop-r)); }
.anchor.dn::after { bottom: 0; background: radial-gradient(circle at 100% 0, transparent calc(var(--pop-r) - .5px), var(--panel) var(--pop-r)); }
.anchor.edge::after, .anchor.edge-l::before { display: none; }
/* Player panels sit on the icon row; the icons span the row's height so their tops meet the panel. */
.subbar { --subbar-pad: 6px; padding-top: var(--subbar-pad); }
.subbar .pop { bottom: calc(100% - var(--subbar-pad) - 1px); margin: 0; border: none; box-shadow: 0 -14px 24px -10px #0009; }
.panel-icons { z-index: 1; }
.panel-icons .anchor { --pop-r: 14px; align-self: stretch; display: inline-flex; align-items: center; }
.panel-icons .anchor.up.open { border-radius: 0 0 var(--r-lg) var(--r-lg); }
.panel-icons .anchor > button { background: none; }
/* Account menu: on the tab bar, over its top line; curves on both sides into the bar. */
.account-menu.pop { bottom: calc(var(--tabs) + env(safe-area-inset-bottom) - 1px); border: none; border-radius: var(--r-lg) var(--r-lg) 0 0; box-shadow: 0 -14px 24px -10px #0009; }
.account-menu.pop::before, .account-menu.pop::after { content: ""; position: absolute; bottom: 0; width: var(--pop-r); height: var(--pop-r); pointer-events: none; }
.account-menu.pop::before { left: calc(-1 * var(--pop-r)); background: radial-gradient(circle at 0 0, transparent calc(var(--pop-r) - .5px), var(--panel) var(--pop-r)); }
.account-menu.pop::after { right: calc(-1 * var(--pop-r)); background: radial-gradient(circle at 100% 0, transparent calc(var(--pop-r) - .5px), var(--panel) var(--pop-r)); }
/* Book page ⋯ menu: under its button, flush with the button's right side. */
.book-actions .icon-btn.anchor { align-self: stretch; height: auto; }
.more-menu.pop { top: calc(100% - 1px); border: none; box-shadow: 0 14px 24px -10px #0009; border-radius: var(--r-lg) 0 var(--r-lg) var(--r-lg); }
/* Sync details: above the badge, flush with its right side. */
.sync-details.pop { bottom: calc(100% - 1px); border: none; border-radius: var(--r-lg) var(--r-lg) 0 var(--r-lg); box-shadow: 0 -14px 24px -10px #0009; }
/* A panel's scrollbar follows its curve: a slim rounded thumb on a clear track, kept off the rounded corners
   (Chromium: ::-webkit-scrollbar, track margin = corner radius; Firefox: its thin themed one, clipped to the radius). */
.pop::-webkit-scrollbar { width: 12px; }
.pop::-webkit-scrollbar-track { background: transparent; margin-block: var(--r-lg); }
.pop::-webkit-scrollbar-thumb { background: var(--line); border: 3px solid transparent; border-radius: 6px; background-clip: padding-box; }
.pop::-webkit-scrollbar-thumb:hover { background-color: #565b65; }
.pop::-webkit-scrollbar-button { display: none; }
/* The app sets the standard scrollbar-width/-color for everything (html, *), and Chromium then ignores the
   ::-webkit-scrollbar styles: undo them on panels where those styles apply. Firefox keeps the global thin one. */
@supports selector(::-webkit-scrollbar) {
  .pop { scrollbar-width: auto; scrollbar-color: auto; }
}

/* ---- authors & narrators (optional), book ⋯ Files / Share, Settings → Password ---- */
.card .no-image { display: grid; place-items: center; height: 100%; color: var(--muted); }
.card .no-image .icon { width: 40%; height: 40%; stroke-width: 1.2; }
.file-list { list-style: none; margin: 0; padding: 0; }
.file-list li { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.file-list .file { display: grid; min-width: 0; overflow-wrap: anywhere; }
.confirm-actions .save-all { padding: 8px 16px; }
.share-link { display: flex; gap: 8px; margin: 8px 0; }
.share-link input { flex: 1; min-width: 0; }
.password form { display: grid; gap: 10px; max-width: 360px; }
