/* chrome.css — the site's shared chrome: design tokens, the floating top bar
 * (brand mark, name, beta link, account button), the collapsed-on-scroll
 * state, the bottom action bar, and the sheets every page can open (site
 * menu, feedback, Add to Home Screen).
 *
 * Loaded by the app (/) as a stylesheet before v3.css, and inlined into every
 * server-rendered page by src/chrome.js — one source, so the header can never
 * drift between pages again. Page-specific chrome (the app's search box and
 * print/edit toggle, the content pages' section tabs) lives with its page.
 *
 * Design language: Material 3 Expressive tokens (shape scale, spring motion,
 * tonal colour) + Apple HIG chrome (translucent floating layers over an
 * opaque canvas, thumb-zone primary action). Notes: docs/v3-research.md.
 */

/* ------------------------------------------------------------------ Tokens -- */
:root {
  /* Tonal colour (HCT-flavoured ramp seeded from the brand rust #e76f51).
     Roles follow M3: primary=T40-ish, container=T90, on-container=T10. */
  --primary: #b3402a;            /* tone ~40 — the ONE filled control per view */
  --on-primary: #ffffff;
  --primary-container: #ffdbd2;  /* tone ~90 — colour-blocked containers */
  --on-primary-container: #3e0e02;
  --secondary-container: #f7e0c1; /* warm gold container */
  --on-secondary-container: #2a1c04;
  --tertiary: #226a5f;           /* teal — success, links */
  --tertiary-container: #cce8e0;
  --on-tertiary-container: #05201b;

  --surface: #fff8f4;            /* warm near-white canvas */
  --surface-dim: #f3e9e3;
  --on-surface: #231a16;
  --on-surface-var: #53433d;
  --outline: #85736c;
  --outline-var: #d8c2ba;

  --paper: #ffffff;              /* journal pages stay paper in both schemes */
  --paper-ink: #1c1917;
  --paper-line: #c9bfb8;
  --paper-accent: #b3402a;

  --scrim: rgba(35, 26, 22, .42);

  /* Chrome translucency (Apple: controls float; keep legible, test reduced
     transparency). Opaque-ish tints + blur, not glass for glass's sake. */
  --chrome-bg: rgba(255, 248, 244, .86);
  --chrome-border: rgba(133, 115, 108, .22);

  /* M3E shape scale */
  --shape-s: 8px;
  --shape-m: 12px;
  --shape-l: 16px;
  --shape-xl: 28px;
  --shape-xxl: 32px;
  --shape-full: 999px;

  /* M3E motion: spatial springs (overshoot) for position/size; effects (no
     bounce) for colour/opacity. linear() approximates damping .8 / stiffness 380. */
  --spring-spatial: linear(0, .012 1.1%, .05 2.4%, .193 5.1%, .794 13.3%, 1.045 18%, 1.085 20.5%, 1.081 24.4%, 1.003 36.2%, .987 42.7%, 1.001 62%, 1);
  --ease-effects: cubic-bezier(.2, 0, 0, 1);
  --dur-fast: 200ms;
  --dur-default: 480ms;

  --font-ui: "Google Sans Flex", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-paper: "Literata", Georgia, "Times New Roman", serif;

  /* Fixed-chrome clearances. Each page sets its own expanded value; chrome.js
     re-measures. They keep their EXPANDED values while the bars are collapsed,
     so collapsing never shifts the content under the reader's finger. */
  --top-h: 120px;
  --bottom-h: 0px;
  --maxw: 1060px;
  color-scheme: light; /* print-first product: always the warm paper theme */
}

/* ------------------------------------------------------------------- Base -- */
* { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  /* In-page anchors (skip link, #sections) land below the fixed bar. */
  scroll-padding-top: calc(var(--top-h) + 12px);
}
body {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 16px;
  line-height: 1.5;
  background: var(--surface);
  color: var(--on-surface);
}
button { font: inherit; cursor: pointer; }
.hidden, [hidden] { display: none !important; }
:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }

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

