/* BetweenBooks — the welcome page at /welcome. Standalone: the app's own chrome (rail,
   shelf, book page) is not wanted here, so this does not load styles.css.

   The token block below is therefore a COPY of the one in styles.css, which is the source
   of truth — change a colour there and change it here too. The alternative was lifting the
   tokens into a third file both stylesheets import, which would have meant editing the
   running app's stylesheet; that is a bigger change than this page is worth on its own, but
   it is the right fix the moment a second page needs them.

   Two themes, same mechanism as the app: `data-theme` on <html>, resolved before first
   paint by the inline script in welcome.html, sharing the app's localStorage key so a
   visitor who has already chosen a side keeps it. */

/* --------------------------------------------------------------------- tokens */

/* ------------------------------------------------------------------------- fonts

   Self-hosted, and that is a privacy decision before it is a performance one: a
   `<link>` to fonts.googleapis.com hands every visitor's IP address to Google before the
   page has painted, with no consent asked and no way to decline — which is what the
   Regional Court of Munich awarded damages over in January 2022. The faces are OFL, so
   serving them from betweenbooks.net is both permitted and simpler.

   Two subsets per face. `latin` is what nearly every visit needs; `latin-ext` carries the
   accented letters an author's name may need (Márquez, Kundera, Ibsen's ø) and is fetched
   only by a page that actually uses one — that is what `unicode-range` is for.

   `font-display: swap` keeps the fallback stack visible while a face loads, so the page is
   readable from first paint, exactly as it is when the fonts never arrive at all. */

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-sans-400-latin.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: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-sans-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-sans-400-italic-latin.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: 'IBM Plex Sans';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-sans-400-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-sans-500-latin.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: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-sans-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-sans-600-latin.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: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-sans-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-mono-400-latin.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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-mono-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-mono-500-latin.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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-mono-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-mono-600-latin.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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/static/fonts/ibm-plex-mono-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'EB Garamond';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/eb-garamond-400-italic-latin.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: 'EB Garamond';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/eb-garamond-400-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'EB Garamond';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/static/fonts/eb-garamond-500-latin.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: 'EB Garamond';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/static/fonts/eb-garamond-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'EB Garamond';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/static/fonts/eb-garamond-600-latin.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: 'EB Garamond';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/static/fonts/eb-garamond-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  color-scheme: light;

  --bg: #f2eff8;
  --surface: #fbf9fe;
  --surface-2: #f6f3fc;
  --sidebar: #ece7f6;
  --border: #e0d9ef;
  --border-strong: #c9c0e0;
  --text: #2b2440;
  --muted: #6b6288;
  --accent: #6a4fb8;
  --accent-hover: color-mix(in srgb, var(--accent) 86%, #000);
  --accent-soft: color-mix(in srgb, var(--accent) 11%, var(--surface));
  --accent-line: color-mix(in srgb, var(--accent) 34%, var(--surface));
  --on-accent: #ffffff;
  --star: #c08a1e;
  --star-empty: #ded5ee;
  --ring: var(--accent);

  --shadow: 0 1px 2px rgba(42, 30, 70, .05), 0 2px 8px rgba(42, 30, 70, .06);
  --shadow-lift: 0 2px 6px rgba(42, 30, 70, .08), 0 12px 28px rgba(42, 30, 70, .12);

  --reading-bg: #fbe7d6; --reading-fg: #8a5426;
  --read-bg: #dcefe4;    --read-fg: #2c6349;
  --want-bg: #e3e4f3;    --want-fg: #565a7d;
  --dnf-bg: #f8dfe8;     --dnf-fg: #8a3556;

  --aurora-1: #6a4fb8; --aurora-2: #c58fb8; --aurora-3: #7f9fd6; --aurora-op: .42;

  --r-sm: 4px;
  --r: 6px;
  --r-full: 999px;

  /* Mirrors the type block in styles.css, which stays the source of truth — the landing
     page and the app are one typographic system, so this is a copy and never a variant.
     Two faces: Plex Sans for anything read as language, Plex Mono for anything read as a
     mark. See styles.css for why the display serif is gone. */
  --font-ui: "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
             "Helvetica Neue", Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               monospace;
  /* Mirrors --font-display in styles.css. Marketing headlines only — see .display below. */
  --font-display: "EB Garamond", Georgia, "Times New Roman", serif;

  --fs-3xs: .72rem;
  --fs-2xs: .78rem;
  --fs-xs:  .82rem;
  --fs-sm:  .88rem;
  --fs-md:  .95rem;
  --fs-lg:  1.06rem;
  --fs-xl:  1.3rem;
  --fs-2xl: 1.75rem;
  --fs-3xl: 2.3rem;
  --fs-hero: 3.2rem;
  --fs-pill: .7rem;

  --w-normal: 400;
  --w-medium: 500;
  --w-semi: 600;

  --ease-spring: cubic-bezier(.22, 1.08, .36, 1);
  --ease-out: cubic-bezier(.22, .61, .36, 1);
  --t-fast: 120ms;
  --t: 190ms;
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #14101f;
  --surface: #1d1730;
  --surface-2: #262040;
  --sidebar: #100d19;
  --border: #2f2749;
  --border-strong: #423868;
  --text: #ebe5f8;
  --muted: #a99cc6;
  --accent: #b49bf2;
  --accent-hover: color-mix(in srgb, var(--accent) 82%, #fff);
  --accent-soft: color-mix(in srgb, var(--accent) 16%, var(--surface));
  --accent-line: color-mix(in srgb, var(--accent) 38%, var(--surface));
  --on-accent: #17102b;
  --star: #e8b84f;
  --star-empty: #372f52;

  --shadow: 0 1px 2px rgba(0, 0, 0, .55), 0 2px 10px rgba(0, 0, 0, .45);
  --shadow-lift: 0 4px 12px rgba(0, 0, 0, .55), 0 18px 40px rgba(0, 0, 0, .55);

  --reading-bg: #3a2a18; --reading-fg: #edbe83;
  --read-bg: #1d3327;    --read-fg: #92d5ae;
  --want-bg: #232042;    --want-fg: #b0abd0;
  --dnf-bg: #35202c;     --dnf-fg: #eba3bf;

  --aurora-1: #b49bf2; --aurora-2: #5b3fa8; --aurora-3: #4f5fa8; --aurora-op: .38;
}

/* ----------------------------------------------------------------------- base */

* { box-sizing: border-box; }
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--fs-md)/1.58 var(--font-ui);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); text-decoration: underline; }

:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; border-radius: var(--r-sm); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
    /* A stagger is mostly delay, and a delay outlives a zeroed duration. Mirrored from
       styles.css so the two sheets cancel motion the same way. */
    animation-delay: 0ms !important;
    transition-delay: 0ms !important;
  }
}

/* The theme flip, same as the app's: the palette is one attribute on <html>, so there is
   nothing to interpolate and a view transition animates the two snapshots instead. The new
   frame fades in over a static old one rather than cross-fading, which keeps the page
   opaque the whole way across. `*` cannot match these pseudo-elements, hence the second
   reduced-motion block. */
::view-transition-old(root),
::view-transition-new(root) { mix-blend-mode: normal; }
::view-transition-old(root) { animation: none; z-index: 0; }
::view-transition-new(root) { animation: theme-fade 360ms var(--ease-out); z-index: 1; }
@keyframes theme-fade { from { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none !important; }
}

/* Marketing headlines, and the ONE place a second face is spent. The rule inside the app
   still holds — a book title in a grid cell is data, not literature, and gets the sans —
   but a hero headline is not a field of a form, it is the sentence that has to carry the
   product in 50 milliseconds. EB Garamond is a real book face, so the vintage half of the
   identity arrives in the type rather than in decoration.

   Tracking is far softer than the sans needed: an oldstyle serif at 51px is already fitted
   for display, and the -.032em that kept Plex from falling apart would close Garamond up.
   Georgia is the fallback because it is the nearest-metric serif a machine is likely to
   have — the page must still be right when the webfonts never arrive. */
.display {
  font-family: var(--font-display);
  font-weight: var(--w-medium);
  letter-spacing: -.012em;
  line-height: 1.06;
  margin: 0 0 1.1rem;
}
/* The accent inside a headline: italic and the accent colour, on the one word the sentence
   turns on. Garamond has a true cursive italic, which is the reason this reads as emphasis
   rather than as a slanted roman. */
.display em { font-style: italic; color: var(--accent); }

.wrap { max-width: 1180px; margin: 0 auto; padding: 0 2rem; }
.sect { padding: 5.5rem 0; }
.band { border-top: 1px solid var(--border); }
.band.tinted { background: var(--surface-2); }
.band.rail { background: var(--sidebar); }

.lede { color: var(--muted); font-size: var(--fs-lg); line-height: 1.6; max-width: 54ch; margin: 0 0 1.2rem; }
.lede:last-child { margin-bottom: 0; }
.centered { text-align: center; }
.centered .lede { margin-left: auto; margin-right: auto; }

.two-col {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 4rem;
  align-items: center;
}

/* ------------------------------------------------------------------- controls */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  font: inherit; font-weight: var(--w-medium); padding: .68rem 1.15rem;
  border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  background: var(--surface); color: var(--text); cursor: pointer;
  transition: background var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-spring);
}
.btn:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
.btn:active { transform: translateY(1px) scale(.98); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent);
               box-shadow: var(--shadow); }
.btn.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover);
                     color: var(--on-accent); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--muted); }
.btn.ghost:hover { background: var(--surface-2); border-color: var(--border); color: var(--accent); }
.btn.block { width: 100%; }

.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r);
}

.pill {
  font-size: var(--fs-3xs); font-weight: var(--w-semi); letter-spacing: .02em;
  padding: .1rem .4rem; border-radius: var(--r-full); white-space: nowrap;
}
.pill.want { background: var(--want-bg); color: var(--want-fg); }
.pill.reading { background: var(--reading-bg); color: var(--reading-fg); }
.pill.read { background: var(--read-bg); color: var(--read-fg); }
.pill.dnf { background: var(--dnf-bg); color: var(--dnf-fg); }

