/* Reading Room design system. See docs/specs/2026-08-01-reading-room-design.md
   in the library repo for the full rationale (fonts, contrast ratios, scale). */

/* ---------------------------------------------------------------------------
   Fonts: self-hosted, Latin subset, font-display swap. No Google CDN.
--------------------------------------------------------------------------- */
@font-face {
  font-family: 'Lexend';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/lexend-400.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: 'Lexend';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/lexend-500.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: 'Atkinson Hyperlegible Next';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/atkinson-hyperlegible-next-700.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: 'Atkinson Hyperlegible Next';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('fonts/atkinson-hyperlegible-next-800.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: 'Atkinson Hyperlegible Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/atkinson-hyperlegible-mono-400.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: 'Atkinson Hyperlegible Mono';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/atkinson-hyperlegible-mono-700.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;
}

/* ---------------------------------------------------------------------------
   Root tokens. Paper is the default and lives directly on :root; the three
   data-theme blocks let the reader-controls bar swap the whole palette with
   one attribute change.
--------------------------------------------------------------------------- */
:root {
  --font-body: 'Lexend', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
  --font-heading: 'Atkinson Hyperlegible Next', 'Atkinson Hyperlegible', ui-sans-serif, system-ui, sans-serif;
  --font-mono: 'Atkinson Hyperlegible Mono', ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;

  --measure: 62ch;
  --radius-card: 16px;
  --radius-btn: 12px;
  --radius-input: 10px;
  --radius-thumb: 12px;

  /* Paper (default) */
  --bg: #FAF6EE;
  --surface: #F2ECDF;
  --text: #2E2A24;
  --muted: #6E6656;
  --border: #E3DACB;
  --accent: #3F6E64;
  --accent-contrast: #FFFFFF;
}

:root[data-theme="paper"] {
  --bg: #FAF6EE;
  --surface: #F2ECDF;
  --text: #2E2A24;
  --muted: #6E6656;
  --border: #E3DACB;
  --accent: #3F6E64;
  --accent-contrast: #FFFFFF;
}

:root[data-theme="sepia"] {
  --bg: #F1E4C9;
  --surface: #E9D9B8;
  --text: #3B2E1E;
  --muted: #6C5936;
  --border: #D9C6A0;
  --accent: #6B4A32;
  --accent-contrast: #FFFFFF;
}

:root[data-theme="dark"] {
  --bg: #1E1B17;
  --surface: #28241F;
  --text: #E4DED2;
  --muted: #9B9385;
  --border: #3A352C;
  --accent: #7FA89D;
  --accent-contrast: #1E1B17;
}

/* ---------------------------------------------------------------------------
   Base + type scale. Root 112.5% (1rem = 18px on a 16px browser default).
   The text-size stepper sets an inline px value on the root, which wins over
   this percentage rule, and every size below reflows because it is in rem.
--------------------------------------------------------------------------- */
* { box-sizing: border-box; }

html { font-size: 112.5%; }

body {
  margin: 0;
  overflow-x: hidden;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

a { color: var(--accent); }
a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: 700; line-height: 1.2; color: var(--text); }

.lib-wrap { max-width: 1100px; margin: 0 auto; padding: 48px 24px 96px; }
.lib-wrap.lib-read { max-width: var(--measure); }

.lib-eyebrow {
  font-family: var(--font-mono); font-size: 0.75rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent);
}

/* ---------------------------------------------------------------------------
   Index list
--------------------------------------------------------------------------- */
.lib-search {
  width: 100%; padding: 14px 16px; background: var(--surface);
  border: 1px solid var(--border); color: var(--text); border-radius: var(--radius-input);
  font-family: var(--font-body); font-size: 1rem; margin: 24px 0 8px;
}
.lib-search::placeholder { color: var(--muted); }
.lib-search:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.lib-list { list-style: none; padding: 0; margin: 24px 0 0; display: flex; flex-direction: column; gap: 12px; }
.lib-item a {
  display: grid; grid-template-columns: 3.5rem 1fr auto; gap: 16px;
  align-items: baseline; padding: 18px 20px; border: 1px solid var(--border);
  border-radius: var(--radius-card); text-decoration: none; color: var(--text);
  background: var(--surface);
  transition: border-color .15s ease, background-color .15s ease;
}
.lib-item a:hover, .lib-item a:focus-visible {
  border-color: var(--accent);
  background: var(--surface);
  background: color-mix(in srgb, var(--surface) 88%, var(--accent) 12%);
}
.lib-item a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-num { font-family: var(--font-mono); font-size: 0.875rem; color: var(--muted); }
.lib-title { font-weight: 600; }
.lib-meta { color: var(--muted); font-size: 0.875rem; }
.lib-audio-flag {
  font-family: var(--font-mono); font-size: 0.6875rem;
  letter-spacing: 0.1em; color: var(--accent); text-transform: uppercase;
}

/* ---------------------------------------------------------------------------
   Book page
--------------------------------------------------------------------------- */
.lib-back { font-family: var(--font-mono); font-size: 0.8125rem; color: var(--muted); text-decoration: none; }
.lib-back:hover { color: var(--accent); }

.lib-head { border-bottom: 1px solid var(--border); padding-bottom: 24px; margin-bottom: 32px; }
.lib-head h1 { font-family: var(--font-heading); font-weight: 800; font-size: 2rem; line-height: 1.2; margin: 8px 0 4px; }
.lib-byline { color: var(--muted); font-size: 0.875rem; line-height: 1.5; }