/* Keyboard users jump straight past the chrome. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 30;
  background: var(--primary); color: var(--on-primary);
  padding: 12px 18px; border-radius: 0 0 var(--shape-m) 0;
  font-weight: 700; text-decoration: none;
}
.skip:focus { left: 0; }

/* ------------------------------------------------------------- Top chrome -- */
.chrome { position: fixed; left: 0; right: 0; z-index: 20; }
.chrome-top {
  top: 0;
  background: var(--chrome-bg);
  border-bottom: 1px solid var(--chrome-border);
}
@supports (backdrop-filter: blur(1px)) {
  .chrome-top { backdrop-filter: blur(14px) saturate(1.4); }
}
/* Apple a11y: when the user asks for reduced transparency, go opaque. */
@media (prefers-reduced-transparency: reduce) {
  .chrome-top, .chrome-bottom { background: var(--surface); backdrop-filter: none; }
}
/* Increased contrast: solid chrome, stronger borders (HIG Increase Contrast). */
@media (prefers-contrast: more) {
  .chrome-top, .chrome-bottom { background: var(--surface); backdrop-filter: none; }
}

.chrome-top-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 8px 16px 12px;
  padding-top: calc(8px + env(safe-area-inset-top));
}
/* A real 40px row: the menu pill, tabs and Beta sit inside it, centred on
   the name, with the header's padding above and this margin below — never
   flush with the top of the screen or touching the row beneath. */
.topline {
  display: flex; align-items: center; gap: 10px;
  min-height: 40px;
  margin-bottom: 6px; /* also keeps the brand link's hit area off the row below */
}
/* Brand mark + name, one link. The mark is the favicon glyph on its own —
   a 24dp ink icon, like any other app-bar icon — not a coloured tile. */
.brand-home {
  display: inline-flex; align-items: center; gap: 12px;
  flex: 0 1 auto; min-width: 0;
  color: inherit; text-decoration: none;
  position: relative;
  /* No overflow:hidden here — it would clip the ::after hit area below. The
     name itself trims (see .brand). */
}
/* The name is a 24px-tall row; the extra hit area makes it a 44px target,
   inside the header's own padding above and the top line's margin below, so
   it never sits over the row beneath (the app's search label, the content
   pages' tabs). */
.brand-home::after { content: ""; position: absolute; inset: -10px -6px; }
/* If a wide font ever leaves too little room, the name trims; it never runs
   under the chip beside it. */
.brand-home .brand { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.brand-mark { width: 24px; height: 24px; flex: 0 0 auto; color: var(--on-surface); }
.brand {
  margin: 0; /* on the app it is the page's h1; elsewhere a plain span */
  font-weight: 700; font-size: 17px; letter-spacing: -.01em;
  font-variation-settings: "wght" 700;
  white-space: nowrap;
  line-height: 1.3;
}
.brand-tag { font-size: 12.5px; color: var(--on-surface-var); white-space: nowrap; }
/* Where you are, in the collapsed phone bar (the section tabs have gone by
   then), and the way back up: tapping it scrolls to the top and opens the
   full bar again, as the brand mark does on the app. A 48dp text button with
   an M3 state layer; no border or fill, so it reads as the bar's title.
   Empty on the app, which puts its print/edit toggle here instead. */
.chrome-title {
  display: none;
  position: relative;
  min-width: 0; min-height: 48px; padding: 0 10px;
  border: 0; border-radius: var(--shape-full); background: none;
  color: inherit; text-align: left;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font: inherit; font-size: 17px; font-weight: 600; letter-spacing: -.01em;
  cursor: pointer;
}
.chrome-title::before {
  content: ""; position: absolute; inset: 4px 0;
  border-radius: inherit;
  background: currentColor; opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-effects);
}
.chrome-title:hover::before { opacity: .08; }
.chrome-title:active::before { opacity: .12; }
/* Section tabs. The same five destinations on every page, in the same order,
   marked in ink, not brand red — red is reserved for the one primary action.
   Two placements (src/chrome.js renders both): in the header's second row on
   narrow screens (content pages only; the app's second row is its search
   box), and in the top line beside the brand on wide screens, on every page
   including the app, so the header is identical everywhere. */