/* A segmented switch, the same shape the app uses for its status filter. */
.seg-group {
  display: inline-flex; gap: .2rem; padding: .25rem;
  border-radius: var(--r-full); background: var(--surface-2); border: 1px solid var(--border);
}
.seg {
  font: inherit; font-size: var(--fs-sm); font-weight: var(--w-medium); border: 0; cursor: pointer;
  border-radius: var(--r-full); padding: .42rem 1rem;
  background: transparent; color: var(--muted);
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.seg[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }

/* ------------------------------------------------------------------------ nav */

.topbar { border-bottom: 1px solid var(--border); background: var(--sidebar); }
.topbar .wrap { display: flex; align-items: center; gap: 2rem; padding-top: .9rem; padding-bottom: .9rem; }
.brand { display: flex; align-items: center; gap: .6rem; color: var(--text); }
.brand:hover { text-decoration: none; }
.brand svg { width: 30px; height: 30px; }
.brand-name {
  font-family: var(--font-display);
  font-weight: var(--w-semi);
  letter-spacing: .005em;
  font-size: var(--fs-xl);
}
.nav-links { display: flex; align-items: center; gap: 1.6rem; margin-left: auto; }
.nav-links a { color: var(--muted); font-weight: var(--w-medium); font-size: var(--fs-md); }
.nav-links a.btn { color: var(--on-accent); }

/* ---------------------------------------------------------------------- hero */

.hero { position: relative; overflow: hidden; }
.hero .wrap { position: relative; padding-top: 5.5rem; padding-bottom: 5rem; }

/* The sign-in screen's aurora, held still. A landing page has enough going on without
   ambient drift, and stillness is also the answer for reduced motion. */
.aurora { position: absolute; inset: 0; pointer-events: none; opacity: var(--aurora-op); }
.aurora span { position: absolute; border-radius: 50%; filter: blur(80px); }
.aurora .b1 { top: -22rem; left: -14rem; width: 46rem; height: 46rem; background: var(--aurora-1); }
.aurora .b2 { top: -12rem; right: -16rem; width: 40rem; height: 40rem; background: var(--aurora-2); }
.aurora .b3 { bottom: -26rem; left: 34%; width: 38rem; height: 38rem; background: var(--aurora-3); }

.hero h1 { font-size: var(--fs-hero); margin-bottom: 1.4rem; }

/* Section headings, sized here rather than inline on each <h2>. Both sit on the same step
   now: they were 2.35 and 2.6rem, a difference no reader can see between two headings that
   never share a screen, and the kind of near-miss the ramp exists to stop. */
.display.h-sect,
.display.h-close { font-size: var(--fs-3xl); }
.hero .lede { margin-bottom: 2rem; }
.cta-row { display: flex; flex-wrap: wrap; gap: .7rem; align-items: center; }
.credit { color: var(--muted); font-size: var(--fs-sm); margin: 1.1rem 0 0; }
.credit strong { color: var(--text); font-weight: var(--w-semi); }

/* --------------------------------------------------------------- shelf mockup */

.mock { padding: 1.1rem; box-shadow: var(--shadow-lift); }
.mock-body { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 1.1rem; align-items: start; }

.rail-label {
  margin: 0 0 .45rem .3rem; font-size: var(--fs-3xs); font-weight: var(--w-semi);
  letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
}
/* The container holds the two shelves an account cannot lose; the ones you made list
   below it, unboxed — the same split the app's own rail makes. */
.rail-box {
  display: flex; flex-direction: column; gap: .15rem; padding: .3rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); box-shadow: var(--shadow);
}
.rail-list { display: flex; flex-direction: column; gap: .15rem; margin-top: .35rem; }
.shelf-btn {
  display: flex; align-items: center; gap: .6rem; width: 100%;
  font: inherit; font-size: var(--fs-md); font-weight: var(--w-medium); text-align: left;
  border: 0; border-radius: var(--r-sm); padding: .5rem .6rem; cursor: pointer;
  background: transparent; color: var(--muted);
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.shelf-btn:hover { background: var(--accent-soft); color: var(--text); }
.shelf-btn[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }
.shelf-btn svg { flex: none; width: 17px; height: 17px; fill: none; stroke: currentColor;
                 stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; opacity: .85; }
.shelf-btn .nm { flex: 1; min-width: 0; }
.shelf-btn .ct {
  flex: none; font-size: var(--fs-2xs); font-weight: var(--w-semi); padding: .05rem .4rem;
  border-radius: var(--r-full); background: var(--accent-soft); color: var(--muted);
}
.shelf-btn[aria-pressed="true"] .ct { background: rgba(255, 255, 255, .22); color: inherit; }

.shelf-name { margin: 0 0 .1rem; font-size: var(--fs-lg); font-weight: var(--w-semi); letter-spacing: -.02em; }
.shelf-sub { margin: 0 0 .8rem; color: var(--muted); font-size: var(--fs-xs); }
.grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .6rem; }

.tile {
  background: transparent; border: 0; display: flex; flex-direction: column;
  transition: transform var(--t) var(--ease-out);
}
.tile:hover { transform: translateY(-2px); }
/* Local cover images keep the sample shelf available without a remote request. */
.tile .cover {
  position: relative; overflow: hidden; aspect-ratio: 2 / 3; display: grid; place-items: center; padding: .5rem;
  text-align: center; font-size: var(--fs-3xs); line-height: 1.3; color: var(--muted);
  background: linear-gradient(150deg, var(--accent-soft), var(--surface-2));
  border-radius: var(--r-sm); box-shadow: var(--shadow);
  transition: box-shadow var(--t) var(--ease-out);
}
.tile:hover .cover { box-shadow: var(--shadow-lift); }
.tile .body { padding: .45rem 0 0; display: flex; flex-direction: column; gap: .2rem; flex: 1; }
/* Height-locked for the same reason the app's tile caption is: an unclamped caption wraps
   to a different line count per title and again on the font swap, which reflows the mock
   shelf. See the note on .book .title in styles.css. The reserved height is derived from
   the token rather than restating it, so the two cannot drift apart. */