.lib-player { margin: 24px 0 40px; }
.lib-audio {
  display: flex; align-items: center; gap: 14px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-card); padding: 12px 16px;
}
.lib-audio-btn {
  flex: none; width: 44px; height: 44px; display: grid; place-items: center;
  background: var(--accent); color: var(--accent-contrast); border: 0;
  border-radius: var(--radius-btn); cursor: pointer;
  transition: background-color .15s ease;
}
.lib-audio-btn:hover {
  background: var(--accent);
  background: color-mix(in srgb, var(--accent), var(--text) 20%);
}
.lib-audio-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-audio-seek {
  flex: 1; -webkit-appearance: none; appearance: none; height: 6px;
  border-radius: 999px; background: var(--border); cursor: pointer;
}
.lib-audio-seek::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 16px; height: 16px; border-radius: 50%; background: var(--accent); cursor: pointer;
}
.lib-audio-seek::-moz-range-thumb {
  width: 16px; height: 16px; border-radius: 50%; background: var(--accent);
  border: 0; cursor: pointer;
}
.lib-audio-seek:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-audio-time {
  flex: none; font-family: var(--font-mono); font-size: 0.8125rem;
  color: var(--muted); min-width: 88px; text-align: right;
}
.lib-noaudio {
  font-family: var(--font-mono); font-size: 0.8125rem; color: var(--muted);
  border: 1px dashed var(--border); border-radius: var(--radius-card); padding: 12px 16px;
}

.lib-guide { font-size: 1rem; line-height: 1.6; text-align: left; overflow-wrap: break-word; }
.lib-guide h2 { font-family: var(--font-heading); font-weight: 700; font-size: 1.556rem; line-height: 1.3; margin: 40px 0 12px; }
.lib-guide h3 { font-family: var(--font-heading); font-weight: 700; font-size: 1.222rem; line-height: 1.35; margin: 28px 0 8px; }
.lib-guide h4 { font-family: var(--font-heading); font-weight: 700; font-size: 1.083rem; line-height: 1.4; margin: 24px 0 8px; }
.lib-guide p { margin: 0 0 1.5em; }
.lib-guide ul, .lib-guide ol { margin: 0 0 1.5em; padding-left: 1.4em; }
.lib-guide li { margin-bottom: 0.5em; }
.lib-guide li:last-child { margin-bottom: 0; }
.lib-guide strong { font-weight: 600; }
.lib-guide em { font-style: italic; }

/* ---------------------------------------------------------------------------
   Explore further: exploration prompts a reader can copy into an AI
   assistant. Sits after the guide, before the prev/next nav.
--------------------------------------------------------------------------- */
.lib-explore { margin: 48px 0 0; }
.lib-explore-heading { font-family: var(--font-heading); font-weight: 700; font-size: 1.556rem; line-height: 1.3; margin: 0 0 8px; }
.lib-explore-intro { color: var(--muted); font-size: 0.875rem; line-height: 1.5; margin: 0 0 20px; }

.lib-prompt-list { display: flex; flex-direction: column; gap: 12px; }
.lib-prompt {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 16px 18px;
}
.lib-prompt-text { flex: 1; margin: 0; color: var(--text); font-size: 0.9375rem; line-height: 1.55; overflow-wrap: break-word; }
.lib-prompt-copy {
  flex: none; min-height: 44px; padding: 8px 16px; display: flex; align-items: center; justify-content: center;
  background: var(--bg); color: var(--text); border: 1px solid var(--border);
  border-radius: var(--radius-btn); font-family: var(--font-body); font-size: 0.8125rem;
  font-weight: 600; cursor: pointer; transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.lib-prompt-copy:hover { border-color: var(--accent); color: var(--accent); }
.lib-prompt-copy:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-prompt-copy[data-copied="true"] {
  background: var(--accent); color: var(--accent-contrast); border-color: var(--accent);
}

.lib-nav {
  display: flex; justify-content: space-between; gap: 16px;
  border-top: 1px solid var(--border); margin-top: 48px; padding-top: 24px;
}
.lib-nav a { text-decoration: none; }
.lib-nav a:hover { text-decoration: underline; }

/* ---------------------------------------------------------------------------
   Generic button (gate "Enter", and any future primary action)
--------------------------------------------------------------------------- */
.lib-btn {
  cursor: pointer; background: var(--accent); color: var(--accent-contrast);
  border: 0; border-radius: var(--radius-btn); font-family: var(--font-body);
  font-weight: 600; font-size: 1rem; padding: 14px 20px; min-height: 44px;
  transition: background-color .15s ease;
}
.lib-btn:hover {
  background: var(--accent);
  background: color-mix(in srgb, var(--accent), var(--text) 15%);
}
.lib-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------------------------------------------------------------------------
   Reader-controls bar: theme switch, text-size stepper, focus-bolding toggle.
--------------------------------------------------------------------------- */
.lib-controls {
  display: flex; flex-wrap: wrap; align-items: flex-start; gap: 20px 32px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 20px 24px; margin: 24px 0 32px;
}
.lib-controls-group { display: flex; flex-direction: column; gap: 8px; min-width: 160px; border: 0; margin: 0; padding: 0; }
.lib-controls-label {
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted);
}