.site-nav ul { display: flex; gap: 4px; list-style: none; margin: 0; padding: 0; }
.site-nav a {
  display: inline-flex; align-items: center;
  min-height: 44px; padding: 0 10px;
  white-space: nowrap;
  font-size: 14.5px; font-weight: 600;
  color: var(--on-surface-var); text-decoration: none;
  border-bottom: 2.5px solid transparent;
  border-radius: var(--shape-s) var(--shape-s) 0 0;
}
.site-nav a:hover { color: var(--on-surface); background: color-mix(in srgb, var(--on-surface) 6%, transparent); }
.site-nav a[aria-current=page] { color: var(--on-surface); border-bottom-color: var(--on-surface); }
/* Second row: scrolls sideways on a phone rather than hiding in a menu, so the
   structure of the site is always visible; fades at the edge to say so. */
.site-nav--row { margin: 0 -16px; }
.site-nav--row ul { padding: 0 16px; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.site-nav--row ul::-webkit-scrollbar { display: none; }
.site-nav--row { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 22px), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 22px), transparent); }
@media (min-width: 560px) { .site-nav--row { -webkit-mask-image: none; mask-image: none; } }
/* Phone, scrolled: the row folds away; the bar's title and the menu remain. */
@media (max-width: 719px) { body.is-collapsed .site-nav--row { display: none; } }
/* Top line: hidden until there is room for brand + tabs + actions on one line. */
.site-nav--top { display: none; }
@media (min-width: 960px) {
  /* 44px targets in the 40px top line: 2px of overhang, inside the header's
     padding. */
  .site-nav--top { display: block; flex: 0 0 auto; margin: -2px 0 -2px 14px; }
  /* Content pages: the second row has folded into the top line, so the line
     is the whole bar — no gap under it, and the pill sits mid-bar. */
  .topline:has(+ .site-nav--row:last-child) { margin-bottom: 0; }
  .site-nav--row { display: none; }
  .brand-tag { display: none; } /* the tabs take its place beside the name */
}
/* Six tabs, the name, the beta link and the account button share the top
   line from 960px: tighter tabs than the phone row, and below 1100px a plain
   "Beta", so the name is never truncated. */
@media (min-width: 960px) {
  .site-nav--top a { padding: 0 6px; font-size: 14px; }
  .site-nav--top { margin-left: 10px; }
}
@media (min-width: 960px) and (max-width: 1099px) {
  .beta-link-more { display: none; }
}

/* Beta: plain text, not a filled pill. It says the site is in beta and opens
   the feedback sheet, but it is not an action competing with the primary —
   only one filled, brand-coloured control belongs on the screen at a time. */
.beta-link {
  position: relative;
  margin-left: auto;
  flex: 0 0 auto;
  border: 0; background: none;
  color: var(--tertiary);
  font-size: 12.5px; font-weight: 600;
  padding: 4px 0;
  white-space: nowrap;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--tertiary) 35%, transparent);
  text-underline-offset: 3px;
  cursor: pointer;
}
.beta-link:hover { text-decoration-color: currentColor; }
/* Visually small, but a full 44px touch target — without growing the row.
   The extra area goes upward into the header's own padding: extending it
   downward instead would put an invisible band over the row below and steal
   taps meant for it. */
.beta-link::after { content: ""; position: absolute; inset: -10px -8px -8px -8px; }
/* M3 standard icon button: a 24dp icon in a 48dp target with no container;
   a 40dp state layer appears on hover/press. */
.icon-btn {
  position: relative;
  flex: 0 0 auto;
  width: 48px; height: 48px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--shape-full);
  background: none;
  color: var(--on-surface-var);
  padding: 0;
  cursor: pointer;
}
.icon-btn svg { width: 24px; height: 24px; position: relative; }
.icon-btn::before {
  content: ""; position: absolute; inset: 4px;
  border-radius: inherit;
  background: currentColor; opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-effects);
}
.icon-btn:hover::before { opacity: .08; }
.icon-btn:active::before { opacity: .12; }
/* Menu + account: one outlined pill (a tonal selection surface, never the
   brand red) holding the hamburger and the avatar, both opening the site
   menu. 40px to the eye, the height of the top line; ::after makes it a 44px
   target, reaching 2px into the header's padding above and the gap below. */