.tile .t {
  font-weight: var(--w-semi); font-size: var(--fs-xs);
  line-height: 1.22; letter-spacing: -.01em;
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden;
  min-height: calc(var(--fs-xs) * 1.22 * 2);
}
.tile .a { color: var(--muted); font-size: var(--fs-3xs); }
.tile .meta { display: flex; justify-content: space-between; align-items: center;
              gap: .25rem; margin-top: auto; padding-top: .3rem; }
.bar { height: 4px; background: var(--accent-soft); border-radius: var(--r-full);
       overflow: hidden; margin-top: .15rem; }
.bar i { display: block; height: 100%; background: var(--accent); border-radius: inherit; }
.bar.big { height: 10px; margin: 0 0 1.2rem; }

/* -------------------------------------------------------------- rating widget */

.panel-title {
  margin: 0 0 1.2rem; font-size: var(--fs-xs); font-weight: var(--w-semi);
  letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
}
.aspects { display: flex; flex-direction: column; gap: 1.05rem; }
.aspect { display: flex; align-items: center; gap: 1rem; }
.aspect .label { flex: none; width: 6.5rem; font-size: var(--fs-sm); font-weight: var(--w-medium); color: var(--muted); }
.aspect .val { margin-left: auto; font-size: var(--fs-sm); font-weight: var(--w-semi); color: var(--text); }

.stars { display: flex; gap: .25rem; }
/* Each slot is an empty star with a clipped filled star over it, so a half needs no SVG
   gradient — and therefore no ids to collide when the row is repeated four times. */
.star { position: relative; width: 28px; height: 28px; }
.star svg { position: absolute; inset: 0; width: 28px; height: 28px; }
.star .fill { position: absolute; inset: 0; overflow: hidden; width: 0; }
.star .fill svg { position: static; display: block; }
.star .hit { position: absolute; inset: 0; display: flex; }
.star .hit button {
  flex: 1; border: 0; background: none; padding: 0; margin: 0; cursor: pointer; height: 100%;
}

.avg-row {
  margin-top: 1.4rem; padding-top: 1.1rem; border-top: 1px solid var(--border);
  display: flex; align-items: baseline; gap: .6rem;
}
.avg-row .n { margin-left: auto; font-size: var(--fs-2xl); font-weight: var(--w-semi);
              letter-spacing: -.03em; line-height: 1; }

/* ------------------------------------------------------------------- progress */

.progress-read { display: flex; align-items: baseline; gap: .6rem; margin-bottom: .55rem; }
.progress-read strong { font-size: var(--fs-3xl); font-weight: var(--w-semi); letter-spacing: -.03em; line-height: 1; }
.stepper { display: flex; align-items: center; gap: .5rem; }
.stepper .box {
  display: grid; place-items: center; width: 2.1rem; height: 2.1rem;
  border: 1px solid var(--border-strong); border-radius: var(--r-sm); color: var(--muted);
}
.stepper .page {
  flex: 1; border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  padding: .48rem .65rem; font-weight: var(--w-medium);
}
.pill-row { display: flex; gap: .4rem; margin-top: 1.2rem; flex-wrap: wrap; }
.pill-row .pill { font-size: var(--fs-2xs); padding: .22rem .6rem; }

/* ---------------------------------------------------------------------- stats */

.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .9rem; margin-top: 2.6rem; }
.stat { padding: .9rem 1rem; text-align: left; }
.stat .n { font-size: var(--fs-2xl); font-weight: var(--w-semi); letter-spacing: -.03em; line-height: 1.1; }
.stat .l { color: var(--muted); font-size: var(--fs-xs); font-weight: var(--w-medium); }

/* -------------------------------------------------------------------- pricing */

.tiers { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.2rem;
         max-width: 780px; margin: 0 auto; }
.tier { padding: 1.8rem; position: relative; }
.tier.featured { border-color: var(--accent-line); box-shadow: var(--shadow-lift); }
.tier h3 { margin: 0 0 .3rem; font-weight: var(--w-semi); font-size: var(--fs-lg); }
.tier .who { margin: 0 0 1.2rem; color: var(--muted); font-size: var(--fs-sm); }
.price { display: flex; align-items: baseline; flex-wrap: wrap; gap: .35rem; margin-bottom: 1.4rem; }
/* No `white-space: nowrap` here, deliberately. The widest amount this can hold is the
   krone's "49,17 kr" — a trailing symbol after a space — and at 320px with reading size at
   150% that string can be wider than a tier card, which would push the document sideways
   rather than clip. The only break opportunity inside it is the space before the unit, so
   letting it wrap costs a currency that fits nothing and saves the one that does not. The
   krone is the fallback currency, so this is what an unlisted country sees.

   The Australian dollar's "A$7.42" carries the first two-character symbol prefix in the
   table (checked 2026-09-12, five-currency table), but is shorter than the krone figure by
   character count and by estimated glyph width at every width in the reflow sweep, so it
   has not needed this break. Unlike the krone it has no space to break at — "A$" sits
   flush against the digits — so if a future price ever makes AUD the widest amount,
   `overflow-wrap: break-word` will split it mid-number rather than at the clean boundary
   the krone gets. Re-check this comment's widest-currency claim whenever a price or
   currency changes; it was not re-verified by rendering, only estimated from character and
   glyph-width sums. */