/* Theme switch: native radios, visually a segmented control */
.lib-theme-options { display: flex; gap: 4px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-btn); padding: 4px; }
.lib-theme-choice { position: relative; display: flex; flex: 1; }
.lib-theme-radio { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; z-index: 1; }
.lib-theme-option {
  position: relative; z-index: 0; flex: 1; display: flex; align-items: center; justify-content: center;
  min-height: 40px; padding: 8px 14px; border-radius: var(--radius-btn);
  font-family: var(--font-body); font-size: 0.875rem; font-weight: 500;
  color: var(--muted); cursor: pointer; user-select: none;
}
.lib-theme-radio:checked + .lib-theme-option { background: var(--accent); color: var(--accent-contrast); }
.lib-theme-radio:focus-visible + .lib-theme-option { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-theme-option:hover { color: var(--text); }
.lib-theme-radio:checked + .lib-theme-option:hover { color: var(--accent-contrast); }

/* Text-size stepper: real buttons */
.lib-size-buttons { display: flex; align-items: center; gap: 6px; }
.lib-size-btn {
  min-width: 44px; min-height: 44px; padding: 8px 12px; display: flex; align-items: center; justify-content: center;
  background: var(--bg); color: var(--text); border: 1px solid var(--border);
  border-radius: var(--radius-btn); font-family: var(--font-body); font-size: 0.9375rem; font-weight: 500;
  cursor: pointer;
}
.lib-size-btn:hover { border-color: var(--accent); color: var(--accent); }
.lib-size-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-size-value { font-family: var(--font-mono); font-size: 0.875rem; color: var(--muted); min-width: 3.2em; text-align: center; }
.lib-size-reset { font-size: 0.8125rem; }

/* Focus-bolding: real checkbox styled as a switch, plus intensity radios */
.lib-toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; cursor: pointer; }
.lib-toggle-track { position: relative; flex: none; width: 44px; height: 24px; border-radius: 999px; background: var(--border); }
.lib-toggle-input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.lib-toggle-thumb {
  position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--bg); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  transition: transform .15s ease, background-color .15s ease;
}
.lib-toggle-input:checked ~ .lib-toggle-thumb { transform: translateX(20px); background: var(--accent); }
.lib-toggle-track:has(.lib-toggle-input:checked) { background: var(--accent); }
.lib-toggle-input:focus-visible ~ .lib-toggle-thumb { outline: 2px solid var(--accent); outline-offset: 2px; }

.lib-fb-options { display: flex; gap: 4px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-btn); padding: 4px; }
.lib-fb-choice { position: relative; display: flex; flex: 1; }
.lib-fb-radio { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; z-index: 1; }
.lib-fb-option {
  position: relative; z-index: 0; flex: 1; display: flex; align-items: center; justify-content: center;
  min-height: 36px; padding: 6px 10px; border-radius: var(--radius-btn);
  font-family: var(--font-body); font-size: 0.8125rem; font-weight: 500;
  color: var(--muted); cursor: pointer; user-select: none;
}
.lib-fb-radio:checked + .lib-fb-option { background: var(--accent); color: var(--accent-contrast); }
.lib-fb-radio:focus-visible + .lib-fb-option { outline: 2px solid var(--accent); outline-offset: 2px; }

.lib-focusbold-desc { color: var(--muted); font-size: 0.8125rem; line-height: 1.5; margin: 4px 0 0; max-width: 44ch; }

/* Applied to the leading portion of each word when focus-bolding is on.
   Screen-reader text is unaffected: the word's full characters are still
   present, split only between this element and its sibling text node. */
.fixation { font-weight: 700; }