.account-btn {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 4px;
  height: 40px; padding: 0 5px 0 9px;
  border: 1px solid var(--outline-var);
  border-radius: var(--shape-full);
  background: var(--paper);
  color: var(--on-surface-var);
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(35,26,22,.06);
  transition: box-shadow var(--dur-fast) var(--ease-effects);
}
.account-btn::after { content: ""; position: absolute; inset: -3px -1px; border-radius: inherit; }
.account-btn:hover { box-shadow: 0 2px 6px rgba(35,26,22,.14); }
.account-btn:active { box-shadow: none; }
.account-btn svg { position: relative; flex: 0 0 auto; }
.account-btn svg:first-child { width: 18px; height: 18px; }          /* the hamburger */
.account-btn svg:last-child { width: 26px; height: 26px; color: var(--on-surface); } /* the avatar */
/* Just past the point where the tabs join the top line, the name, six tabs,
   "Beta" and the pill are 30px over; the beta note and feedback link stay in
   the menu and the footer. */
@media (min-width: 960px) and (max-width: 999px) {
  .beta-link { display: none; }
}

@media (max-width: 480px) {
  .brand { font-size: 16px; }
  .brand-tag { display: none; } /* keep the top line to one calm row */
  /* With the mark and menu pill on the line, "Beta" alone fits; the
     feedback link lives in the account menu and the footer too. */
  .beta-link-more { display: none; }
}
@media (max-width: 400px) {
  /* Below this the name, "Beta" and the pill cannot all fit; the beta note
     and feedback link stay reachable in the menu and the footer. */
  .beta-link { display: none; }
  /* Beta was what pushed the pill to the edge; now the pill does it. */
  .account-btn { margin-left: auto; }
}
@media (max-width: 340px) {
  /* The narrowest phones: a hair off the name and the pill so the name
     still reads in full. */
  .brand { font-size: 15px; }
  .brand-home { gap: 8px; }
  .account-btn { gap: 3px; padding: 0 4px 0 8px; }
  .account-btn svg:last-child { width: 24px; height: 24px; }
}
/* Desktop: the header is roomier. */
@media (min-width: 720px) {
  .chrome-top-inner { padding-top: 12px; }
  .topline { margin-bottom: 10px; }
}

/* ------------------------------------------------------- Collapsed chrome -- */
/* Scrolled away from the top (chrome.js toggles body.is-collapsed), the bars
   shrink to give the content the screen. --top-h / --bottom-h keep their
   EXPANDED values throughout, so collapsing never shifts the content. */
.chrome-top-inner, .chrome-bottom-inner, .bar-caption, .topline, .dl-main {
  transition: all var(--dur-fast) var(--ease-effects);
  transition-property: padding, margin, height, min-height, width, flex-basis, opacity, font-size;
}
body.is-collapsed .chrome-top-inner { padding-top: calc(6px + env(safe-area-inset-top)); padding-bottom: 6px; }
/* Phone, collapsed: the whole bar becomes an M3 small top app bar — 64dp
   tall, 4dp edge padding, leading icon (the brand mark), a title slot, then
   the trailing actions as plain 48dp icon buttons. The brand name, tag and
   beta link drop out. Each page's second row decides for itself whether it
   folds into this row (the app's search icon) or hides (section tabs). */
@media (max-width: 719px) {
  body.is-collapsed .chrome-top-inner {
    display: flex; align-items: center; gap: 0;
    padding: calc(8px + env(safe-area-inset-top)) 4px 8px;
  }
  body.is-collapsed .topline { display: contents; }
  body.is-collapsed .brand,
  body.is-collapsed .brand-tag,
  body.is-collapsed .beta-link { display: none; }
  body.is-collapsed .brand-home {
    order: -1;
    width: 48px; height: 48px; justify-content: center;
    border-radius: var(--shape-full);
  }
  body.is-collapsed .brand-home::after { inset: 0; }
  body.is-collapsed .chrome-title { display: block; order: 2; flex: 1 1 auto; margin-left: 0; }
  /* The pill keeps its 16px from the edge in the 4px-padded collapsed bar. */
  body.is-collapsed .account-btn { order: 4; margin: 0 12px 0 0; }
}
@media (min-width: 720px) {
  body.is-collapsed .topline { margin-bottom: 6px; }
}