.price .amt { font-size: var(--fs-3xl); font-weight: var(--w-semi); letter-spacing: -.03em; line-height: 1;
             min-width: 0; overflow-wrap: break-word; }
.price .per { color: var(--muted); font-size: var(--fs-md); }
.tier .badge {
  position: absolute; top: -.7rem; left: 1.8rem;
  background: var(--accent); color: var(--on-accent); font-size: var(--fs-3xs); padding: .25rem .6rem;
  /* This is the one pill carrying a sentence rather than a word. `.pill` sets
     `white-space: nowrap`, which is right for "Currently reading" and wrong here: measured in
     Chromium at 320px with Reading controls at 150%, this badge alone pushed the document to
     368px against a 320px viewport — a 1.4.10 Reflow failure, present in every currency and
     unrelated to the prices. Cap it to the card and let it wrap. The 3.6rem is the 1.8rem
     offset above plus an equal gutter on the right. */
  white-space: normal; max-width: calc(100% - 3.6rem);
}
.rule { height: 1px; background: var(--border); margin: 1.4rem 0; }
.ticks { display: flex; flex-direction: column; gap: .7rem; }
.ticks li { display: flex; gap: .6rem; align-items: flex-start; font-size: var(--fs-md); color: var(--muted); }
.ticks svg { flex: none; width: 17px; height: 17px; margin-top: .15rem; fill: none;
             stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ticks { list-style: none; margin: 0; padding: 0; }
.fineprint { text-align: center; color: var(--muted); font-size: var(--fs-xs); margin: 1.6rem 0 0; }

/* ------------------------------------------------------------------------ faq */

.faq { max-width: 760px; margin: 0 auto; }
.faq-item { border-bottom: 1px solid var(--border); }
.faq-q {
  font: inherit; font-size: var(--fs-lg); font-weight: var(--w-semi); letter-spacing: -.01em;
  width: 100%; text-align: left; border: 0; background: none; cursor: pointer;
  color: var(--text); padding: 1.15rem 0;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}
.faq-q svg {
  flex: none; width: 20px; height: 20px; fill: none; stroke: var(--muted);
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
  transition: transform var(--t) var(--ease-out);
}
.faq-q[aria-expanded="true"] svg { transform: rotate(180deg); }
.faq-a { margin: -.3rem 0 1.3rem; color: var(--muted); line-height: 1.65; max-width: 62ch; }

/* --------------------------------------------------------------------- footer */

.foot .wrap { display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;
              padding-top: 2.6rem; padding-bottom: 1rem; }
.foot-links { display: flex; gap: 1.4rem; margin-left: auto; flex-wrap: wrap; }
.foot-links a { color: var(--muted); font-size: var(--fs-sm); }
.foot .small { color: var(--muted); font-size: var(--fs-xs); padding-bottom: 2.6rem; margin: 0; }
.foot .brand svg { width: 24px; height: 24px; }

/* ---------------------------------------------------------------- narrow */

@media (max-width: 900px) {
  .wrap { padding: 0 1.25rem; }
  .sect { padding: 3rem 0; }
  .two-col { grid-template-columns: 1fr; gap: 2rem; }
  .hero .wrap { padding-top: 2.6rem; padding-bottom: 3rem; }
  .hero h1 { font-size: var(--fs-3xl); }
  .display { font-size: var(--fs-2xl); }
  .nav-links { gap: 1rem; }
  /* The links go to the footer at this width; the one action stays. */
  .nav-links a:not(.btn) { display: none; }
  .mock-body { grid-template-columns: 1fr; }
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tiers { grid-template-columns: 1fr; }
  .cta-row { flex-direction: column; align-items: stretch; }
  .cta-row .btn { width: 100%; }
  /* Every tappable thing clears 44px on a touch layout. */
  .btn { min-height: 46px; }
  .shelf-btn { min-height: 44px; }
  .faq-q { min-height: 52px; }
  .aspect .label { width: auto; flex: 1; }
  .star, .star svg { width: 24px; height: 24px; }
}

/* A compact, browsable shelf gives the books room without crowding the introduction. */
.hero .aurora { opacity: .12; }
.hero .two-col { grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: clamp(2rem, 4vw, 4rem); }
.hero h1 { font-size: clamp(2.8rem, 4.2vw, 4.4rem); line-height: 1.05; letter-spacing: -.035em; }
.hero .lede { max-width: 38ch; }
.mock { padding: 1.25rem; background: var(--surface); }
.mock-heading { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0 0 1rem; margin-bottom: 1.2rem; border-bottom: 1px solid var(--border); font-size: var(--fs-sm); font-weight: 500; }
.mock-caption { color: var(--muted); font-size: var(--fs-3xs); font-weight: 400; }
.mock-body { grid-template-columns: 125px minmax(0, 1fr); }
.tile .cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.tile .cover span { padding: .4rem; }
@media (max-width: 1000px) {
  .hero .two-col { grid-template-columns: 1fr; }
  .hero .lede { max-width: 48ch; }
  .mock { max-width: 640px; width: 100%; margin-inline: auto; }
}
@media (max-width: 900px) {
  .wrap.sect { padding: 3rem 1.25rem; }
  .hero .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .hero .mock-body { grid-template-columns: 125px minmax(0, 1fr); }
}
@media (max-width: 540px) {
  .hero h1 { font-size: 2.8rem; }
  .topbar .wrap { gap: .5rem; }
  .brand { gap: .3rem; }
  .brand-name { font-size: 1.15rem; }
  .nav-links { gap: 0; }
  .nav-links .btn { font-size: var(--fs-xs) !important; padding-inline: .65rem !important; }
  .hero .mock-body { grid-template-columns: 1fr; }
  .mock-body > div:first-child { display: flex; flex-wrap: wrap; gap: .4rem; }
  .mock .rail-label { display: none; }
  .mock .rail-box, .mock .rail-list { display: contents; }
  .mock .shelf-btn { width: auto; font-size: var(--fs-xs); padding: .4rem .55rem; }
  .mock .shelf-btn svg, .mock .shelf-btn .ct { display: none; }
  .mock { padding: .9rem; }
  .mock .grid { gap: .55rem; }
}
@media (max-width: 540px) {
  .two-col { grid-template-columns: minmax(0, 1fr); }
  #features .card { padding: 1rem !important; }
  .aspect { gap: .5rem; }
  .stars { gap: .1rem; }
  .aspect .label { font-size: var(--fs-xs); }
}

/* --------------------------------------------------------------------- prose

   The privacy page, and anything else that is a document rather than a pitch. The landing
   page is built from panels; a policy is built from paragraphs, and it needs a measure
   narrow enough to read down: 68ch on the body, which is about twelve words a line. */

.prose { max-width: 68ch; margin-inline: auto; }
.prose h1 { font-size: clamp(2.2rem, 4vw, 3.1rem); }
.prose h2 {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--w-medium);
  letter-spacing: -.01em;
  margin: 2.8rem 0 .9rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--border);
}
.prose p, .prose li { line-height: 1.7; }
.prose ul { padding-left: 1.1rem; margin: 0 0 1.1rem; }
.prose li { margin-bottom: .55rem; }
.prose li::marker { color: var(--accent); }
.prose code {
  font-family: var(--font-mono);
  font-size: .88em;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: .08em .34em;
}
.prose .fineprint { margin-top: 2.4rem; }