/* ---------------------------------------------------------------------------
   Passphrase gate: calm, centered login card on the plain paper background.
   No hero photo and no recommendation UI here; both live on the index (see
   "Index hero" below), which is the first page a reader sees once past the
   gate. Built from the shared design tokens rather than the photo-specific
   hex values the hero column below needs for contrast against a busy image.
--------------------------------------------------------------------------- */
.lib-gate-body { margin: 0; overflow-x: hidden; }
.lib-gate-wrap {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.lib-gate-card {
  width: 100%;
  max-width: 440px;
  padding: 40px 36px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
}
.lib-gate-title {
  font-family: var(--font-heading); font-weight: 800; color: var(--text);
  font-size: clamp(2rem, 5vw, 2.6rem); line-height: 1.05; margin: 8px 0 12px;
}
.lib-gate-sub { font-size: 1.0625rem; line-height: 1.5; color: var(--text); margin: 0 0 10px; max-width: 46ch; }
.lib-gate-hint { color: var(--muted); font-size: 0.875rem; line-height: 1.5; margin: 0 0 28px; max-width: 46ch; }
.lib-gate-form { margin: 0; display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px; }
.lib-gate-input {
  flex: 1 1 100%; width: 100%; padding: 14px 16px;
  background: var(--bg); border: 1px solid var(--border);
  color: var(--text); border-radius: var(--radius-input);
  font-family: var(--font-body); font-size: 1rem;
}
.lib-gate-input::placeholder { color: var(--muted); letter-spacing: 0.04em; }
.lib-gate-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------------------------------------------------------------------------
   Index hero: full-bleed background photo (warm home-library scene, brass
   lamp and armchair on the right), a dark-ink content column sitting on the
   photo's plain left-hand wall, and a chalkboard recommendation panel below
   the title. Sits above .lib-wrap at the top of the authenticated index;
   every rule below is scoped to the .lib-hero* and .lib-chalk* classes,
   which only the index template renders, so nothing here can leak onto the
   gate or book pages.

   Contrast verified 2026-08-02 against a real sample of hero.jpg (see
   docs/specs in the library repo): dark ink #241c14 on the lightest panel
   blend measures 8.3:1+ even at the gradient's most transparent stop, and
   9.3:1+ at its most opaque; the muted warm brown #4a3826 measures 5.5:1+
   across the same range. Both clear WCAG AA (4.5:1) with margin.
--------------------------------------------------------------------------- */

/* The recommendation wall now holds a fixed footprint (notes stack into a
   pile rather than tiling), so the hero no longer grows with submissions.
   The photo still lives on ::before, pinned to the top and capped at the
   hero's target height, so it always renders at a sane, undistorted scale
   even if the column's content runs a little long; .lib-hero itself just
   supplies a solid warm fallback for everything below that band. */
.lib-hero {
  position: relative;
  min-height: 560px;
  min-height: max(560px, 78vh);
  min-height: max(560px, 78svh);
  display: flex;
  align-items: center;
  background: #2b2015;
  overflow: hidden;
}
.lib-hero::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 560px;
  height: max(560px, 78vh);
  height: max(560px, 78svh);
  z-index: 0;
  background-color: #3c2f22;
  background-image:
    linear-gradient(to bottom, rgba(36, 28, 20, 0) 58%, rgba(36, 28, 20, 0.16) 100%),
    url('hero.jpg');
  background-image:
    linear-gradient(to bottom, rgba(36, 28, 20, 0) 58%, rgba(36, 28, 20, 0.16) 100%),
    -webkit-image-set(url('hero.webp') 1x);
  background-image:
    linear-gradient(to bottom, rgba(36, 28, 20, 0) 58%, rgba(36, 28, 20, 0.16) 100%),
    image-set(url('hero.webp') type('image/webp'), url('hero.jpg') type('image/jpeg'));
  background-size: auto, cover;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
  -webkit-mask-image: linear-gradient(to bottom, #000 82%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 82%, transparent 100%);
}

.lib-hero-col {
  position: relative;
  z-index: 1;
  width: 48%;
  min-width: 380px;
  max-width: 620px;
  padding: 72px 40px 56px 24px;
  color: #241c14;
  background: linear-gradient(100deg, rgba(250, 246, 238, 0.86) 0%, rgba(250, 246, 238, 0.6) 62%, rgba(250, 246, 238, 0) 92%);
}

.lib-hero-eyebrow {
  font-family: var(--font-mono); font-size: 0.8125rem;
  letter-spacing: 0.16em; text-transform: uppercase; color: #4a3826; margin: 0 0 12px;
}
.lib-hero-title {
  font-family: var(--font-heading); font-weight: 800; color: #241c14;
  font-size: clamp(2.4rem, 5vw, 3.4rem); line-height: 1.05; margin: 0 0 14px;
}

@media (max-width: 860px) {
  .lib-hero-col { width: 100%; max-width: none; min-width: 0; padding: 64px 24px 40px; }
}
@media (max-width: 640px) {
  .lib-hero::before { background-position: left center, left center; }
  .lib-hero-col {
    padding: 48px 16px 36px;
    /* Lower opacity than the desktop panel on purpose: the column is full
       width here, so this is the only way the photo still reads as a top
       band behind the header rather than being fully hidden. Contrast
       verified down to alpha 0.5 against the photo's darkest sampled
       region: ink #241c14 measures 8.3:1+, muted #4a3826 measures 5.5:1+,
       both well past WCAG AA (4.5:1). */
    background:
      linear-gradient(180deg, rgba(250, 246, 238, 0.72) 0%, rgba(250, 246, 238, 0.6) 55%, rgba(250, 246, 238, 0.52) 100%);
  }
}

/* ---------------------------------------------------------------------------
   Chalkboard: the "Recommend a book" form and the wall of sticky-note
   recommendations, framed as one board sitting inside the index hero's left
   column, directly below the title. Warmed deliberately (charcoal-brown,
   not cool slate) to match the scene.
--------------------------------------------------------------------------- */
.lib-chalkboard { margin-top: 36px; }
.lib-chalkboard-frame {
  background: linear-gradient(160deg, #6b4425 0%, #4e3018 55%, #3c2412 100%);
  padding: 12px;
  border-radius: 2px;
  box-shadow: 0 16px 34px rgba(20, 12, 4, 0.4), inset 0 0 0 2px rgba(255, 255, 255, 0.07), inset 0 0 0 4px rgba(0, 0, 0, 0.2);
}
.lib-chalkboard-board {
  background: #26201b;
  padding: 26px 24px 30px;
  border-radius: 1px;
  box-shadow: inset 0 0 46px rgba(0, 0, 0, 0.55);
}

.lib-chalk-heading {
  font-family: var(--font-heading); font-weight: 700; letter-spacing: 0.015em;
  color: #f3ede0; font-size: 1.3125rem; margin: 0 0 6px;
}
.lib-chalk-intro { color: #cfc4ae; font-size: 0.875rem; line-height: 1.5; margin: 0 0 20px; }
.lib-wall-heading { margin-top: 30px; font-size: 1.125rem; }

.lib-reco-form { display: flex; flex-direction: column; gap: 4px; }
.lib-reco-label {
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: #a89a80; margin: 12px 0 0;
}
.lib-reco-label:first-child { margin-top: 0; }
.lib-reco-input, .lib-reco-textarea {
  width: 100%; background: transparent; border: 0; border-bottom: 1px solid rgba(243, 237, 224, 0.32);
  color: #f3ede0; border-radius: 0; font-family: var(--font-body); font-size: 1rem;
  padding: 8px 2px; margin: 4px 0 0; line-height: 1.5;
}
.lib-reco-textarea { resize: vertical; }
.lib-reco-input::placeholder, .lib-reco-textarea::placeholder { color: #9a8c72; }
.lib-reco-input:focus-visible, .lib-reco-textarea:focus-visible {
  outline: none; border-bottom-color: #f3ede0;
}
.lib-reco-form .lib-btn { margin-top: 18px; align-self: flex-start; }
.lib-chalk-btn { background: #8a5a2b; color: #f8f1e4; border-radius: 2px; }
.lib-chalk-btn:hover { background: #9c6b34; }
.lib-chalk-btn:focus-visible { outline: 2px solid #f3ede0; outline-offset: 2px; }
.lib-reco-status { margin: 10px 0 0; font-size: 0.875rem; color: #cfc4ae; min-height: 1.25em; }
/* Errors and success reuse already-verified chalk tones rather than
   introducing an unverified new color; the message text itself carries
   the meaning, color is never the only signal. */
.lib-reco-status[data-state="error"] { color: #f3ede0; font-weight: 600; }
.lib-reco-status[data-state="success"] { color: #e8cfa2; font-weight: 600; }

/* Honeypot: present in the DOM for bots, invisible and unreachable by tab
   or sight for real visitors. Off-screen rather than display:none, which
   some bots skip. */
.lib-reco-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* The wall keeps a FIXED footprint in the hero: notes stack into a pile
   (newest on top and readable, the rest peeking from beneath) instead of
   tiling, so the board never grows as recommendations arrive. The whole
   board opens in a shrinkable overlay via the Expand control below. */
.lib-wall-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px 16px; flex-wrap: wrap; margin-top: 30px;
}
.lib-wall-head .lib-wall-heading { margin-top: 0; }
.lib-wall-expand {
  flex: none; font-family: var(--font-mono); font-size: 0.6875rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: #f3ede0; background: rgba(243, 237, 224, 0.08);
  border: 1px solid rgba(243, 237, 224, 0.28); border-radius: 2px;
  padding: 7px 12px; min-height: 32px; cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease;
}
.lib-wall-expand:hover { background: rgba(243, 237, 224, 0.16); border-color: rgba(243, 237, 224, 0.5); }
.lib-wall-expand:focus-visible { outline: 2px solid #f3ede0; outline-offset: 2px; }
.lib-wall-count { margin: 14px 0 0; font-size: 0.8125rem; color: #cfc4ae; min-height: 1.2em; }

/* Shared sticky-note look (both the pile and the full board). */
.lib-reco-card {
  position: relative;
  width: 100%; max-width: 230px;
  background: var(--note-color, #f6d98a);
  color: #241c14;
  border-radius: 2px;
  padding: 22px 16px 16px;
  box-shadow: 0 10px 18px rgba(20, 12, 4, 0.35), 0 2px 4px rgba(20, 12, 4, 0.25);
  transition: transform .15s ease, box-shadow .15s ease, opacity .15s ease;
}
.lib-reco-card--a { --note-color: #f6d98a; }
.lib-reco-card--b { --note-color: #e8cfa2; }
.lib-reco-card--c { --note-color: #f4ecc0; }

/* Compact pile: notes stacked on one another, newest first. --stack-i is set
   per note in library.js (clamped) so the pile stays tidy at any count. */
.lib-reco-list {
  list-style: none; padding: 0; margin: 18px auto 0;
  position: relative; min-height: 252px; max-width: 230px;
}
.lib-reco-list .lib-reco-card {
  position: absolute; top: 0; left: 0; right: 0; margin: 0 auto;
  transform:
    translateX(calc(var(--stack-i, 0) * 4px))
    translateY(calc(var(--stack-i, 0) * 7px))
    rotate(var(--note-rot, 0deg));
  opacity: calc(1 - var(--stack-i, 0) * 0.13);
  z-index: calc(50 - var(--stack-i, 0));
  pointer-events: none;
}
/* In the pile a note is a bounded teaser: clamp long titles and notes so
   every card stays a predictable height and the deepest never spills onto the
   count line below. Scoped to the pile by id, NOT the shared .lib-reco-list
   class, so the Expand overlay (#lib-reco-full-list) still shows full text. */
#lib-reco-list .lib-reco-card-title,
#lib-reco-list .lib-reco-card-note {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* Only the top note in the pile is interactive; act on the rest in the full
   board (Expand). */
.lib-reco-list > .lib-reco-card:first-child { pointer-events: auto; }
.lib-reco-list > .lib-reco-empty { position: static; }

/* Full board (overlay): the familiar wrapping sticky-note grid, all notes. */
.lib-reco-list--full {
  position: static; max-width: none; min-height: 0; margin: 0;
  display: flex; flex-wrap: wrap; align-items: flex-start; gap: 26px 20px;
}
.lib-reco-list--full .lib-reco-card {
  position: relative; margin: 0; flex: 1 1 200px;
  transform: rotate(var(--note-rot, 0deg));
  opacity: 1; pointer-events: auto;
}
.lib-reco-list--full .lib-reco-card:hover,
.lib-reco-list--full .lib-reco-card:focus-within {
  transform: rotate(0deg) translateY(-3px);
  box-shadow: 0 14px 24px rgba(20, 12, 4, 0.4), 0 3px 6px rgba(20, 12, 4, 0.3);
  z-index: 2;
}

/* Pin: a small strip of washi tape across the top edge, purely decorative. */
.lib-reco-pin {
  position: absolute; top: -9px; left: 50%; width: 38px; height: 16px;
  transform: translateX(-50%) rotate(-2deg);
  background: rgba(255, 255, 255, 0.5);
  border: 1px solid rgba(36, 28, 20, 0.15);
  box-shadow: 0 2px 3px rgba(20, 12, 4, 0.3);
}

.lib-reco-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.lib-reco-card-title {
  font-family: var(--font-heading); font-weight: 700; font-size: 1.0625rem;
  margin: 0; overflow-wrap: break-word; color: #241c14;
}
.lib-reco-card.is-added .lib-reco-card-title,
.lib-reco-card.is-added .lib-reco-card-byline { text-decoration: line-through; color: #5c4a30; }
.lib-reco-card-byline { color: #5c4a30; font-size: 0.8125rem; margin: 2px 0 0; }
.lib-reco-card-note { font-size: 0.875rem; line-height: 1.5; margin: 10px 0 0; overflow-wrap: break-word; color: #33281b; }
.lib-reco-card-date { font-family: var(--font-mono); font-size: 0.625rem; color: #5c4a30; flex: none; white-space: nowrap; }
.lib-reco-tag {
  display: inline-block; margin-top: 10px; font-family: var(--font-mono); font-size: 0.625rem;
  letter-spacing: 0.08em; text-transform: uppercase; color: #f3ede0;
  background: #26201b; border-radius: 2px; padding: 3px 8px;
}
.lib-reco-mod { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.lib-reco-mod-btn {
  min-height: 32px; padding: 5px 10px; background: rgba(36, 28, 20, 0.08); color: #241c14;
  border: 1px solid rgba(36, 28, 20, 0.35); border-radius: 2px;
  font-family: var(--font-body); font-size: 0.6875rem; font-weight: 600; cursor: pointer;
  transition: background-color .15s ease;
}
.lib-reco-mod-btn:hover { background: rgba(36, 28, 20, 0.18); }
.lib-reco-mod-btn:focus-visible { outline: 2px solid #241c14; outline-offset: 2px; }
.lib-reco-empty { color: #cfc4ae; font-size: 0.875rem; }

/* ---------------------------------------------------------------------------
   Shrinkable full-board overlay: opens from the Expand control, shows every
   sticky note on a larger board, and shrinks back with Shrink / Escape /
   backdrop. Fixed and centered, so the hero footprint never changes.
--------------------------------------------------------------------------- */
.lib-board-overlay {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(18, 11, 4, 0.66);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.lib-board-overlay[hidden] { display: none; }
.lib-board-panel {
  width: 100%; max-width: 900px; max-height: 88vh;
  display: flex; flex-direction: column;
  background: linear-gradient(160deg, #6b4425 0%, #4e3018 55%, #3c2412 100%);
  padding: 14px; border-radius: 3px;
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.5), inset 0 0 0 2px rgba(255, 255, 255, 0.07), inset 0 0 0 4px rgba(0, 0, 0, 0.2);
}
.lib-board-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 8px 10px 14px;
}
.lib-board-title { font-family: var(--font-heading); font-weight: 700; color: #f3ede0; font-size: 1.3125rem; margin: 0; }
.lib-board-shrink {
  flex: none; font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: #f3ede0; background: rgba(243, 237, 224, 0.1);
  border: 1px solid rgba(243, 237, 224, 0.3); border-radius: 2px;
  padding: 8px 14px; min-height: 36px; cursor: pointer; white-space: nowrap;
  transition: background-color .15s ease;
}
.lib-board-shrink:hover { background: rgba(243, 237, 224, 0.2); }
.lib-board-shrink:focus-visible { outline: 2px solid #f3ede0; outline-offset: 2px; }
.lib-board-panel .lib-reco-list--full {
  overflow-y: auto; padding: 10px 12px 14px;
  background: #26201b; border-radius: 2px; box-shadow: inset 0 0 46px rgba(0, 0, 0, 0.55);
}

/* ---------------------------------------------------------------------------
   Hero steam: soft plumes rising from the coffee mug on the right of the
   photo. library.js positions this over the mug and only unhides it when the
   whole mug is within the covered/cropped photo (wide viewports), so steam
   never floats over empty space. Purely decorative, aria-hidden.
--------------------------------------------------------------------------- */
.lib-hero-steam {
  position: absolute; z-index: 1; pointer-events: none;
  width: 40px; height: 70px;
  /* left/top and --steam-scale are set inline by library.js. */
  transform: translate(-50%, -100%) scale(var(--steam-scale, 1));
  transform-origin: bottom center;
}
.lib-hero-steam[hidden] { display: none; }
.lib-steam-wisp {
  position: absolute; bottom: 0; left: 50%; width: 12px; height: 100%;
  margin-left: -6px; opacity: 0;
  background: linear-gradient(to top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.55) 45%, rgba(255, 255, 255, 0) 100%);
  filter: blur(5px);
  animation: lib-steam 4.2s ease-in-out infinite;
}
.lib-steam-wisp:nth-child(1) { left: 42%; animation-duration: 4.2s; animation-delay: 0s; }
.lib-steam-wisp:nth-child(2) { left: 55%; width: 11px; animation-duration: 5.1s; animation-delay: -1.4s; }
.lib-steam-wisp:nth-child(3) { left: 48%; width: 10px; animation-duration: 4.6s; animation-delay: -2.7s; }
@keyframes lib-steam {
  0%   { opacity: 0; transform: translateY(6px) translateX(0) scaleX(1) scaleY(0.7); }
  20%  { opacity: 0.5; }
  55%  { opacity: 0.34; transform: translateY(-34px) translateX(4px) scaleX(1.4) scaleY(1.1); }
  100% { opacity: 0; transform: translateY(-72px) translateX(-3px) scaleX(1.9) scaleY(1.35); }
}
/* Motion off: no rising steam, and hide it entirely rather than freeze a
   static smudge over the photo. */
@media (prefers-reduced-motion: reduce) {
  .lib-hero-steam { display: none; }
  .lib-steam-wisp { animation: none; opacity: 0; }
}

/* ---------------------------------------------------------------------------
   Coffee-mug doorway: the mug in the hero photo is a clickable entry to
   David's Corner. library.js positions it over the mug (same geometry as the
   steam) and shows it only when the whole mug is on-screen. A text fallback in
   the hero column covers narrow viewports where the mug is cropped away, so
   the corner is always reachable.
--------------------------------------------------------------------------- */
.lib-hero-mug {
  position: absolute; z-index: 2; display: block;
  border-radius: 8px; cursor: pointer;
  transition: box-shadow .18s ease, background-color .18s ease;
}
.lib-hero-mug[hidden] { display: none; }
.lib-hero-mug:hover, .lib-hero-mug:focus-visible {
  outline: none;
  background: rgba(243, 237, 224, 0.10);
  box-shadow: 0 0 0 2px rgba(243, 237, 224, 0.55), 0 6px 20px rgba(20, 12, 4, 0.4);
}
.lib-hero-mug-hint {
  position: absolute; left: 50%; bottom: calc(100% + 10px); transform: translateX(-50%);
  white-space: nowrap; opacity: 0; pointer-events: none;
  font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: #241c14; background: #f3ede0; padding: 5px 10px; border-radius: 4px;
  box-shadow: 0 6px 16px rgba(20, 12, 4, 0.4); transition: opacity .18s ease;
}
.lib-hero-mug:hover .lib-hero-mug-hint, .lib-hero-mug:focus-visible .lib-hero-mug-hint { opacity: 1; }

.lib-corner-fallback {
  display: inline-block; margin: 6px 0 0;
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.06em;
  color: #4a3826; text-decoration: none; border-bottom: 1px solid rgba(74, 56, 38, 0.45);
}
.lib-corner-fallback[hidden] { display: none; }
.lib-corner-fallback:hover { color: #241c14; border-bottom-color: #241c14; }

/* ---------------------------------------------------------------------------
   David's Corner index: shelves of David's own writing (reading-room themed).
--------------------------------------------------------------------------- */
.lib-corner-head { margin-bottom: 8px; }
.lib-corner-tagline { color: var(--muted); font-size: 1.0625rem; line-height: 1.5; margin: 8px 0 0; max-width: 44ch; }
.lib-corner-subtitle { color: var(--muted); font-size: 1rem; line-height: 1.5; margin: 8px 0 0; }
.lib-corner-shelf { margin-top: 40px; }
.lib-corner-shelf-title {
  font-family: var(--font-heading); font-weight: 800; color: var(--accent);
  font-size: 1.25rem; margin: 0 0 4px; padding-bottom: 8px; border-bottom: 1px solid var(--border);
}
.lib-corner-shelf-blurb { color: var(--muted); font-size: 0.9375rem; line-height: 1.5; margin: 8px 0 14px; }
.lib-corner-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 2px; }
.lib-corner-link {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  padding: 14px; text-decoration: none; color: inherit; border-radius: 4px;
  transition: background-color .15s ease;
}
.lib-corner-link:hover, .lib-corner-link:focus-visible { outline: none; background: var(--surface); }
.lib-corner-item-main { min-width: 0; }
.lib-corner-item-title { display: block; font-family: var(--font-heading); font-weight: 700; font-size: 1.0625rem; color: var(--text); overflow-wrap: break-word; }
.lib-corner-item-sub { display: block; color: var(--muted); font-size: 0.875rem; line-height: 1.4; margin-top: 2px; }
.lib-corner-item-meta { flex: none; font-family: var(--font-mono); font-size: 0.75rem; color: var(--muted); white-space: nowrap; }

/* ---------------------------------------------------------------------------
   Squircles (progressive enhancement, Chromium only; plain rounded rect
   elsewhere, no regression).
--------------------------------------------------------------------------- */
@supports (corner-shape: squircle) {
  .lib-item a, .lib-audio, .lib-noaudio, .lib-controls,
  .lib-audio-btn, .lib-btn, .lib-size-btn, .lib-theme-option, .lib-fb-option,
  .lib-search,
  .lib-card, .lib-card-play, .lib-card-read, .lib-card-pending-tag,
  .lib-sort-select, .lib-miniplayer-btn, .lib-miniplayer-close,
  .lib-modal, .lib-modal-close, .lib-section-heading,
  .lib-prompt, .lib-prompt-copy,
  .lib-wall-expand, .lib-board-shrink, .lib-board-panel,
  .lib-hero-mug, .lib-corner-link {
    corner-shape: squircle;
  }
}

/* ---------------------------------------------------------------------------
   Card hub: responsive manuscript-cover grid, inline play, sticky
   mini-player, and the read-preview modal. Reuses the tokens above; no new
   colors are introduced.
--------------------------------------------------------------------------- */
.lib-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  margin: 24px 0 8px;
}
.lib-toolbar .lib-search { margin: 0; flex: 1 1 240px; }
.lib-sort-control { display: flex; align-items: center; gap: 10px; flex: none; }
.lib-sort-select {
  min-height: 44px; padding: 10px 14px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-input);
  color: var(--text); font-family: var(--font-body); font-size: 0.9375rem;
  cursor: pointer;
}
.lib-sort-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.lib-intro { max-width: 68ch; margin: 20px 0 4px; padding: 16px 20px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card); }
.lib-intro p { margin: 0; color: var(--text); font-size: 0.95rem; line-height: 1.6; }

.lib-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px;
  padding: 0; margin: 24px 0 0; list-style: none;
}
@media (min-width: 640px) { .lib-grid { grid-template-columns: repeat(3, 1fr); gap: 20px; } }
@media (min-width: 1024px) { .lib-grid { grid-template-columns: repeat(4, 1fr); gap: 24px; } }

.lib-section-heading {
  grid-column: 1 / -1; font-family: var(--font-heading); font-weight: 700;
  font-size: 0.9375rem; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--muted); border-bottom: 1px solid var(--border);
  padding: 0 0 8px; margin: 28px 0 2px;
}
.lib-section-heading:first-child { margin-top: 4px; }

/* Manuscript cover: typographic front, no photography. */
.lib-card {
  display: flex; flex-direction: column; min-width: 0; border: 1px solid var(--border);
  border-radius: var(--radius-card); background: var(--surface);
  transition: border-color .15s ease;
}
.lib-card:hover, .lib-card:focus-within { border-color: var(--accent); }
.lib-card.is-playing { border-color: var(--accent); }

.lib-card-cover {
  display: flex; flex-direction: column; flex: 1; gap: 6px;
  padding: 20px 18px 14px; text-decoration: none; color: var(--text);
}
a.lib-card-cover:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-card-topline { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.lib-card-section {
  font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lib-card-num { font-family: var(--font-mono); font-size: 0.6875rem; color: var(--muted); flex: none; }
.lib-card-title {
  font-family: var(--font-heading); font-weight: 700; font-size: 1.0625rem;
  line-height: 1.3; margin: 6px 0 0; overflow-wrap: break-word;
}
.lib-card-byline { color: var(--muted); font-size: 0.8125rem; margin: 0; }

.lib-card-actions { display: flex; gap: 8px; padding: 0 18px 18px; }
.lib-card-play, .lib-card-read {
  flex: 1; min-height: 44px; display: flex; align-items: center; justify-content: center;
  background: var(--bg); color: var(--text); border: 1px solid var(--border);
  border-radius: var(--radius-btn); font-family: var(--font-body); font-size: 0.8125rem;
  font-weight: 600; cursor: pointer; transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.lib-card-play:hover, .lib-card-read:hover { border-color: var(--accent); color: var(--accent); }
.lib-card-play:focus-visible, .lib-card-read:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-card-play[data-playing="true"] {
  background: var(--accent); color: var(--accent-contrast); border-color: var(--accent);
}

/* Pending: quiet, muted, no controls. */
.lib-card-pending { opacity: 0.6; }
.lib-card-pending .lib-card-cover { cursor: default; }
.lib-card-pending-tag {
  align-self: flex-start; margin-top: 10px; font-family: var(--font-mono);
  font-size: 0.625rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted); border: 1px dashed var(--border); border-radius: var(--radius-btn);
  padding: 4px 10px;
}

/* Sticky mini-player: keeps playing while the reader scrolls the grid. */
.lib-miniplayer {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  background: var(--surface); border-top: 1px solid var(--border);
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.12);
}
.lib-miniplayer[hidden] { display: none; }
.lib-miniplayer-inner {
  max-width: 1100px; margin: 0 auto; padding: 12px 24px;
  display: flex; align-items: center; gap: 14px;
}
.lib-miniplayer-info { display: flex; flex-direction: column; min-width: 0; flex: 1 1 160px; max-width: 260px; }
.lib-miniplayer-label {
  font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent);
}
.lib-miniplayer-title {
  font-weight: 600; font-size: 0.875rem; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.lib-miniplayer-btn {
  flex: none; width: 44px; height: 44px; display: grid; place-items: center;
  background: var(--accent); color: var(--accent-contrast); border: 0;
  border-radius: var(--radius-btn); cursor: pointer;
}
.lib-miniplayer-btn:hover { background: color-mix(in srgb, var(--accent), var(--text) 20%); }
.lib-miniplayer-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-miniplayer-seek { flex: 1; }
.lib-miniplayer-time { flex: none; }
.lib-miniplayer-close {
  flex: none; width: 44px; height: 44px; display: grid; place-items: center;
  background: transparent; border: 1px solid var(--border); color: var(--muted);
  border-radius: var(--radius-btn); cursor: pointer; font-size: 1.25rem; line-height: 1;
}
.lib-miniplayer-close:hover { border-color: var(--accent); color: var(--accent); }
.lib-miniplayer-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
body.lib-has-miniplayer .lib-wrap { padding-bottom: 128px; }

/* Read-preview modal. */
html.lib-modal-open { overflow: hidden; }
.lib-modal-backdrop {
  position: fixed; inset: 0; background: rgba(0, 0, 0, 0.5);
  display: flex; align-items: center; justify-content: center; padding: 24px; z-index: 60;
}
.lib-modal-backdrop[hidden] { display: none; }
.lib-modal {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-card);
  width: 100%; max-width: 720px; max-height: 85vh; display: flex; flex-direction: column;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}
.lib-modal:focus-visible { outline: none; }
.lib-modal-header {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 20px 24px; border-bottom: 1px solid var(--border); flex: none;
}
.lib-modal-title { font-family: var(--font-heading); font-size: 1.25rem; margin: 0; }
.lib-modal-close {
  flex: none; width: 44px; height: 44px; display: grid; place-items: center;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-btn);
  color: var(--text); cursor: pointer; font-size: 1.375rem; line-height: 1;
}
.lib-modal-close:hover { border-color: var(--accent); color: var(--accent); }
.lib-modal-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lib-modal-body { padding: 20px 24px; overflow-y: auto; flex: 1; }
.lib-modal-loading { color: var(--muted); font-family: var(--font-mono); font-size: 0.875rem; }
.lib-modal-footer { padding: 14px 24px; border-top: 1px solid var(--border); flex: none; }
.lib-modal-footer a { font-family: var(--font-mono); font-size: 0.8125rem; text-decoration: none; }
.lib-modal-footer a:hover { text-decoration: underline; }