/* ------------------------------------------------------------ Bottom chrome -- */
/* The one dominant action, in the thumb zone. */
.chrome-bottom {
  bottom: 0;
  background: var(--chrome-bg);
  border-top: 1px solid var(--chrome-border);
  transition: transform var(--dur-fast) var(--ease-effects);
}
@supports (backdrop-filter: blur(1px)) {
  .chrome-bottom { backdrop-filter: blur(14px) saturate(1.4); }
}
.chrome-bottom-inner {
  max-width: 640px;
  margin: 0 auto;
  display: flex; gap: 8px;
  padding: 9px 16px;
  /* max(), not +: on a device with a home indicator the inset alone is already
     ample clearance, and adding to it left a dead strip under the button. */
  padding-bottom: max(9px, env(safe-area-inset-bottom));
}
/* The one dominant action (M3E: single large filled button per view). */
.dl-main {
  flex: 1 1 auto;
  min-height: 56px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px;
  border: 0;
  border-radius: var(--shape-full);
  background: var(--primary);
  color: var(--on-primary);
  text-decoration: none;
  box-shadow: 0 4px 16px color-mix(in srgb, var(--primary) 42%, transparent);
  transition: border-radius var(--dur-default) var(--spring-spatial),
              transform var(--dur-default) var(--spring-spatial);
}
.dl-main:active { border-radius: var(--shape-l); transform: scale(.98); } /* press morph */
.dl-main[disabled] { opacity: .6; cursor: progress; }
.dl-main-label { font-size: 16.5px; font-weight: 700; letter-spacing: .01em; }
/* A one-line caption above the button row — ellipsized so it never grows
   the bar. */
.bar-caption {
  max-width: 640px;
  margin: 0 auto;
  padding: 6px 16px 0;
  font-size: 13px; font-weight: 600;
  color: var(--on-surface-var);
  text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Share: a 56dp outlined icon button beside the primary. */
.dl-more {
  flex: 0 0 auto;
  width: 56px; min-height: 56px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--outline-var);
  border-radius: var(--shape-full);
  background: var(--paper);
  color: var(--on-surface);
  padding: 0;
  transition: transform var(--dur-default) var(--spring-spatial),
              border-radius var(--dur-default) var(--spring-spatial);
}
.dl-more svg { display: block; }
/* The caption row: what is about to print (empty on the app, whose heading
   already names the book) and the
   format, which is a text button that opens the format sheet. Visually one
   line of small text; the button's padding makes it a 44px target that
   overhangs the caption's own padding, so the bar keeps its height: down to
   the top of the Print button, and the rest up past the bar's top edge. The
   row must not clip (overflow: visible) or the overhang takes no taps; its
   children ellipsize themselves. */
.bar-caption { display: flex; align-items: center; justify-content: center; gap: 6px; white-space: nowrap; overflow: visible; }
.bar-caption-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.bar-caption-text:empty { display: none; }
.bar-caption-text:not(:empty)::after { content: "·"; margin-left: 6px; color: var(--outline); }
.bar-format {
  flex: 0 0 auto;
  border: 0; background: none; padding: 16px 4px 8px; margin: -16px 0 -8px;
  font: inherit; font-size: 13px; font-weight: 700;
  color: var(--tertiary);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, var(--tertiary) 35%, transparent);
  cursor: pointer;
}
.bar-format:hover { text-decoration-color: currentColor; }
/* Bottom bar, collapsed: the caption text goes but the format stays one tap
   away; the buttons tighten (still ≥44px). */
body.is-collapsed .bar-caption-text { display: none; }
body.is-collapsed .bar-caption { padding-top: 4px; }
body.is-collapsed .bar-format { padding-top: 19px; margin-top: -19px; } /* still 44px */
body.is-collapsed .chrome-bottom-inner { padding-top: 5px; }
body.is-collapsed .dl-main { min-height: 48px; }
body.is-collapsed .dl-main-label { font-size: 15.5px; }
body.is-collapsed .dl-more { width: 48px; min-height: 48px; }