/* A table of what is stored is the one place a table beats prose: three columns, and the
   reader is scanning for their own row rather than reading it through. It scrolls inside
   its own box on a phone instead of widening the page. */
/* The one block that breaks the measure. A three-column table is scanned, not read down,
   so it is allowed the width of the page rather than the width of a paragraph — centred on
   the prose column it interrupts, and scrolling inside itself on a narrow screen. */
.table-scroll {
  overflow-x: auto;
  width: min(62rem, calc(100vw - 3rem));
  position: relative;
  left: 50%;
  transform: translateX(-50%);
  margin: 0 auto 1.6rem;
}
.prose table { border-collapse: collapse; width: 100%; min-width: 34rem; font-size: var(--fs-sm); }
.prose th, .prose td { text-align: left; vertical-align: top; padding: .7rem .8rem; border-bottom: 1px solid var(--border); }
.prose thead th { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: .08em; color: var(--muted); font-weight: var(--w-semi); }
.prose tbody td:first-child { font-weight: var(--w-medium); white-space: nowrap; }
@media (max-width: 700px) {
  .prose tbody td:first-child { white-space: normal; }
}

/* The tax line sits with the prices rather than in the small print at the foot: what a
   subscription costs including tax is part of the price, not a disclaimer about it. */
.tax-note { text-align: center; margin: .9rem 0 0; }