/* Print-format sheet: three radio rows, 64dp each, the current one tonal. */
.format-list { display: flex; flex-direction: column; gap: 6px; margin: 6px -6px 0; }
.format-opt {
  display: flex; align-items: flex-start; gap: 14px;
  width: 100%; min-height: 64px; padding: 12px 14px;
  border: 1.5px solid var(--outline-var); border-radius: var(--shape-l);
  background: var(--paper); color: var(--on-surface);
  font: inherit; text-align: left; cursor: pointer;
  transition: background var(--dur-fast) var(--ease-effects), border-color var(--dur-fast) var(--ease-effects);
}
.format-opt-check {
  flex: 0 0 auto; width: 22px; height: 22px; margin-top: 1px;
  border: 2px solid var(--outline); border-radius: var(--shape-full);
  position: relative;
}
.format-opt[aria-checked=true] { background: var(--secondary-container); border-color: transparent; color: var(--on-secondary-container); }
.format-opt[aria-checked=true] .format-opt-check { border-color: var(--on-secondary-container); }
.format-opt[aria-checked=true] .format-opt-check::after {
  content: ""; position: absolute; inset: 4px; border-radius: inherit; background: var(--on-secondary-container);
}
.format-opt-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.format-opt-text strong { font-size: 16px; font-weight: 700; }
.format-opt-text span { font-size: 13.5px; line-height: 1.45; color: var(--on-surface-var); }
.format-opt[aria-checked=true] .format-opt-text span { color: inherit; }

/* "Digital journals" demand check (src/interest.js): two yes/no questions in
   the post-print cards and under a book's questions, and a short sheet.
   Yes/No are selection chips (tonal when picked); nothing here is brand red. */
.ao-line { display: block; margin: 14px 0 0; padding-top: 6px; border-top: 1px solid color-mix(in srgb, currentColor 18%, transparent); font-size: 14.5px; line-height: 1.4; }
.ao-q { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px; padding: 6px 0; }
.ao-q + .ao-q { border-top: 1px solid color-mix(in srgb, currentColor 10%, transparent); }
.ao-q-text { flex: 1 1 170px; font-weight: 700; }
.ao-q-acts { display: flex; gap: 6px; }
.ao-yn {
  min-height: 44px; min-width: 60px; padding: 0 14px;
  border: 1.5px solid color-mix(in srgb, currentColor 35%, transparent); border-radius: var(--shape-full);
  background: none; color: inherit; font: inherit; font-weight: 700; cursor: pointer;
}
.ao-yn[aria-pressed=true] { background: var(--secondary-container); color: var(--on-secondary-container); border-color: transparent; }
/* Under a book's questions: shown only with JS (the head script marks <html>),
   and hidden before first paint on a device that already answered. */
.ao-line--page { display: none; margin: 16px 0 0; padding-top: 8px; border-top: 1px solid var(--outline-var); color: var(--on-surface); }
html[data-ao-js] .ao-line--page { display: block; }
html[data-ao=done] .ao-line--page { display: none; }
html[data-ao-js] .ao-line--landing { display: block; } /* the landing page always asks */
.ao-line--sheet { margin-top: 8px; border-top: 0; padding-top: 0; font-size: 16px; }
.menu-tag { margin-left: auto; font-size: 11.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--on-surface-var); }
/* The sheet's option rows copy .format-opt under their own class: chrome.js
   wires every .format-opt to the print format and rewrites its aria-checked. */
.ao-list { display: flex; flex-direction: column; gap: 6px; margin: 6px -6px 0; }
.ao-opt {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  width: 100%; min-height: 56px; padding: 10px 14px;
  border: 1.5px solid var(--outline-var); border-radius: var(--shape-l);
  background: var(--paper); color: var(--on-surface);
  font: inherit; font-size: 16px; font-weight: 600; text-align: left; cursor: pointer;
}
.ao-opt-check { flex: 0 0 auto; width: 22px; height: 22px; border: 2px solid var(--outline); border-radius: var(--shape-full); position: relative; }
.ao-opt[aria-checked=true] { background: var(--secondary-container); border-color: transparent; color: var(--on-secondary-container); }
.ao-opt[aria-checked=true] .ao-opt-check { border-color: var(--on-secondary-container); }
.ao-opt[aria-checked=true] .ao-opt-check::after { content: ""; position: absolute; inset: 4px; border-radius: inherit; background: var(--on-secondary-container); }
.ao-thanks { margin: 4px 0 0; text-align: center; font-size: 16px; font-weight: 700; }
.ao-email-row { display: flex; gap: 8px; }
.ao-email-row input {
  flex: 1 1 auto; min-width: 0;
  border: 1.5px solid var(--outline-var); border-radius: var(--shape-m);
  background: var(--paper); color: var(--on-surface);
  padding: 10px 12px; font: inherit; font-size: 16px; /* ≥16px: iOS never zoom-jumps */
}
.ao-email-row input:focus-visible { outline: none; border-color: var(--primary); box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 22%, transparent); }
.ao-email-row button {
  flex: 0 0 auto; border: 0; border-radius: var(--shape-full);
  background: var(--primary-container); color: var(--on-primary-container);
  font: inherit; font-weight: 700; font-size: 14px; padding: 0 16px; min-height: 44px;
}
.ao-email-row button[disabled] { opacity: .6; }

/* After Print: a quiet inline card (never a modal — the PDF tab has the
   reader's attention, and this waits for them to come back). */
.print-tips {
  margin: 0 0 18px;
  padding: 16px 44px 16px 18px;
  position: relative;
  background: var(--tertiary-container); color: var(--on-tertiary-container);
  border-radius: var(--shape-l);
  font-size: 15px; line-height: 1.5;
}
.print-tips h2, .print-tips .sheet-title { margin: 0 0 6px; font-size: 16.5px; font-weight: 800; letter-spacing: -.01em; }
.print-tips ol { margin: 0; padding-left: 20px; }
.print-tips li { margin: 2px 0; }
.print-tips strong, .print-tips em { color: inherit; }
.print-tips-x {
  position: absolute; top: 8px; right: 8px;
  width: 40px; height: 40px;
  border: 0; border-radius: var(--shape-full); background: none;
  color: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
}
.print-tips-x:hover { background: color-mix(in srgb, currentColor 10%, transparent); }

/* A small confirmation ("Link copied") for pages without the app's toast. */
.mini-toast {
  position: fixed; left: 50%; bottom: calc(var(--bottom-h) + env(safe-area-inset-bottom) + 12px);
  transform: translateX(-50%);
  z-index: 30;
  padding: 10px 16px; border-radius: var(--shape-full);
  background: var(--on-surface); color: var(--surface);
  font-size: 14px; font-weight: 600; white-space: nowrap;
  box-shadow: 0 8px 24px rgba(35,26,22,.28);
  animation: fade-in var(--dur-fast) var(--ease-effects);
}

/* ------------------------------------------------------------------ Sheets -- */
.sheet-scrim {
  position: fixed; inset: 0; z-index: 40;
  background: var(--scrim);
  animation: fade-in var(--dur-fast) var(--ease-effects);
}
@keyframes fade-in { from { opacity: 0; } }
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 41;
  max-width: 560px; margin: 0 auto;
  background: var(--surface);
  border-radius: var(--shape-xxl) var(--shape-xxl) 0 0;
  padding: 10px 22px calc(18px + env(safe-area-inset-bottom));
  box-shadow: 0 -12px 48px rgba(0,0,0,.28);
  animation: sheet-up var(--dur-default) var(--spring-spatial);
  max-height: 86vh; overflow-y: auto;
}
@keyframes sheet-up { from { transform: translateY(60%); opacity: .4; } to { transform: none; opacity: 1; } }
.sheet-handle {
  width: 40px; height: 4px;
  border-radius: var(--shape-full);
  background: var(--outline-var);
  margin: 4px auto 14px;
}
/* Wider screens: a bottom sheet is a phone pattern, so from 600px (the same
   breakpoint as /books' Filter & sort) every sheet is a dialog centred in
   the window, rounded all round, with no drag handle. */