/* Landing composition. Scoped so the shared privacy document keeps its layout. */
.landing .wrap { max-width: 1240px; }
.landing .topbar { background: var(--bg); }
.landing .topbar .wrap { min-height: 88px; }
.landing .brand-name { font-family: var(--font-ui); font-size: 1.25rem; font-weight: 600; letter-spacing: -.055em; }
.landing .btn { border-radius: 100px; min-height: 46px; padding: .8rem 1.35rem; }
.landing .btn.primary { box-shadow: none; }
.landing .hero { overflow: clip; }
.landing .hero .wrap { padding-top: 76px; padding-bottom: 84px; }
.landing .hero .two-col { grid-template-columns: .95fr 1.05fr; gap: 64px; }
.landing .hero h1 { font-size: clamp(4rem, 6.8vw, 6rem); line-height: .98; letter-spacing: -.045em; margin-bottom: 28px; }
.landing .hero .lede { font-size: 1.1rem; max-width: 37ch; }
.landing .hero .aurora { opacity: .09; }
.landing .cta-row { gap: 10px; }
.landing .hero .cta-row { margin-top: 28px; }
.landing .hero .cta-row .btn { font-size: .92rem !important; }
.landing .credit { margin-top: 18px; font-size: var(--fs-xs); }
.shelf-stage { position: relative; padding: 32px 0 40px; }
.shelf-stage::before { content: ''; position: absolute; inset: -30px -26px 0; background: var(--accent-soft); border-radius: 50% 50% 32% 45%; transform: rotate(-8deg); z-index: -1; }
.stage-note { margin: 0 0 16px 18px; color: var(--muted); font-size: var(--fs-xs); display: flex; align-items: center; gap: 9px; }
.status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--read-fg); }
.landing .mock { border-radius: 18px; padding: 23px; box-shadow: 0 24px 65px -28px color-mix(in srgb, var(--text) 30%, transparent); transform: rotate(-2deg); }
.landing .mock-heading { font-size: .9rem; }
.landing .mock-body { grid-template-columns: 105px minmax(0,1fr); gap: 18px; min-height: 258px; }
.landing .mock .shelf-btn { font-size: var(--fs-2xs); padding: .55rem .4rem; gap: .3rem; }
.landing .mock .ct { display: none; }
.landing .mock .shelf-btn svg { width: 14px; }
.landing .mock .tile .a { font-size: var(--fs-3xs); }
.landing .mock .tile .t { font-size: var(--fs-2xs); }
.landing .mock .grid { gap: 12px; }
.reading-note { position: relative; display: flex; align-items: center; gap: 13px; margin: -2px -14px 0 100px; padding: 16px 20px; border: 1px solid var(--border); background: var(--surface); border-radius: 14px; box-shadow: var(--shadow-lift); transform: rotate(3deg); }
.reading-note strong, .reading-note div>span { display: block; }
.reading-note strong { font-size: .88rem; }
.reading-note div>span { font-size: var(--fs-2xs); color: var(--muted); }
.note-icon { font-size: 1.4rem; color: var(--read-fg); background: var(--read-bg); border-radius: 12px; padding: 4px 12px; }
.note-star { color: var(--accent); margin-left: auto; font-size: 1.8rem; }
.promise-strip { display: flex; justify-content: space-between; gap: 18px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding-block: 23px; color: var(--muted); font-size: .85rem; }
.promise-strip span::before { content: '✦'; margin-right: 12px; color: var(--accent); }
.landing .sect { padding: 88px 32px; }
.section-intro { display: grid; grid-template-columns: 1fr 1fr; column-gap: 90px; align-items: end; margin-bottom: 38px; }
.landing .h-sect { font-size: clamp(2.6rem, 4vw, 3.7rem); letter-spacing: -.03em; }
.section-intro .lede { max-width: 35ch; margin-bottom: 8px; font-size: 1rem; }
.feature-grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: 22px; }
.feature-card { padding: 34px; border-radius: 22px; border: 1px solid var(--border); background: var(--surface); overflow: hidden; }
.feature-card h3 { font-family: var(--font-display); font-size: 2.1rem; line-height: 1.1; font-weight: 500; letter-spacing: -.02em; margin: 0 0 14px; }
.feature-card p { color: var(--muted); font-size: .92rem; max-width: 44ch; margin: 0; }
.rating-card { background: color-mix(in srgb, var(--accent-soft) 50%, var(--surface)); }
.rating-demo { margin-top: 26px; padding: 23px; background: var(--surface-2); border-radius: 14px; }
.rating-demo .panel-title { display: none; }
.rating-demo .aspect { gap: .7rem; }
.rating-demo .aspect .label { width: 5rem; }
.rating-demo .star, .rating-demo .star svg { width: 30px; height: 30px; }
.rating-demo .star { height: 44px; }
.rating-demo .star>svg, .rating-demo .star .fill { top: 7px; }
.rating-demo .star .fill { bottom: 7px; }
.progress-demo { margin-top: 24px; padding: 22px; background: var(--surface-2); border-radius: 14px; }
.progress-book { display: flex; gap: 16px; align-items: center; margin: 18px 0; }
.progress-book img { border-radius: 4px; object-fit: cover; box-shadow: var(--shadow); }
.progress-book strong, .progress-book div>span { display: block; }
.progress-book strong { font-size: .95rem; }
.progress-book div>span { font-size: var(--fs-xs); color: var(--muted); }
.progress-demo label { font-size: var(--fs-xs); color: var(--muted); }
.progress-demo input { width: 100%; margin: 4px 0 12px; height: 30px; accent-color: var(--accent); cursor: pointer; }
.progress-demo .progress-read { justify-content: space-between; }
.progress-demo .progress-read strong { font-size: 1.9rem; }
.progress-demo .progress-read>span { color: var(--muted); font-size: var(--fs-xs); }
.progress-demo .demo-caption { margin-top: 14px; font-size: var(--fs-3xs); }
.shelves-card { min-height: 305px; }
.shelf-chips { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 30px; }
.shelf-chips span { border: 1px solid var(--accent-line); border-radius: 10px; padding: 12px 15px; background: var(--accent-soft); font-size: .8rem; }
.theme-card { position: relative; background: var(--sidebar); }
.theme-card p { max-width: 29ch; }
.theme-card .seg-group { margin-top: 25px; position: relative; z-index: 1; }
.theme-art { position: absolute; right: -18px; bottom: -20px; display: flex; align-items: end; gap: 7px; transform: rotate(-15deg); opacity: .3; pointer-events: none; }
.theme-art i { display: block; width: 28px; height: 120px; background: var(--accent); border: 1px solid var(--accent-line); border-radius: 5px; }
.theme-art i:nth-child(2n) { height: 150px; background: var(--aurora-2); }
.theme-art i:nth-child(3) { height: 100px; background: var(--aurora-3); }
.landing .tiers { max-width: 900px; gap: 24px; }
.landing .tier { border-radius: 20px; padding: 32px; }
.landing .tier.featured { box-shadow: none; }
.landing .tier:first-child { border-color: var(--accent-line); }
.landing .price { min-height: 65px; }
.landing #pricing .fineprint { max-width: 85ch; margin-inline: auto; }
.landing .faq { max-width: 800px; }
.landing .faq-q { font-size: 1rem; padding-block: 24px; }
.landing .faq-a { font-size: .9rem; }
.landing .h-close { font-size: clamp(3rem,5vw,4.8rem); line-height: 1.03; }
.skip-link { position: fixed; top: -100px; left: 16px; z-index: 100; padding: 12px; background: var(--surface); }
.skip-link:focus { top: 12px; }
.landing [id] { scroll-margin-top: 24px; }
@keyframes card-arrive { from { opacity: 0; translate: 0 18px; } to { opacity: 1; translate: 0 0; } }
@media (prefers-reduced-motion: no-preference) {
  .landing .mock { animation: card-arrive 800ms var(--ease-out) both; }
  .reading-note { animation: card-arrive 800ms 160ms var(--ease-out) both; }
  .landing .grid:not([hidden]) .tile { animation: card-arrive 420ms var(--ease-out) both; }
  .landing .grid .tile:nth-child(2) { animation-delay: 60ms; }
  .landing .grid .tile:nth-child(3) { animation-delay: 120ms; }
  .feature-card.entered { animation: card-arrive 650ms var(--ease-out) both; }
  .feature-card { transition: border-color 200ms, box-shadow 200ms; }
  .feature-card:hover { border-color: var(--accent-line); box-shadow: 0 12px 36px -24px var(--accent); }
}
@media (max-width: 1000px) {
  .landing .hero .two-col { gap: 38px; grid-template-columns: 1fr 1fr; }
  .landing .hero h1 { font-size: 4.4rem; }
  .landing .mock-body { grid-template-columns: 1fr; }
  .landing .mock-body>div:first-child { display: flex; flex-wrap: wrap; gap: 4px; }
  .landing .mock .rail-box, .landing .mock .rail-list { display: contents; }
  .landing .mock .rail-label { display: none; }
  .landing .mock .shelf-btn { width: auto; min-height: 44px; }
  .landing .mock .shelf-btn svg { display: none; }
  .landing .mock-caption { display: none; }
  .feature-card { padding: 25px; }
  .rating-demo { padding: 16px; }
  .rating-demo .aspect .label { width: auto; flex: 1; }
  .rating-demo .stars { gap: 1px; }
  .rating-demo .star, .rating-demo .star svg { width: 26px; }
}
@media (max-width: 760px) {
  .landing .topbar .wrap { min-height: 76px; }
  .landing .hero .two-col { grid-template-columns: minmax(0,1fr); gap: 24px; }
  .landing .hero .wrap { padding-top: 42px; padding-bottom: 34px; }
  .landing .hero h1 { font-size: clamp(3.8rem, 12vw, 5.5rem); }
  .landing .hero .lede { max-width: 42ch; }
  .landing .hero .cta-row { flex-direction: row; flex-wrap: wrap; }
  .landing .hero .cta-row .btn { width: auto; }
  .shelf-stage { max-width: 530px; width: 100%; margin-inline: auto; padding-top: 20px; }
  .shelf-stage::before { inset: 0; }
  .landing .mock { padding: 20px; }
  .landing .mock-caption { display: inline; }
  .reading-note { margin-left: 40px; margin-right: 0; }
  .promise-strip { flex-wrap: wrap; justify-content: center; font-size: var(--fs-2xs); padding-block: 20px; }
  .landing .sect { padding: 58px 20px; }
  .section-intro { grid-template-columns: 1fr; gap: 0; }
  .section-intro .lede { max-width: 44ch; }
  .feature-grid { grid-template-columns: minmax(0,1fr); gap: 16px; }
  .feature-card { padding: 26px; }
  .rating-demo .aspect .label { flex: 1; }
  .landing .tiers { grid-template-columns: minmax(0,1fr); }
  .landing .tier { padding: 26px; }
  .landing .foot .wrap { gap: 24px; }
  .landing .foot-links { margin-left: 0; }
}
/* The badge straddles the card's top edge by being absolutely positioned, which means the card
   reserves no room for it. Measured in Chromium: it wraps to two lines at every width, which is
   fine, but at 440px and below with Reading controls turned up it reaches three and the last
   line lands on the "Pro" heading — 14px of overlap at 125%, 21px at 150%. CSS cannot ask how
   many lines something took, so below this width the badge simply joins the flow and pushes the
   heading down instead of covering it. */
@media (max-width: 440px) {
  .tier .badge { position: static; display: inline-block; margin: 0 0 .6rem; max-width: 100%; }
}

@media (max-width: 380px) {
  .landing .mock-caption { display: none; }
  .landing .brand-name { font-size: 1.08rem; }
  .feature-card { padding: 20px; }
  .rating-demo { padding: 12px; }
  .rating-demo .star, .rating-demo .star svg { width: 23px; }
}