@media (min-width: 600px) {
  .sheet {
    top: 50%; bottom: auto;
    width: calc(100% - 32px);
    border-radius: var(--shape-xxl);
    padding: 22px 22px 18px;
    box-shadow: 0 12px 48px rgba(0,0,0,.28);
    transform: translateY(-50%);
    animation-name: sheet-pop;
  }
  .sheet-handle { display: none; }
}
@keyframes sheet-pop { from { transform: translateY(-50%) scale(.96); opacity: 0; } to { transform: translateY(-50%); opacity: 1; } }
/* Visible close in the corner — sheets must never rely on the scrim alone. */
.sheet-x {
  position: absolute; top: 10px; right: 12px;
  width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--shape-full);
  background: var(--surface-dim);
  color: var(--on-surface-var);
  font-size: 16px; font-weight: 700;
  padding: 0;
}
.sheet-x:hover { color: var(--on-surface); }
.sheet h2, .sheet .sheet-title {
  margin: 0 0 12px; text-align: center;
  /* Clear the corner close button, so a longer title can't run under it. */
  padding: 0 44px;
  font-size: 22px; font-weight: 800; letter-spacing: -.01em;
}
.sheet h2:focus, .sheet .sheet-title:focus { outline: none; } /* takes initial focus on open */
.done-sub {
  margin: 0 auto 12px; max-width: 400px; text-align: center;
  font-size: 14.5px; color: var(--on-surface-var); line-height: 1.5;
}
.sheet-close {
  display: block;
  margin: 16px auto 0;
  min-height: 44px;
  border: 0; border-radius: var(--shape-full);
  background: none;
  color: var(--tertiary);
  font-weight: 700; font-size: 15px;
  padding: 0 18px;
}
/* A sheet's one filled button (M3E: single large filled button per view). */
.btn-share-primary {
  display: block;
  width: min(100%, 340px);
  margin: 18px auto 0;
  min-height: 52px;
  border: 0; border-radius: var(--shape-full);
  background: var(--primary); color: var(--on-primary);
  font-weight: 700; font-size: 16px;
  box-shadow: 0 4px 16px color-mix(in srgb, var(--primary) 40%, transparent);
  transition: border-radius var(--dur-default) var(--spring-spatial), transform var(--dur-default) var(--spring-spatial);
}
.btn-share-primary:active { border-radius: var(--shape-l); transform: scale(.98); }
.btn-share-primary[disabled] { opacity: .6; cursor: progress; }
.done-check {
  width: 52px; height: 52px;
  margin: 2px auto 10px;
  border-radius: var(--shape-full);
  background: var(--tertiary);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 26px; font-weight: 800;
  animation: pop-in var(--dur-default) var(--spring-spatial);
}
@keyframes pop-in { from { transform: scale(.6); opacity: 0; } }

/* Site menu (the account sheet). M3 list items: 56dp, 16dp inset, 24dp icon. */
.menu-list { display: flex; flex-direction: column; margin: 8px -6px 0; }
.menu-item {
  display: flex; align-items: center; gap: 16px;
  width: 100%; min-height: 56px; padding: 8px 16px;
  border: 0; border-radius: var(--shape-full);
  background: none; text-align: left;
  font: inherit; font-size: 16px; font-weight: 400; line-height: 1.5;
  color: var(--on-surface); text-decoration: none;
  transition: background var(--dur-fast) var(--ease-effects);
}
.menu-ico { width: 24px; height: 24px; flex: 0 0 auto; color: var(--on-surface-var); }
.menu-item:hover { background: color-mix(in srgb, var(--on-surface) 8%, transparent); }
.menu-item[aria-current=page] { background: var(--secondary-container); color: var(--on-secondary-container); font-weight: 600; }
.menu-item[aria-current=page] .menu-ico { color: inherit; }

/* Feedback sheet form */
.fb-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.fb-label { display: block; font-size: 14px; font-weight: 700; margin: 14px 0 6px; }
.fb-optional { font-weight: 500; color: var(--on-surface-var); }
#fb-sheet textarea, #fb-sheet input[type=email] {
  width: 100%;
  border: 1.5px solid var(--outline-var); border-radius: var(--shape-m);
  background: var(--paper); color: var(--on-surface);
  padding: 11px 13px;
  font: inherit; font-size: 16px; /* ≥16px so iOS never zoom-jumps */
}
#fb-sheet textarea:focus-visible, #fb-sheet input:focus-visible {
  outline: none; border-color: var(--primary);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 22%, transparent);
}
.fb-sheet-status { margin: 12px 0 0; text-align: center; font-size: 14.5px; font-weight: 600; min-height: 20px; }
.fb-sheet-status.is-error { color: #8c2f1c; }
.fb-sheet-status.is-ok { color: var(--tertiary); }

/* Install sheet */
.install-steps { margin: 4px auto 0; max-width: 400px; padding-left: 24px; font-size: 15px; line-height: 1.65; color: var(--on-surface-var); }
.install-steps li { margin-bottom: 8px; }
.install-steps strong { color: var(--on-surface); }
.install-ico { display: inline-flex; vertical-align: -4px; color: var(--tertiary); }
