/* Glimpt — light only. Warm paper, ink, one green accent.
   Borders are uniform 1px hairlines; nothing gets a thick edge on one side. */

/* Simonetta, self-hosted. Latin and latin-ext, 400 + 400 italic + 900 — the
   extended subset matters because book titles and author names arrive from the
   catalogues and routinely carry ł, ś, ž and friends.
   SIL Open Font License 1.1 — see fonts/Simonetta-OFL.txt. */
@font-face {
  font-family: 'Simonetta';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/simonetta-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: 'Simonetta';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/simonetta-400-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: 'Simonetta';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/simonetta-400i-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: 'Simonetta';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/simonetta-400i-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: 'Simonetta';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url('../fonts/simonetta-900-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: 'Simonetta';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url('../fonts/simonetta-900-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 {
  /* These are the "Paper & ink" scheme, written out. js/theme.js derives the
     same values from six seed colours and can swap the lot at runtime; the
     block below is what the page looks like before any of that runs, and with
     JavaScript off. Do not hand-edit one line of it — change the seeds and
     paste in what the Colours panel copies out. */
  --paper:        #faf9f6;
  --surface:      #ffffff;
  --surface-sunk: #f4f2ec;

  --ink:          #17171a;
  --ink-2:        #484540;
  --muted:        #7b776f;
  --muted-2:      #9a958b;

  --line:         #e4e1d9;
  --line-strong:  #cfcbbf;

  --accent:       #1d5c4f;
  --accent-deep:  #14453b;
  --accent-line:  #d5e3df;
  --accent-wash:  #eef4f2;
  /* The seed at full strength, for the two places colour is decoration rather
     than information: the brand mark and the progress bar. */
  --accent-vivid: #1d5c4f;

  /* The one blue: a review the model is looking at right now. Nothing else in
     the palette is blue, which is the point — it reads as machine activity
     rather than part of the page. */
  --working:      #1f5fa8;
  --working-wash: #f5f8fb;

  --amber:        #8a6524;
  --amber-wash:   #f9f2e7;

  --title:        #17171a;   /* headlines and book titles; the ink unless a scheme says otherwise */
  --title-weight: 400;
  --on-ink:       #ffffff;   /* text on the ink itself: the skip link, the toast */
  --shadow-rgb:   23, 23, 26;

  --radius:   6px;
  --radius-s: 4px;

  --serif: 'Simonetta', Georgia, 'Iowan Old Style', 'Times New Roman', Times, serif;
  --sans:  -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --mono:  ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  --wrap: 1180px;
  --sticky-h: 0px;   /* measured at runtime; see syncStickyOffset() */
}

*, *::before, *::after { box-sizing: border-box; }

/* The browser hides [hidden] with a user-agent rule, which any author rule that
   sets `display` silently beats. .results, .clerk and .clerk-recall all set one,
   so they stayed on screen with the attribute applied — the recall button most
   visibly, since it has no opacity of its own to mask it. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding-inline: 24px;
}


.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--on-ink); padding: 10px 16px;
}
.skip:focus { left: 8px; top: 8px; }

a { color: var(--accent); }

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

/* ------------------------------------------------------------------ *
 * Masthead
 * ------------------------------------------------------------------ */

.masthead {
  background: var(--surface);
}

.masthead-inner {
  display: flex;
  align-items: baseline;
  gap: 20px;
  flex-wrap: wrap;
  padding-block: 20px 18px;
}

.brand { display: flex; align-items: center; gap: 10px; color: inherit; text-decoration: none; border-radius: var(--radius-s); }
.brand:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.brand-mark {
  /* Tass (assets/tass.svg), drawn inline in the scheme's accent: the same
     colour as the Commonplace book, so the two change together. */
  flex: none;
  display: block;
  width: 24px; height: 24px;
  /* Level with the body of the word: the G's height and the descenders make
     the wordmark's box sit higher than the letters read. */
  position: relative; top: 4px;
}
.brand-mark svg { display: block; width: 100%; height: 100%; fill: var(--accent-vivid); }

.brand-name {
  font-family: var(--serif);
  font-size: 21px;
  letter-spacing: -0.01em;
  font-weight: 900;
  color: var(--title);
  line-height: 0;
}
/* The Glimpt wordmark, drawn in the title colour so every scheme recolours
   it. The p's descender is a fifth of its height; the negative margin lets
   the word itself, not its box, sit level with the mark beside it. */
.wordmark {
  display: block;
  height: 46px;
  width: auto;
  aspect-ratio: 1254 / 802;
  fill: currentColor;
  margin: -2px 0 -9px;
}
@media (max-width: 640px) { .wordmark { height: 40px; margin-bottom: -8px; } }

.brand-tagline {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
}

/* ------------------------------------------------------------------ *
 * Search bar
 * ------------------------------------------------------------------ */

.searchbar {
  /* No rule underneath: the Edge colour, at half strength, rises from the
     bottom of the bar and fades to nothing halfway up, over the bar's own
     surface, so the bar reads as lifted off the page rather than fenced
     from it. A browser without color-mix gets the plain surface. */
  background: var(--surface);
  background: linear-gradient(to top, color-mix(in srgb, var(--line) 50%, transparent), transparent 50%), var(--surface);
  padding-block: 8px 24px;
  position: sticky;
  top: 0;
  z-index: 40;
}

/* Under the bar, a fade from the paper colour to nothing, laid over the page,
   so cards and reviews scrolling up dissolve before they reach the bar
   instead of being cut off by its edge. It hangs from the bar, pinned or
   not, so it always sits directly under it; it never takes a click. */
.searchbar::after {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 100%;
  height: 36px;
  background: linear-gradient(to bottom, var(--paper), transparent);
  pointer-events: none;
}

/* Not shown, but still read out: the field keeps its name for screen
   readers and voice control, and the placeholder says the rest. */
.field-label {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.combo { position: relative; }

.field {
  width: 100%;
  font-family: var(--serif);
  font-size: 21px;
  line-height: 1.3;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: 14px 92px 14px 16px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field::placeholder { color: var(--muted-2); }
.field:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}


.clear-btn {
  position: absolute;
  top: 50%; right: 10px;
  transform: translateY(-50%);
  font: inherit;
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  padding: 6px 10px;
  cursor: pointer;
}
.clear-btn:hover { color: var(--ink); border-color: var(--line-strong); }
/* Scan holds the same slot while the field is empty, and Clear takes it
   once there is something to clear: same box, so the slot never jumps. */
.scan-btn { display: inline-flex; align-items: center; gap: 6px; }
.scan-icon { flex: none; width: 15px; height: 12px; fill: currentColor; }
.clear-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* What the model is doing, inside the sticky search field so it stays in
   view: right-aligned, left of Clear, with a pulse in the Working colour. */
.field-status {
  position: absolute;
  top: 50%; right: 92px;
  transform: translateY(-50%);
  display: inline-flex; align-items: center; gap: 8px;
  max-width: calc(100% - 180px);
  font-family: var(--sans);
  font-size: 13.5px;
  color: var(--working);
  white-space: nowrap;
  pointer-events: none;
}
.field-status-long, .field-status-short { overflow: hidden; text-overflow: ellipsis; }
.field-status-short { display: none; }
.field-status-dot {
  flex: none;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--working);
  animation: field-pulse 1.2s ease-in-out infinite;
}
@keyframes field-pulse { 0%, 100% { opacity: .25; transform: scale(.8); } 50% { opacity: 1; transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .field-status-dot { animation: none; } }
@media (max-width: 640px) {
  .field-status { font-size: 13px; max-width: calc(100% - 150px); }
  .field-status-long { display: none; }
  .field-status-short { display: inline; }
  /* Pinned, a little tighter, only while the model is at work. */
  .model-working .searchbar { position: sticky; padding-block: 10px 14px; }
}


/* Suggestions ------------------------------------------------------- */

.suggestions {
  position: absolute;
  top: calc(100% + 6px);
  left: 0; right: 0;
  z-index: 50;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: 0 10px 28px rgba(var(--shadow-rgb), 0.10);
  max-height: 60vh;
  overflow-y: auto;
}

.sg-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  border-radius: var(--radius-s);
  cursor: pointer;
}
.sg-item:hover, .sg-item.is-active { background: var(--accent-wash); }

.sg-cover {
  width: 34px; height: 50px;
  object-fit: cover;
  flex: none;
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: 2px;
}
.sg-cover-blank { display: block; }

.sg-text { min-width: 0; display: flex; flex-direction: column; }

.sg-title {
  font-family: var(--serif);
  font-size: 16px;
  color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.sg-meta {
  font-size: 13px;
  color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* The last row: what you typed, whether or not a catalogue agrees it exists.
   Set apart by a rule above it rather than a different ground, so it reads as
   a way out of the list rather than another book in it.

   Sticky, because the list scrolls at 60vh and eight suggestions push this
   below the fold — an escape hatch you have to scroll to find is not one. */
.sg-free {
  position: sticky;
  bottom: -4px;                    /* cancel the list's own 4px padding */
  background: var(--surface);
  border-top: 1px solid var(--line);
}
.sg-free .sg-title { font-style: italic; color: var(--ink-2); }
.sg-free .sg-cover-blank { opacity: .5; }

.sg-empty {
  padding: 14px 12px;
  color: var(--muted);
  font-size: 14px;
}

/* Recents ----------------------------------------------------------- */


/* Chips ------------------------------------------------------------- */


/* ------------------------------------------------------------------ *
 * Intro
 * ------------------------------------------------------------------ */

.intro { padding-block: 56px 72px; }

.intro-lead { max-width: 660px; }

.intro h1 {
  font-family: var(--serif);
  font-size: clamp(28px, 4vw, 40px);
  line-height: 1.18;
  letter-spacing: -0.02em;
  margin: 0 0 18px;
  font-weight: 900;
  color: var(--title);
}

.intro p {
  margin: 0;
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink-2);
}


/* ------------------------------------------------------------------ *
 * Results layout
 * ------------------------------------------------------------------ */

.results {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  gap: 48px;
  padding-block: 40px 80px;
  align-items: start;
  scroll-margin-top: calc(var(--sticky-h) + 16px);
}

.book-pane {
  position: sticky;
  top: calc(var(--sticky-h) + 24px);
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Book card --------------------------------------------------------- */

.book-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
}

.bc-top { display: flex; gap: 16px; }

.bc-cover {
  width: 84px;
  height: 124px;
  object-fit: cover;
  flex: none;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: var(--surface-sunk);
}

.bc-cover-blank {
  display: grid;
  place-items: center;
  font-family: var(--serif);
  font-size: 34px;
  color: var(--muted-2);
}

/* The head runs the height of the cover, so the shelf buttons can sit at
   its foot, level with the bottom of the cover beside them. */
.bc-head { min-width: 0; flex: 1; display: flex; flex-direction: column; }

.bc-title {
  font-family: var(--serif);
  font-size: 20px;
  line-height: 1.25;
  margin: 0 0 4px;
  letter-spacing: -0.01em;
  font-weight: 900;
  color: var(--title);
}

.bc-subtitle {
  margin: 0 0 6px;
  font-size: 14px;
  color: var(--muted);
  font-style: italic;
}

.bc-author {
  margin: 0;
  font-size: 16px;
  color: var(--ink-2);
}

.facts {
  margin: 18px 0 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 14px;
}

.fact { min-width: 0; }
.fact dt {
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.fact dd {
  margin: 3px 0 0;
  font-size: 19px;
  line-height: 1.2;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* Panels ------------------------------------------------------------ *
 *
 * The shape the Prices and Podcasts blocks are built from. It was the Swedish
 * edition card's own styling until that card went — the book card answers the
 * Swedish question in a single row now — and the shell is what was worth
 * keeping.
 * ------------------------------------------------------------------ */

.ident {
  background: var(--accent-wash);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius);
  padding: 16px 18px;
}

.ident-head {
  margin: 0 0 8px;
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-deep);
  font-weight: 600;
}



.ident-note { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--muted); }

.ident-none { margin: 0 0 8px; font-size: 15px; color: var(--ink-2); }


.ident-link {
  display: inline-block;
  margin-top: 10px;
  font-size: 13px;
  color: var(--accent-deep);
}

/* Prices ------------------------------------------------------------ *
 *
 * Sits under the edition panels and borrows their shape, because it answers
 * the next question in the same breath: this is the book, here is what it
 * costs. One line per format, cheapest first.
 * ------------------------------------------------------------------ */

/* It arrives late — after the sweep — into a column the reader has already
   settled on, so it announces itself rather than appearing between blinks:
   the panel rises and fades, then the rows follow it one at a time. */
.prices {
  margin-bottom: 16px;
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity .32s ease, transform .32s ease;
}
.prices.is-in { opacity: 1; transform: none; }

.prices.is-in .price-row {
  animation: priceIn .34s cubic-bezier(.22, .8, .3, 1) backwards;
  animation-delay: calc(var(--i) * 65ms + 120ms);
}

@keyframes priceIn {
  from { opacity: 0; transform: translateY(-7px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .prices { transition: none; }
  .prices.is-in .price-row { animation: none; }
}

.price-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.price-row + .price-row { border-top: 1px solid var(--accent-line); }

/* Folded, each shop's cheapest copy shows. The rest are in the list already,
   so unfolding costs nothing but the class. */
.price-row.is-extra { display: none; }
.prices.is-expanded .price-row.is-extra { display: block; }

.price-more {
  margin-top: 9px;
  font: inherit;
  font-size: 12.5px;
  color: var(--accent);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--accent-line);
  padding: 0 0 1px;
  cursor: pointer;
}
.price-more:hover { color: var(--accent-deep); border-bottom-color: var(--accent); }
.price-more:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.price-link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 0;
  text-decoration: none;
  color: inherit;
}
.price-link:hover .price-what { color: var(--accent-deep); text-decoration: underline; text-underline-offset: 2px; }
.price-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

.price-what {
  font-size: 14px;
  color: var(--ink-2);
  min-width: 0;
}

.price-amount {
  flex: none;
  font-size: 16px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.price-kr { font-size: 11.5px; color: var(--muted); margin-left: 2px; }

/* A reduction, shown as the ordinary price struck through beside the real
   one — the only place in the app where anything is struck out. */
.price-was {
  margin-right: 6px;
  font-size: 12.5px;
  color: var(--muted-2);
  text-decoration-thickness: 1px;
}
.price-row.is-reduced .price-amount { color: var(--amber); }

/* The list is the answer; the notes under it are the caveats, so they get a
   rule and some air rather than running straight on from the last price. */
.prices .price-list + .ident-note,
.prices .ident-none + .ident-note { margin-top: 10px; }
.prices .ident-note + .ident-note {
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px solid var(--accent-line);
}

/* The shops that can only be linked to, one per line: there can be a dozen. */
.price-elsewhere-head { margin: 12px 0 2px; padding-top: 9px; border-top: 1px solid var(--accent-line); font-size: 11px; letter-spacing: 0.09em; text-transform: uppercase; color: var(--muted); }
.price-elsewhere { list-style: none; margin: 0; padding: 0; }
.price-elsewhere li + li { margin-top: 5px; }
.price-elsewhere .ident-link { margin-top: 0; font-size: 14px; }

/* Podcasts ---------------------------------------------------------- *
 *
 * Last in the left column, after the editions: by the time you are wondering
 * what an hour of argument about it sounds like, you have already read what it
 * is and what it costs.
 * ------------------------------------------------------------------ */

.podcasts { margin-top: 16px; }

.pod-list { list-style: none; margin: 0; padding: 0; }
.pod-row + .pod-row { margin-top: 2px; padding-top: 10px; border-top: 1px solid var(--accent-line); }

.pod-link {
  display: block;
  padding: 2px 0 8px;
  text-decoration: none;
  color: inherit;
}
.pod-link:hover .pod-title { color: var(--accent-deep); text-decoration: underline; text-underline-offset: 2px; }
.pod-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

.pod-title {
  display: block;
  font-family: var(--serif);
  font-size: 15.5px;
  line-height: 1.35;
  color: var(--title);
}

.pod-meta {
  display: block;
  margin-top: 3px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--muted);
}

.podcasts .ident-note { margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--accent-line); }

/* List ----------------------------------------------------------------- *
 *
 * The books you chose to keep, in the settings panel under List, on two
 * shelves: Own and Want. The cache behind it holds every book you have
 * opened; this is the curated subset, and the only part that exports.
 * ------------------------------------------------------------------ */

.masthead-slot { display: flex; align-items: center; gap: 14px; }

/* The list, in the settings panel. Two shelves as subtabs, quieter than the
   panel's own tabs above them so the two levels read as two levels. */
.lv-shelves { display: flex; gap: 6px; margin: 14px 0 6px; }
.lv-shelf {
  font: inherit; font-size: 13px;
  color: var(--muted);
  background: none;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 12px;
  cursor: pointer;
}
.lv-shelf:hover { color: var(--accent-deep); border-color: var(--accent-line); }
.lv-shelf[aria-selected="true"] { color: var(--accent-deep); background: var(--accent-wash); border-color: var(--accent-line); font-weight: 600; }
.lv-shelf:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The bookmark on the shelf pills and the card's shelf buttons. */
.bm-icon {
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linejoin: round;
  vertical-align: -2px;
  margin-right: 6px;
}
.lv-shelf[aria-selected="true"] .bm-icon,
.bc-save.is-saved .bm-icon { fill: currentColor; }
.bc-save { display: inline-flex; align-items: center; justify-content: center; }
.lv-arrow { margin-left: 2px; }
.lv-n { font-variant-numeric: tabular-nums; font-weight: 400; color: var(--muted-2); margin-left: 2px; }
.lv-n:empty { display: none; }

.lv-rows { max-height: min(60vh, 520px); overflow-y: auto; }
.lv-tools { display: flex; gap: 8px; margin-top: 14px; }

.lv-row {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}
.lv-row-inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 36px 1fr;
  grid-template-areas: "cover text" "cover actions";
  column-gap: 12px;
  row-gap: 4px;
  align-items: start;
  padding: 11px 0;
  background: var(--surface);
  touch-action: pan-y;          /* vertical scrolling stays the browser's; sideways is ours */
}
/* What a swipe uncovers: the shelf the book is going to, in its colour. */
.lv-band {
  position: absolute; inset: 0;
  display: flex; align-items: center;
  padding: 0 18px;
  font-size: 15px; font-weight: 600;
  opacity: 0;
}
.lv-band.to-own  { justify-content: flex-end;   background: var(--accent-wash); color: var(--accent-deep); }
.lv-band.to-want { justify-content: flex-start; background: var(--amber-wash);  color: var(--amber); }
.lv-row.is-swiping { cursor: grabbing; user-select: none; }
/* A link or a cover dragged with a mouse would start drag-and-drop, which
   cancels the swipe. */
.lv-row-inner a, .lv-row-inner img { -webkit-user-drag: none; user-select: none; }
.lv-cover {
  grid-area: cover;
  width: 36px; height: 52px;
  object-fit: cover;
  border-radius: 3px;
  background: var(--surface-sunk);
  border: 1px solid var(--line);
}
.lv-cover-blank {
  display: grid; place-items: center;
  font-family: var(--serif); font-size: 19px; color: var(--muted-2);
}
.lv-open {
  grid-area: text;
  display: block;
  text-decoration: none;
  color: inherit;
  min-width: 0;
}
.lv-open:hover .lv-title { color: var(--accent-deep); text-decoration: underline; text-underline-offset: 2px; }
.lv-title {
  display: block;
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.25;
  color: var(--title);
}
.lv-meta { display: block; margin-top: 2px; font-size: 12.5px; color: var(--muted); }
.lv-actions { grid-area: actions; display: flex; gap: 14px; }
.lv-move, .lv-remove {
  font: inherit; font-size: 12.5px;
  background: none; border: 0; padding: 2px 0; cursor: pointer;
  border-bottom: 1px solid transparent;
}
.lv-move { color: var(--accent-deep); }
.lv-move:hover { border-bottom-color: var(--accent); }
.lv-remove { color: var(--muted); }
.lv-remove:hover { color: var(--amber); border-bottom-color: var(--amber); }
.lv-empty { margin: 16px 0 4px; font-size: 14px; color: var(--muted); line-height: 1.5; }

/* The two shelf buttons on the book card. The one the book is on is filled;
   pressing it again takes the book off the list. */
.bc-shelf { display: flex; flex-wrap: wrap; gap: 8px; margin-top: auto; padding-top: 12px; }
.bc-save {
  flex: 1 1 0;
  min-width: 74px;
  font-size: 13px;
  padding: 7px 10px;
}
.bc-save.is-saved { color: var(--accent-deep); background: var(--accent-wash); border-color: var(--accent-line); font-weight: 600; }

/* Provenance on the status line: this came from the store, and how old it is. */
.status-cached { color: var(--muted-2); }

/* ------------------------------------------------------------------ *
 * Reviews pane
 * ------------------------------------------------------------------ */


.reviews-pane { min-width: 0; }

/* "1 outlet unreachable" is a button, because the useful question is always
   which one. */
.status-more {
  font: inherit;
  font-size: inherit;
  color: var(--muted);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}
.status-more:hover { color: var(--accent-deep); text-decoration-style: solid; }
.status-more:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

.unreachable {
  margin-top: 12px;
  padding: 11px 14px;
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.55;
}
.unreachable h4 {
  margin: 0 0 6px;
  font-size: 10.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted-2);
  font-weight: 600;
}
.unreachable ul { list-style: none; margin: 0; padding: 0; }
.unreachable li { display: flex; gap: 10px; flex-wrap: wrap; padding: 2px 0; }
.unreachable .u-name { color: var(--ink-2); }
.unreachable .u-why { font-family: var(--mono); font-size: 11px; color: var(--muted-2); }
.unreachable p { margin: 7px 0 0; font-size: 12px; color: var(--muted-2); }

.progress { margin-top: 16px; }

.progress-track {
  height: 3px;
  background: var(--surface-sunk);
  border-radius: 2px;
  overflow: hidden;
}

.progress-bar {
  height: 100%;
  width: 0;
  background: var(--accent-vivid);
  transition: width .25s ease;
}

.progress-text {
  margin: 7px 0 0;
  font-size: 12.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* The clerk reads the closing paragraphs back to you. He is drawn on his own
   cream ground and faces left, so the bubble sits to his left and he keeps his
   own background rather than being cut out onto the page. */
/* A footnote marker: [1], [2]. Points at the one review that statement rests
   on; clicking it raises a copy of that review above the bubble. */
.clerk-ref {
  display: inline;
  font-family: var(--sans);
  font-size: 0.72em;
  font-weight: 600;
  line-height: 1;
  vertical-align: 0.35em;          /* sits like a superscript without shifting the line */
  color: var(--accent);
  cursor: pointer;
  padding: 0 1px;
  border-radius: 2px;
  white-space: nowrap;
}
.clerk-ref:hover,
.clerk-ref.is-open {
  color: var(--surface);
  background: var(--accent-deep);
}
.clerk-ref:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

/* The raised copy of the cited review. Fixed, and positioned from the bubble
   each time it opens, so it sits directly above whatever height it happens to be. */
.clerk-card {
  position: fixed;
  z-index: 70;
  max-height: 46vh;
  overflow-y: auto;
  filter: drop-shadow(0 10px 28px rgba(var(--shadow-rgb), 0.22));
  animation: cardIn .18s ease;
}
.clerk-card .review { margin-bottom: 0; }
/* Its own card: it used to borrow the review card's background, and lost it
   when the reviews went cardless. */
.clerk-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.clerk-card .review-link { padding: 15px 18px; }

@keyframes cardIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .clerk-card { animation: none; }
}

/* The clerk floats over the page rather than sitting in the flow: fixed to the
   bottom right, fading in once he has something to say, and dismissed by
   clicking him. The artwork is transparent, so only he and the bubble cover
   what is behind them. */
.clerk {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 60;
  display: flex;
  align-items: flex-end;
  max-width: min(620px, calc(100vw - 40px));
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .3s ease, transform .3s ease;
  /* the gap between bubble and clerk should not swallow clicks on the page */
  pointer-events: none;
}
.clerk > * { pointer-events: auto; }
.clerk.is-in { opacity: 1; transform: none; }

.clerk-bubble {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 152px;                 /* room for the tail to reach his mouth */
  position: relative;
  margin-right: 14px;
  padding: 16px 18px;
  background: var(--accent-wash);
  border: 1px solid var(--accent-line);
  border-radius: 14px;
  box-shadow: 0 6px 28px rgba(var(--shadow-rgb), 0.14);
}

/* The tail, in two layers so it keeps the bubble's border. His mouth is 51% of
   the way down the artwork, so at 257px tall it sits 126px above the bottom
   edge — and both he and the bubble are bottom-aligned. */
.clerk-bubble::before,
.clerk-bubble::after {
  content: '';
  position: absolute;
  bottom: 126px;
  width: 0; height: 0;
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
}
.clerk-bubble::before {
  right: -11px;
  border-left: 11px solid var(--accent-line);
}
.clerk-bubble::after {
  right: -9px;
  border-left: 10px solid var(--accent-wash);
}

.clerk-tag {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent-deep);
  font-weight: 600;
}

.clerk-verdict {
  margin-bottom: 8px;
  font-size: 10.5px;
  letter-spacing: 0.06em;
  color: var(--surface);
  background: var(--accent-deep);
  border-radius: 3px;
  padding: 2px 7px;
}
.clerk-verdict:empty { display: none; }

.clerk-text {
  margin: 0;
  font-family: var(--serif);
  font-size: 17.5px;
  line-height: 1.55;
  color: var(--ink);
}

.clerk-source {
  margin: 8px 0 0;
  font-size: 11.5px;
  color: var(--muted);
}
.clerk-source:empty { display: none; }

/* He is the dismiss control, so he is a button — keyboard reachable, and with
   a cursor that says he can be clicked. */
.clerk-dismiss {
  flex: none;
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  border-radius: var(--radius);
  transition: transform .15s ease, filter .15s ease;
}
.clerk-dismiss:hover { transform: translateY(2px); filter: brightness(1.04); }
.clerk-dismiss:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.clerk-art {
  width: 190px;
  height: 257px;
  display: block;
  filter: drop-shadow(0 4px 10px rgba(var(--shadow-rgb), 0.18));
}

@media (max-width: 760px) {
  .clerk { right: 12px; bottom: 12px; max-width: calc(100vw - 24px); }
  .clerk-bubble { min-height: 108px; padding: 13px 14px; margin-right: 10px; }
  .clerk-bubble::before, .clerk-bubble::after { bottom: 88px; }
  .clerk-text { font-size: 16px; }
  .clerk-art { width: 132px; height: 179px; }
}

/* His bubble always stands clear of her headphones button's corner, button
   or not: lifted by the button's height and a gap, the tail lowered by the
   same so it still meets his mouth, the floor lowered with it. Making room
   only once the button appeared made the bubble jump up after arriving. */
.clerk-bubble { margin-bottom: 58px; min-height: 94px; }
.clerk-bubble::before, .clerk-bubble::after { bottom: 68px; }
@media (max-width: 760px) {
  .clerk-bubble { min-height: 50px; }
  .clerk-bubble::before, .clerk-bubble::after { bottom: 30px; }
}

/* Award winning: at the top of the bubble, beside the verdict, when the
   book won something (js/awards.js). */
.clerk-award-tag {
  display: inline-flex; align-items: center; gap: 5px; flex: none; white-space: nowrap; line-height: 1.5;
  margin-bottom: 8px; padding: 1px 7px 1px 6px;
  font-size: 10.5px; letter-spacing: 0.03em;
  color: var(--amber); background: var(--surface);
  border: 1px solid var(--amber); border-radius: 3px;
}
.clerk-tag:has(.clerk-award-tag) { flex-wrap: wrap; column-gap: 6px; }
.clerk-award-tag svg { width: 11px; height: 11px; fill: currentColor; flex: none; }

/* The podcast tip ---------------------------------------------------- *
 *
 * The clerk's opposite number. He arrives bottom right with the critics'
 * verdict; she arrives bottom left when one of the two trusted shows has done
 * an episode. Same artwork height as him — 257px — so the two read as the same
 * pair of hands, even though her source image is a different crop.
 * ------------------------------------------------------------------ */

.podrec {
  position: fixed;
  left: 20px;
  bottom: 20px;
  z-index: 60;
  display: flex;
  /* Bottom-aligned, as he is: the bubble's foot on her feet, and the tail a
     fixed height up from that foot so it meets her mouth. A one-line tip would
     be too short for that height and push the tail out through the top corner,
     so the bubble has a floor of 150px. */
  align-items: flex-end;
  max-width: min(560px, calc(100vw - 40px));
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .3s ease, transform .3s ease;
  pointer-events: none;
}
.podrec > * { pointer-events: auto; }
.podrec.is-in { opacity: 1; transform: none; }

/* She is the dismiss control, the way he is. */
.podrec-dismiss {
  flex: none;
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.podrec-dismiss:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.podrec-art {
  width: 206px;                      /* 257px tall at the artwork's 600:750 */
  height: 257px;
  display: block;
  filter: drop-shadow(0 4px 10px rgba(var(--shadow-rgb), 0.18));
}

.podrec-bubble {
  flex: 0 1 auto;
  min-width: 0;
  position: relative;
  min-height: 150px;
  margin: 0 0 0 14px;
  padding: 16px 18px;
  background: var(--amber-wash);
  border: 1px solid var(--line-strong);
  border-radius: 14px;
  box-shadow: 0 6px 28px rgba(var(--shadow-rgb), 0.14);
}

/* The tail points the other way to his, because she stands on the other side.
   125px up from the foot is her mouth, on a 257px figure standing level with
   the bubble. */
.podrec-bubble::before,
.podrec-bubble::after {
  content: '';
  position: absolute;
  bottom: 125px;
  width: 0; height: 0;
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
}
.podrec-bubble::before {
  left: -11px;
  border-right: 11px solid var(--line-strong);
}
.podrec-bubble::after {
  left: -9px;
  border-right: 10px solid var(--amber-wash);
}

.podrec-tag {
  margin: 0 0 8px;
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--amber);
  font-weight: 600;
}

.podrec-text {
  margin: 0;
  font-family: var(--serif);
  font-size: 17.5px;
  line-height: 1.55;
  color: var(--ink);
}

/* On a phone there is no room beside her, so the bubble goes above her and she
   stands on the floor of the screen, as he does. The tail turns to point down
   at her, a quarter of the way in from the left — where her head is, since the
   bubble runs the full width and she stands at its left edge. Her artwork
   stays 257px; only the bubble tightens. */
@media (max-width: 760px) {
  .podrec {
    left: 12px; bottom: 12px;
    max-width: calc(100vw - 24px);
    flex-direction: column;
    align-items: flex-start;
  }
  .podrec-dismiss { order: 2; }
  .podrec-bubble { order: 1; padding: 13px 14px; margin: 0 0 14px; }
  .podrec-bubble { min-height: 0; }
  .podrec-bubble::before, .podrec-bubble::after {
    left: 25%; margin-left: -9px;
    border-top: 0; border-bottom: 0; border-right: 0;
    border-left: 9px solid transparent;
    border-right: 9px solid transparent;
  }
  .podrec-bubble::before { bottom: -11px; border-top: 11px solid var(--line-strong); }
  .podrec-bubble::after  { bottom: -9px;  border-top: 10px solid var(--amber-wash); }
  .podrec-text { font-size: 16px; }
}

/* Once he has been sent away, a small page icon takes his place in the corner
   so the summary can be called back. Same corner, same z-index, so one replaces
   the other rather than the two ever sitting side by side. */
.clerk-recall {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 60;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  padding: 0;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.14);
  cursor: pointer;
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.clerk-recall:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: 0 7px 20px rgba(var(--shadow-rgb), 0.18);
}
.clerk-recall:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.clerk-recall svg {
  width: 21px;
  height: 21px;
  fill: none;
  stroke: var(--accent-deep);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (max-width: 760px) {
  .clerk-recall { right: 12px; bottom: 12px; }
}

/* Hers, the headphones: the same button in her corner, in her amber. */
.podrec-recall { left: 20px; right: auto; }
.podrec-recall svg { stroke: var(--amber); }
.podrec-recall:hover { border-color: var(--amber); }
@media (max-width: 760px) {
  .podrec-recall { left: 12px; right: auto; }
}

.reviews-list { margin-top: 20px; }

.review-items {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The blurb ---------------------------------------------------------- *
 *
 * What the book is about, above the list, while the sweep is still running.
 * Deliberately not a card: it is context, not a result, and a bordered block
 * here would read as the first review.
 * ------------------------------------------------------------------ */

.blurb {
  margin: 14px 0 18px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
}

.blurb-label {
  margin: 0 0 6px;
  font-size: 10.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted-2);
}

.blurb-body { display: block; }
.blurb.is-hidden .blurb-body { display: none; }

.blurb-body p {
  margin: 0 0 9px;
  font-family: var(--serif);
  /* It sits a card’s padding wider than the quotes below it, so at the same
     size it reads a touch longer — 83 characters. */
  font-size: 22px;
  line-height: 1.5;
  color: var(--ink-2);
}
.blurb-body p:last-child { margin-bottom: 0; }

.blurb-more {
  margin-top: 8px;
  font: inherit;
  font-size: 12.5px;
  color: var(--accent);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--accent-line);
  padding: 0 0 1px;
  cursor: pointer;
}
.blurb-more:hover { color: var(--accent-deep); border-bottom-color: var(--accent); }
.blurb-more:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Separate cards rather than one bordered list. The 10px is a margin, not a
   flex gap, so that a card being discarded can collapse its own spacing too —
   a zero-height flex item still takes its gap, which would leave a hole. */
.review {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin-bottom: 10px;
}
.review:last-child { margin-bottom: 0; }



/* Being looked at by the model: a 2px dashed ring that crawls slowly clockwise.

   It is painted on a pseudo-element rather than as a border or outline, so the
   card does not resize and nothing below it shifts. The two masks cut the fill
   down to a 2px ring that follows the card's own corner radius — a plain
   `border: dashed` cannot be animated, and straight gradient edges would leave
   gaps at the corners. */
.review.is-verifying { position: relative; background: var(--working-wash); }

.review.is-verifying::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  padding: 2px;                       /* the thickness of the ring */
  border-radius: inherit;
  pointer-events: none;
  background: repeating-linear-gradient(
    45deg,
    var(--working) 0 7px,
    transparent 7px 15px
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  animation: ants 700ms linear infinite;
}

@keyframes ants {
  to { background-position: 21.21px 0; }   /* one full stripe cycle at 45 degrees */
}

@media (prefers-reduced-motion: reduce) {
  .review.is-verifying::after { animation: none; }
}

/* Thrown out as a different book: fade, then collapse so the rows below slide
   up into the gap. The height is set in JS because it has to be measured first
   — you cannot transition from auto. */
.review.is-leaving {
  overflow: hidden;
  opacity: 0;
  transform: translateX(-12px);
  margin-bottom: 0;
  /* border-width too, or border-box leaves a 2px sliver at height: 0 */
  border-width: 0;
  transition: height .34s cubic-bezier(.4, 0, .2, 1),
              margin-bottom .34s cubic-bezier(.4, 0, .2, 1),
              border-width .34s cubic-bezier(.4, 0, .2, 1),
              opacity .2s ease,
              transform .24s ease;
}

.review-link {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 15px 18px;
  text-decoration: none;
  color: inherit;
}
.review-link:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Set in the serif, italic and uppercased. Capitals set solid look cramped, so
   they get a little tracking back, and the size drops since uppercase reads
   larger than the same point size in mixed case. */
.review-outlet {
  font-family: var(--serif);
  font-style: italic;
  /* 900 is the heaviest Simonetta ships; asking for more only gets a synthetic
     smear. At 10px the capitals need the extra tracking to stay readable. */
  font-weight: 900;
  font-size: 10px;
  line-height: 1.3;
  letter-spacing: 0.085em;
  text-transform: uppercase;
  color: var(--accent-deep);
}

.review-headline {
  font-family: var(--serif);
  font-size: 25px;
  line-height: 1.28;
  color: var(--title);
  font-weight: var(--title-weight);
}
.review-link:hover .review-headline { text-decoration: underline; text-underline-offset: 2px; }

.review-top {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

/* The date rides with the outlet rather than sitting in a footer of its own.
   Quieter than the outlet and not set in caps, so the pair reads as one line
   with an emphasis rather than as two competing labels. */
.review-date {
  font-size: 11.5px;
  color: var(--muted-2);
  white-space: nowrap;
}

.rating-badge {
  flex: none;
  margin-left: auto;
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  color: var(--accent-deep);
  background: var(--accent-wash);
  border: 1px solid var(--accent-line);
  border-radius: 3px;
  padding: 2px 7px;
}

/* No box, and no label. The quote sits straight on the card under the
   headline, which is enough to say what it is. */
.review-closing {
  display: block;
  margin-top: 7px;
}

.closing-text {
  display: block;
  font-family: var(--serif);
  /* Simonetta has a smaller x-height than Georgia, so the quote needed a point
     back to read as comfortably at the same measure. Out of its box it carries
     the card on its own, and took another. */
  /* At 16px this ran to 104 characters a line in a 726px column, half as long
     again as anything you would set a book in. Raising the size rather than
     narrowing the column brings it to 79. */
  font-size: 21px;
  line-height: 1.55;
  color: var(--ink-2);
  quotes: '\201C' '\201D';
}
.closing-text::before { content: open-quote; }
.closing-text::after  { content: close-quote; }


.review-snippet {
  font-size: 16px;
  line-height: 1.55;
  color: var(--muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.reviews-list-quiet .review-headline { font-size: 19px; }
.reviews-list-quiet .review { background: var(--surface-sunk); }

.disclosure {
  font: inherit;
  font-size: 13.5px;
  color: var(--ink-2);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line-strong);
  padding: 4px 0;
  cursor: pointer;
}
.disclosure::before {
  content: '+';
  display: inline-block;
  width: 14px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.disclosure[aria-expanded="true"]::before { content: '\2212'; }
.disclosure:hover { color: var(--accent-deep); border-bottom-color: var(--accent); }

.reviews-pane .empty {
  margin: 20px 0 0;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  line-height: 1.6;
  max-width: 68ch;
}

/* ------------------------------------------------------------------ *
 * Sources pane
 * ------------------------------------------------------------------ */

.pane-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line-strong);
}

.pane-head h2 {
  font-family: var(--serif);
  font-size: 29px;
  margin: 0;
  letter-spacing: -0.01em;
  font-weight: 900;
  color: var(--title);
}


.pane-count { margin: 0; font-size: 13.5px; color: var(--muted); }

.pane-side {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}



.btn {
  font: inherit;
  font-size: 13.5px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-s);
  padding: 8px 15px;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color .12s ease, background .12s ease;
}
.btn:hover { border-color: var(--accent); color: var(--accent-deep); background: var(--accent-wash); }


/* Groups & rows ----------------------------------------------------- */



.empty { color: var(--muted); font-size: 14px; }

/* ------------------------------------------------------------------ *
 * Footer & toast
 * ------------------------------------------------------------------ */

.footer {
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding-block: 28px 40px;
}

.footer-inner { max-width: 760px; }

.footer p { margin: 0 0 9px; font-size: 16px; line-height: 1.55; color: var(--muted); }

.footer-meta { font-size: 13.5px; line-height: 1.5; color: var(--muted-2); }

.footer code {
  font-family: var(--mono);
  font-size: 12px;
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 1px 5px;
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 12px);
  z-index: 90;
  background: var(--ink);
  color: var(--on-ink);
  font-size: 14px;
  padding: 11px 20px;
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(var(--shadow-rgb), 0.22);
  opacity: 0;
  transition: opacity .18s ease, transform .18s ease;
}
.toast.is-on { opacity: 1; transform: translate(-50%, 0); }

/* The scanner: a sheet over the page with the camera in it, a frame to aim
   with, one line of guidance and two buttons. Without a camera the view
   folds away and the photo button becomes the way on. */
.scan-open { overflow: hidden; }
.scan-sheet {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  background: rgba(var(--shadow-rgb), 0.45);
  opacity: 0;
  transition: opacity .18s ease;
}
.scan-sheet.is-in { opacity: 1; }
.scan-card {
  width: min(480px, 100%);
  max-height: 100%;
  overflow: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 18px 18px 16px;
  box-shadow: 0 18px 50px rgba(var(--shadow-rgb), 0.3);
}
.scan-title {
  margin: 0 0 12px;
  font-family: var(--serif);
  font-size: 24px;
  font-weight: var(--title-weight);
  line-height: 1.2;
  color: var(--title);
}
.scan-view {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--ink);
  border-radius: var(--radius);
  overflow: hidden;
}
.scan-video { display: block; width: 100%; height: 100%; object-fit: cover; }
.scan-box {
  position: absolute;
  left: 12%; right: 12%; top: 28%; bottom: 28%;
  border: 2px solid var(--on-ink);
  border-radius: 8px;
  box-shadow: 0 0 0 100vmax rgba(var(--shadow-rgb), 0.3);
  pointer-events: none;
}
.scan-hint { margin: 12px 0 0; font-size: 15px; line-height: 1.45; color: var(--ink-2); }
.scan-hint.is-problem { color: var(--amber); }
.scan-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; margin-top: 14px; }
.no-camera .scan-view { display: none; }
.no-camera .scan-photo { background: var(--accent); border-color: var(--accent); color: var(--on-ink); }
.no-camera .scan-photo:hover { background: var(--accent-deep); border-color: var(--accent-deep); color: var(--on-ink); }
@media (max-width: 560px) {
  .scan-sheet { align-items: flex-end; padding: 0; }
  .scan-card { border-radius: 14px 14px 0 0; border-bottom: 0; padding: 16px 16px 20px; }
  .scan-view { aspect-ratio: 3 / 4; max-height: 58vh; width: 100%; }
  .scan-actions .btn { flex: 1; font-size: 15px; padding: 11px 14px; }
}
@media (prefers-reduced-motion: reduce) { .scan-sheet { transition: none; } }

/* ------------------------------------------------------------------ *
 * Responsive
 * ------------------------------------------------------------------ */

@media (max-width: 1000px) {
  .results { grid-template-columns: 1fr; gap: 32px; }
  .book-pane { position: static; }
  .book-card { display: grid; }
  /* One column: the reviews are the point, so they come straight after the
     book card, then the podcasts, and the prices last of all. The side pane
     steps out of the way so its three parts can be ordered among the rest. */
  .book-pane { display: contents; }
  .book-card { order: 1; }
  .reviews-pane { order: 2; }
  .podcasts { order: 3; margin-top: 0; }
  .results .videos { order: 4; margin-top: 0; }
  .prices { order: 5; margin-top: 0; }
}

@media (max-width: 640px) {
  .wrap { padding-inline: 16px; }
  /* Not pinned on a phone, but still positioned, so the fade under it
     (.searchbar::after) hangs from the bar and not from the page. */
  .searchbar { position: relative; padding-block: 6px 20px; }
  .field { font-size: 17px; padding: 12px 96px 12px 13px; }   /* room for Scan, the wider of the two */
  .intro { padding-block: 36px 48px; }
  .pane-head { flex-direction: column; align-items: flex-start; gap: 8px; }
  .pane-head h2 { font-size: 25px; }
  .review-link { padding: 14px 15px; }

  /* The sizes above are set for a 726px column. Carried onto a phone they cut
     the quote to 36 characters a line — as unreadable at the short end as 104
     was at the long. These bring it back to the mid-forties. */
  .review-headline { font-size: 21px; }
  .closing-text { font-size: 17px; }
  .blurb-body p { font-size: 17.5px; }
  .review-snippet { font-size: 15px; }
  .reviews-list-quiet .review-headline { font-size: 17px; }
  .footer p { font-size: 15px; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
}

@media print {
  .searchbar, .footer, .toast, .skip, .btn { display: none; }
  .results { grid-template-columns: 1fr; }
  .review-link { color: #000; }
}
/* ------------------------------------------------------------------ *
 * Colours panel
 *
 * Built by js/theme.js, so any page that loads the script gets it — the
 * styleguide needs it as much as the app does, since that is where colour
 * decisions actually get made.
 * ------------------------------------------------------------------ */

.masthead-slot { margin-left: auto; align-self: center; }
.rg-slot { float: right; }

.settings-launch {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font: inherit;
  font-size: 12.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  padding: 5px 11px 5px 9px;
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
}
.settings-launch svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.settings-launch:hover { color: var(--accent-deep); border-color: var(--accent-line); }
.settings-launch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.settings-launch.is-floating { position: fixed; top: 16px; right: 16px; z-index: 60; background: var(--surface); }


.st-tabs {
  display: flex;
  gap: 2px;
  margin-top: 14px;
  border-bottom: 1px solid var(--line);
}
.st-tab {
  font: inherit;
  font-size: 13px;
  color: var(--muted);
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  padding: 6px 10px;
  cursor: pointer;
}
.st-tab:hover { color: var(--accent-deep); }
.st-tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--accent); font-weight: 600; }
.st-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

.st-choices { margin-top: 14px; }
.st-choice {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 9px 0;
  border-top: 1px solid var(--line);
  cursor: pointer;
}
.st-choice:first-child { border-top: 0; }
.st-choice input { margin-top: 3px; accent-color: var(--accent); }
.st-choice-text { display: block; min-width: 0; }
.st-choice-label { display: block; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.st-choice-note { display: block; margin-top: 2px; font-size: 12px; line-height: 1.45; color: var(--muted); }
/* Shown but not offered: the browser cannot do it, and the note says why. */
.st-choice.is-ghost { cursor: default; }
.st-choice.is-ghost .st-choice-label, .st-choice.is-ghost .st-choice-note { color: var(--muted-2); }

.st-extra { padding: 2px 0 10px 24px; }

/* Commonplace › Connexions: Glimpt's own clerk, a switch above the models. */
.st-switch-row { align-items: center; justify-content: space-between; gap: 16px; margin-top: 14px; padding: 12px 0; border-top: 0; border-bottom: 1px solid var(--line); }
.st-switch {
  appearance: none; -webkit-appearance: none; flex: none; position: relative;
  width: 44px; height: 26px; margin: 0; border-radius: 999px; cursor: pointer;
  background: var(--line); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 12%, transparent);
  transition: background-color .18s ease;
}
.st-switch::after {
  content: ''; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--surface, #fff); box-shadow: 0 1px 3px rgb(0 0 0 / .25); transition: transform .18s ease;
}
.st-switch:checked { background: var(--accent); }
.st-switch:checked::after { transform: translateX(18px); }
.st-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .st-switch, .st-switch::after { transition: none; } }
.st-url-row { display: flex; gap: 8px; align-items: center; }
.st-url { flex: 1; margin-top: 0; }
/* Commonplace › Sources: the add row and the reader's own sites. */
.st-lang {
  font: inherit; font-size: 13px;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-s);
  padding: 7px 6px;
}
.st-src-add { margin-top: 14px; }
.st-src-add .st-url { min-width: 0; }
.st-src-rows { margin-top: 10px; border-top: 1px solid var(--line); }
.st-src {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}
.st-src-text { min-width: 0; }
.st-src-name { display: block; font-family: var(--serif); font-size: 16px; color: var(--title); }
.st-src-meta { display: block; margin-top: 2px; font-size: 12.5px; color: var(--muted); overflow-wrap: anywhere; }
.st-src-empty { margin: 12px 0 0; font-size: 13px; color: var(--muted); }
/* The eye under the model address: shows and hides the address and the key. */
.st-reveal {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 8px;
  font: inherit; font-size: 13px;
  color: var(--muted);
  background: none; border: 0; padding: 4px 0; cursor: pointer;
}
.st-reveal svg { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.st-reveal:hover { color: var(--accent-deep); }
.st-reveal:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
.settings-panel .st-reveal { font-size: 14.5px; }
.st-url-extras { margin-top: 8px; flex-direction: column; align-items: stretch; }
.st-url-extras .st-url { min-width: 0; width: 100%; }
.st-key-note { display: block; margin-top: 6px; }

.st-about { margin: 12px 0 0; font-size: 13px; line-height: 1.55; color: var(--ink-2); }
.st-about:first-child { margin-top: 14px; }
.st-about-h {
  margin: 22px 0 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: 17px;
  color: var(--title);
}
.st-about-list { padding-left: 18px; }
.st-about-list li + li { margin-top: 6px; }
.st-about a { color: var(--accent-deep); }
/* A font credit is set in the face it names. */
.st-about a[href*="specimen/Simonetta"] { font-family: var(--serif); font-size: 15px; }
.st-about img { display: block; }

/* The coffee button: Buy Me a Coffee's own yellow and black, drawn here as a
   plain link rather than their embed, which loads a script on every view. */
.bmc-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  padding: 0.5em 1.05em;
  background: #ffdd00;
  color: #000;
  border: 2px solid #000;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  transition: box-shadow 150ms ease;
}
.st-about a.bmc-btn { color: #000; }
.bmc-btn:hover, .bmc-btn:focus-visible { box-shadow: 0 5px 10px rgba(0, 0, 0, 0.25); }
@media (prefers-reduced-motion: reduce) { .bmc-btn { transition: none; } }

.theme-launch {
  font: inherit;
  font-size: 12.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  padding: 5px 11px;
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
}
.theme-launch:hover { color: var(--accent-deep); border-color: var(--accent-line); }
.theme-launch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-launch.is-floating { position: fixed; top: 16px; right: 16px; z-index: 60; background: var(--surface); }

.theme-lab {
  position: fixed;
  top: 64px;
  right: 20px;
  z-index: 70;
  width: 332px;
  max-height: calc(100vh - 88px);
  overflow-y: auto;
  padding: 18px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: 0 14px 40px rgba(var(--shadow-rgb), 0.16);
}

.tl-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.tl-head h2 {
  margin: 0;
  font-family: var(--serif);
  font-size: 19px;
  font-weight: 900;
  color: var(--ink);
}
.tl-close {
  font: inherit;
  font-size: 12.5px;
  color: var(--muted);
  background: none;
  border: 0;
  padding: 2px;
  cursor: pointer;
}
.tl-close:hover { color: var(--accent-deep); }
.tl-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.tl-presets { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.tl-chip {
  font: inherit;
  font-size: 13px;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  padding: 5px 10px;
  cursor: pointer;
}
.tl-chip:hover { border-color: var(--accent-line); color: var(--accent-deep); }
.tl-chip[aria-pressed="true"] {
  color: var(--accent-deep);
  background: var(--accent-wash);
  border-color: var(--accent-line);
  font-weight: 600;
}
.tl-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.tl-custom { margin: 8px 0 0; font-size: 12.5px; color: var(--muted); }

.tl-intro {
  margin: 12px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
}

.tl-row {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin-top: 16px;
}

.tl-swatch {
  flex: none;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-s);
  background: none;
  cursor: pointer;
}
.tl-swatch::-webkit-color-swatch-wrapper { padding: 2px; }
.tl-swatch::-webkit-color-swatch { border: 0; border-radius: 2px; }
.tl-swatch::-moz-color-swatch { border: 0; border-radius: 2px; }
.tl-swatch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.tl-body { min-width: 0; flex: 1; }

.tl-label {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
}

.tl-hex {
  width: 100%;
  margin-top: 4px;
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--ink-2);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  padding: 4px 7px;
}
.tl-hex:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent-line); }

.tl-note { margin: 5px 0 0; font-size: 12px; line-height: 1.45; color: var(--muted); }

.tl-strip { display: flex; gap: 3px; margin-top: 7px; }
.tl-token {
  flex: 1;
  height: 15px;
  border: 1px solid var(--line);
  border-radius: 2px;
}

.tl-readout { margin: 6px 0 0; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.tl-readout.is-thin { color: var(--amber); }

.tl-foot {
  display: flex;
  gap: 8px;
  margin-top: 20px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.tl-btn { font-size: 13px; padding: 6px 12px; }

@media (max-width: 640px) {
  .theme-lab { right: 12px; left: 12px; width: auto; top: 56px; }
}

/* The backlog line in the LLM tab: what the model is reading in the background. */
.st-backlog { margin: 6px 0 16px; }


/* Commonplace, the panel ------------------------------------------------ *
 *
 * A drawer the full height of the screen, on the right; the full width of it
 * on a phone. Its type is set here in one place, a size up from the rest of
 * the page's small print: at 12–13px, settings text was hard work.
 * Scoped to .theme-lab.settings-panel so it outranks the Colours workshop's
 * own rules above, which the styleguide still uses at their original size.
 * ------------------------------------------------------------------ */

.theme-lab.settings-panel {
  top: 0; right: 0; bottom: 0; left: auto;
  width: min(440px, 100vw);
  height: 100vh; height: 100dvh;
  max-height: none;
  padding: 0 22px 32px;
  border: 0;
  border-left: 1px solid var(--line-strong);
  border-radius: 0;
  box-shadow: -12px 0 40px rgba(var(--shadow-rgb), 0.14);
  overscroll-behavior: contain;
  font-size: 16px;
}
.settings-panel .st-top {
  position: sticky; top: 0; z-index: 2;
  margin: 0 -22px;
  padding: 18px 22px 0;
  background: var(--surface);
}
.settings-panel .tl-head h2 { font-size: 26px; }
.settings-panel .tl-close { font-size: 16px; padding: 6px 2px; }

.settings-panel .st-tabs { margin-top: 12px; overflow-x: auto; scrollbar-width: none; }
.settings-panel .st-tabs::-webkit-scrollbar { display: none; }
.settings-panel .st-tab { font-size: 16px; padding: 10px 11px; white-space: nowrap; }

.settings-panel .tl-intro,
.settings-panel .st-about { font-size: 16px; line-height: 1.6; }
.settings-panel .st-about-h { font-size: 21px; margin-top: 28px; }
.settings-panel .st-about a[href*="specimen/Simonetta"] { font-size: 18px; }
.settings-panel .bmc-btn { font-size: 16px; }

.settings-panel .st-choice-label { font-size: 17px; }
/* The radio's middle on the title's middle: the 3px above suited the old
   13.5px label, and left the radio high beside the 17px one. */
.settings-panel .st-choice input { margin-top: 7px; }
.settings-panel .st-choice-note,
.settings-panel .tl-note,
.settings-panel .tl-custom { font-size: 14.5px; line-height: 1.5; }
.settings-panel .tl-readout { font-size: 14px; line-height: 1.45; }
.settings-panel .tl-label { font-size: 16px; }
.settings-panel .tl-hex,
.settings-panel .st-url,
.settings-panel .st-lang { font-size: 15px; }
.settings-panel .tl-chip,
.settings-panel .tl-btn { font-size: 15px; padding: 8px 14px; }

.settings-panel .lv-shelf { font-size: 15.5px; padding: 6px 14px; }
.settings-panel .lv-title { font-size: 20px; }
.settings-panel .lv-meta,
.settings-panel .st-src-meta { font-size: 14.5px; }
.settings-panel .lv-move,
.settings-panel .lv-remove { font-size: 15px; padding: 4px 0; }
.settings-panel .lv-empty,
.settings-panel .st-src-empty { font-size: 15px; }
.settings-panel .st-src-name { font-size: 19px; }
.settings-panel .lv-rows { max-height: none; overflow: visible; }
.settings-panel .lv-row-inner { grid-template-columns: 44px 1fr; column-gap: 14px; }
.settings-panel .lv-cover { width: 44px; height: 64px; }

@media (max-width: 560px) {
  .theme-lab.settings-panel { width: 100vw; border-left: 0; padding: 0 16px 28px; }
  .settings-panel .st-top { margin: 0 -16px; padding: 14px 16px 0; }
  .settings-panel .st-tab { padding: 10px 6px; font-size: 15.5px; }
  .settings-panel .st-tabs { gap: 0; justify-content: space-between; }
  /* The address gets its own line; the language and Add go under it. */
  .settings-panel .st-src-add { flex-wrap: wrap; }
  .settings-panel .st-src-add .st-url { flex: 1 1 100%; }
  .settings-panel .st-src-add .st-lang { flex: 1; }
}

/* The intro's top rule separates it from the Colours presets. First in a
   pane, straight under the tab bar, it only doubles the bar's own line. */
.settings-panel .st-pane > .tl-intro:first-child { border-top: 0; padding-top: 0; margin-top: 18px; }

/* Under the Colours chips while Mine is chosen: its changes are kept, and
   this takes it back to the four colours it started from. */
.tl-reset-btn {
  font: inherit;
  color: var(--accent-deep);
  background: none; border: 0; padding: 0; cursor: pointer;
  text-decoration: underline; text-underline-offset: 2px;
}
.tl-reset-btn:hover { color: var(--accent); }


/* The app --------------------------------------------------------------- *
 *
 * Install, in the masthead beside Commonplace, while the browser offers it;
 * the bar that says a new version is ready; the About tab's app section.
 * ------------------------------------------------------------------ */

.install-btn {
  display: inline-flex; align-items: center; gap: 7px;
  font: inherit; font-size: 12.5px; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--accent-deep);
  background: var(--accent-wash);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius-s);
  padding: 7px 12px;
  cursor: pointer;
}
.install-btn svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.install-btn:hover { border-color: var(--accent); }
.install-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 480px) {
  .install-btn { padding: 7px 9px; }
  .install-btn span { display: none; }            /* the icon alone; the label is on the button */
}

.update-bar {
  position: fixed; left: 0; right: 0; bottom: 20px; z-index: 90;
  width: fit-content; margin: 0 auto;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: center;
  max-width: min(560px, calc(100vw - 24px));
  padding: 12px 14px 12px 18px;
  background: var(--ink); color: var(--surface);
  border-radius: 12px;
  box-shadow: 0 10px 34px rgba(var(--shadow-rgb), 0.28);
  font-size: 15px;
  transform: translateY(16px); opacity: 0;
  transition: transform .28s ease, opacity .28s ease;
}
.update-bar.is-in { transform: none; opacity: 1; }
.update-go { background: var(--surface); color: var(--ink); border-color: var(--surface); font-weight: 600; padding: 7px 14px; }
.update-later { font: inherit; font-size: 14px; color: inherit; opacity: .75; background: none; border: 0; padding: 6px 4px; cursor: pointer; }
.update-later:hover { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .update-bar { transition: none; } }

.st-app { margin-top: 6px; }
.st-app-check { margin-top: 10px; }

/* Commonplace › Share: the share sheet, the address, the QR code. */
.st-share-which { margin-top: 16px; }
.st-share-sheet {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  width: 100%; margin-top: 14px; padding: 11px 16px;
  font-size: 16px; font-weight: 600;
  color: var(--accent-deep); background: var(--accent-wash); border-color: var(--accent-line);
}
.st-share-sheet svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.st-share-sheet:hover { border-color: var(--accent); }
.st-share-url { margin-top: 14px; }
.st-share-url .st-url { min-width: 0; }
.st-qr { margin: 20px 0 0; text-align: center; }
.st-qr-code {
  display: inline-block; width: min(240px, 70vw); padding: 10px;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
}
.st-qr-code svg { display: block; width: 100%; height: auto; }
.st-qr-cap { margin: 10px auto 0; max-width: 30ch; font-size: 13px; line-height: 1.45; color: var(--muted); }
.settings-panel .st-qr-cap { font-size: 14.5px; }
.st-qr-save { display: block; margin: 10px auto 0; font-size: 14px; }

/* Commonplace › Sources › Bookshops */
.st-sub { margin: 30px 0 0; font-family: var(--serif); font-weight: 400; font-size: 19px; color: var(--title); }
.st-shops { margin: 16px 0 0; padding: 0; border: 0; }
.st-shops-legend { padding: 0; margin-bottom: 4px; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.st-shop { display: flex; align-items: flex-start; gap: 11px; padding: 9px 0; border-bottom: 1px solid var(--line); cursor: pointer; }
.st-shop input { margin: 4px 0 0; accent-color: var(--accent); width: 17px; height: 17px; flex: none; }
.st-shop-name { display: block; font-size: 16px; color: var(--ink); }
.st-shop-note { display: block; margin-top: 1px; font-size: 13.5px; color: var(--muted); }
.st-shop-note.is-live { color: var(--accent-deep); }

.lv-tools { flex-wrap: wrap; }
.lv-format { margin: 10px 0 0; font-size: 14px; color: var(--muted); }
.lv-format a { color: var(--accent-deep); }

/* On YouTube: the podcast panel's shape, under it, in the warm wash rather
   than the green, so the two lists read as two things. The amber pair comes
   from the colour scheme, so it follows whichever one is chosen. */
.videos { margin-top: 16px; --video-line: color-mix(in srgb, var(--amber) 22%, var(--amber-wash)); }
.videos .ident { background: var(--amber-wash); border-color: var(--video-line); }
.videos .ident-head { color: var(--amber); }
.videos .pod-row + .pod-row { border-top-color: var(--video-line); }
.videos .pod-link:hover .pod-title { color: var(--amber); }

/* Podcasts beyond the first six, unfolded by the button under them. */
.pod-more-list { margin-top: 2px; padding-top: 10px; border-top: 1px solid var(--accent-line); }
.pod-more { display: block; margin-top: 10px; }
/* The typed row while the catalogues are still answering. */
.sg-meta.is-looking { font-style: italic; }
.pod-beyond { font-size: 13.5px; color: var(--muted); }

/* The scan sheet's head: the title, and the flashlight when the camera has one. */
.scan-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.scan-head .scan-title { margin: 0; }
.scan-torch { display: inline-flex; align-items: center; gap: 7px; font-size: 14px; padding: 7px 12px; white-space: nowrap; }
.scan-torch svg { fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linejoin: round; stroke-linecap: round; }
.scan-torch[aria-pressed="true"] { color: var(--ink); background: #ffe58a; border-color: #d9b93e; }

/* Commonplace › Settings: Sources, Colours and LLM as three index cards.
   Each has a line drawing and its name in the book serif. The chosen card is lifted onto the panel colour and wears a
   bookmark ribbon at its top right, the mark the Own and Want buttons use;
   the others sit flat on the paper until hovered. */
.st-subtabs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 16px 0 6px;
}
.st-subtab {
  position: relative;
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  min-width: 0;
  padding: 12px 12px 11px;
  font: inherit; text-align: left;
  color: var(--muted);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.st-subtab svg { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; margin-bottom: 6px; }
.st-subtab-name { font-family: var(--serif); font-size: 18px; line-height: 1.15; color: var(--ink-2); }
.st-subtab .knock { fill: var(--paper); }
.st-subtab[aria-selected="true"] .knock { fill: var(--surface); }
.st-subtab:hover { border-color: var(--accent-line); transform: translateY(-1px); }
.st-subtab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.st-subtab[aria-selected="true"] {
  color: var(--accent-deep);
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: 0 6px 16px rgba(var(--shadow-rgb), 0.08);
}
.st-subtab[aria-selected="true"] .st-subtab-name { color: var(--title); font-weight: var(--title-weight); }
/* The ribbon: a strip of the accent with a notch cut from its foot. */
.st-subtab[aria-selected="true"]::after {
  content: '';
  position: absolute;
  top: -1px; right: 12px;
  width: 12px; height: 18px;
  background: var(--accent);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 72%, 0 100%);
}
@media (prefers-reduced-motion: reduce) { .st-subtab { transition: none; } .st-subtab:hover { transform: none; } }
@media (max-width: 400px) { .st-subtab { padding: 11px 10px 10px; } }

/* An intro of several paragraphs is one intro: no rule between them. */
.settings-panel .st-pane > .tl-intro + .tl-intro { border-top: 0; padding-top: 0; margin-top: 10px; }

/* The Enshittification Resistance badge's artwork starts a few pixels into
   its frame; pull it back so it lines up with the text and the CC badge. */
.st-about img[src*="enshittification-resistance"] { margin-left: -5px; }

/* The arrow on Move to Own / Move to Want and on the swipe bands: drawn, so
   it is heavy everywhere and never turns into an emoji. */
.mv-arrow { width: 1.05em; height: 1.05em; vertical-align: -0.17em; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.lv-band .mv-arrow { width: 1.15em; height: 1.15em; }

/* The intro: paragraphs with room between them, a larger lead-in after the
   heading, and the extras text/intro.md can use — subheadings, lists,
   quotes, a footnote. */
.intro p + p, .intro p + .intro-list, .intro .intro-list + p, .intro blockquote + p { margin-top: 0.85em; }
.intro h1 + p { font-size: 20px; line-height: 1.55; color: var(--ink); }
.intro-sub { margin: 1.6em 0 0.4em; font-family: var(--serif); font-weight: 400; font-size: 22px; line-height: 1.25; color: var(--title); }
.intro-list { margin: 0.85em 0 0; padding-left: 1.2em; font-size: 17px; line-height: 1.65; color: var(--ink-2); }
.intro-list li + li { margin-top: 0.25em; }
.intro-quote { margin: 1.2em 0; padding: 0; font-family: var(--serif); font-size: 23px; line-height: 1.4; font-style: italic; color: var(--title); }
.intro-quote p { margin: 0; font: inherit; color: inherit; }
.intro .intro-note { margin-top: 1.6em; font-size: 14px; color: var(--muted); }
@media (max-width: 640px) { .intro h1 + p { font-size: 18px; } .intro-quote { font-size: 20px; } }

/* The signature at the foot of the intro. */
.intro img[src$="-sig.svg"] { display: block; height: 76px; width: auto; margin: 4px 0 0 2px; }
@media (max-width: 640px) { .intro img[src$="-sig.svg"] { height: 64px; } }

/* Text for screen readers only. */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Watches ------------------------------------------------------------ *
 *
 * A long press on a book in the list opens the sheet; a book on watch wears
 * the clerk's glasses on its cover; the clerk brings the news.
 * ------------------------------------------------------------------ */

.lv-cover-wrap { grid-area: cover; position: relative; display: block; }
.lv-watch {
  position: absolute; left: 50%; top: 34%;
  transform: translate(-50%, -50%);
  display: grid; place-items: center;
  width: 36px; height: 22px;
  background: var(--surface);
  border: 1px solid var(--accent-line);
  border-radius: 11px;
  box-shadow: 0 2px 6px rgba(var(--shadow-rgb), 0.18);
  color: var(--accent-deep);
  pointer-events: none;
}
.settings-panel .lv-watch { width: 40px; height: 24px; }
.glasses-icon { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.lv-watch .glasses-icon { width: 22px; height: 22px; margin-top: -3px; }

.watch-sheet {
  position: fixed; inset: 0; z-index: 95;
  display: grid; place-items: end center;
  padding: 16px;
  background: rgba(var(--shadow-rgb), 0.38);
  opacity: 0; transition: opacity .2s ease;
}
.watch-sheet.is-in { opacity: 1; }
@media (min-width: 640px) { .watch-sheet { place-items: center; } }
.watch-card {
  position: relative;
  width: min(440px, 100%);
  max-height: calc(100dvh - 32px); overflow-y: auto;
  padding: 22px 22px 18px;
  background: var(--surface);
  border-radius: 14px;
  box-shadow: 0 18px 50px rgba(var(--shadow-rgb), 0.28);
  transform: translateY(14px); transition: transform .22s ease;
}
.watch-sheet.is-in .watch-card { transform: none; }
.watch-kicker { display: flex; align-items: center; gap: 8px; margin: 0; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-deep); }
.watch-kicker .glasses-icon { width: 22px; height: 22px; }
.watch-title { margin: 6px 0 0; font-family: var(--serif); font-size: 26px; font-weight: var(--title-weight); color: var(--title); }
.watch-book { margin: 2px 0 0; font-size: 15px; color: var(--muted); }
.watch-group { margin: 18px 0 0; padding: 0; border: 0; }
.watch-group legend { padding: 0; margin-bottom: 6px; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.watch-opt { display: flex; gap: 11px; align-items: flex-start; padding: 9px 0; border-bottom: 1px solid var(--line); cursor: pointer; }
.watch-opt input { margin: 4px 0 0; width: 18px; height: 18px; accent-color: var(--accent); flex: none; }
.watch-opt b { display: block; font-size: 16px; font-weight: 600; color: var(--ink); }
.watch-opt small { display: block; margin-top: 1px; font-size: 13.5px; line-height: 1.4; color: var(--muted); }
.watch-shops { display: flex; flex-wrap: wrap; gap: 6px; }
.watch-shop {
  font: inherit; font-size: 15px; padding: 6px 14px; cursor: pointer;
  color: var(--muted); background: none; border: 1px solid var(--line); border-radius: 999px;
}
.watch-shop[aria-pressed="true"] { color: var(--accent-deep); background: var(--accent-wash); border-color: var(--accent-line); font-weight: 600; }
.watch-shop:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.watch-now { margin: 16px 0 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); min-height: 2.9em; padding-right: 64px; }
.watch-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 14px; padding-right: 64px; }
.watch-save { font-weight: 600; color: var(--surface); background: var(--accent-deep); border-color: var(--accent-deep); }
.watch-save:disabled { opacity: .45; cursor: default; }
.watch-cancel, .watch-drop { font: inherit; font-size: 14px; color: var(--muted); background: none; border: 0; padding: 8px 4px; cursor: pointer; }
.watch-drop:hover { color: var(--amber); }
.watch-clerk {
  position: absolute; right: max(16px, calc(50% - 220px - 8px)); bottom: 16px;
  width: 74px; height: auto; pointer-events: none;
  filter: drop-shadow(0 3px 6px rgba(var(--shadow-rgb), 0.2));
}
@media (min-width: 640px) { .watch-clerk { bottom: calc(50% - 40px); } }

/* The clerk's news on opening the app. */
.watch-notice { z-index: 85; }
.watch-details { margin: 8px 0 0; padding-left: 1.1em; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.watch-open { display: block; margin-top: 10px; font-size: 14px; }
@media (prefers-reduced-motion: reduce) { .watch-sheet, .watch-card { transition: none; } }
.settings-panel .st-sub-first { margin-top: 18px; }
/* A heading straight above an intro needs no rule between them. */
.settings-panel .st-sub + .tl-intro { border-top: 0; padding-top: 0; margin-top: 8px; }

/* A finished step, shown for a moment: calm, with no pulse. */
.field-status.is-done { color: var(--accent-deep); }
.field-status.is-done .field-status-dot { animation: none; background: var(--accent); opacity: 1; }
/* Podcasts and YouTube arriving after the reviews. */
@keyframes panel-arrive { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.is-arriving { animation: panel-arrive .45s ease both; }

/* ================================================================== *
 * TRIAL, October 2026: reviews without cards.
 *
 * No border or box round each review; every one runs the full width of the
 * column, and they are told apart by printer's ornaments instead, a fleuron
 * and a dinkus by turns. The quote and the labels are a step larger, paid
 * for by the padding the cards no longer need.
 *
 * To roll back: delete from this comment to the END TRIAL line. Nothing
 * else in the site depends on it.
 * ================================================================== */

.review,
.reviews-list-quiet .review {
  background: none;
  border: 0;
  border-radius: 0;
  margin-bottom: 0;
}
.review-link { padding: 14px 0 6px; }
.review.is-verifying { background: var(--working-wash); border-radius: var(--radius); }
.review.is-verifying .review-link { padding-inline: 12px; }

/* The ornament between two reviews, part of the second one, so it leaves
   with it when that review is thrown out. Fleuron, dinkus, fleuron... */
.review + .review::before {
  content: '\2766';                         /* ❦ */
  display: block;
  padding-top: 14px;
  text-align: center;
  font-family: var(--serif);
  font-size: 24px;
  line-height: 1;
  color: var(--muted-2);
  font-variant-emoji: text;
}
.review + .review:nth-child(odd)::before {
  content: '*\2003*\2003*';                 /* the dinkus */
  font-size: 18px;
  padding-top: 18px;
  letter-spacing: 0;
}

.review-outlet { font-size: 11px; }
.review-date, .rating-badge { font-size: 12.5px; }
.closing-text { font-size: 22.5px; }
.review-snippet { font-size: 17px; }

@media (max-width: 640px) {
  .review-link { padding: 12px 0 4px; }
  .closing-text { font-size: 18.5px; }
  .review-snippet { font-size: 16px; }
}

/* ================================ END TRIAL ======================== */

/* Podcasts laid out like Ting ting's list: artwork, then the title, then
   length, date and show on one line that is cut short when it runs out. The
   YouTube rows share .pod-row but have no artwork (no YouTube images are
   ever loaded), so all of this hangs off .has-art. */
.pod-row.has-art { display: flex; align-items: flex-start; gap: 12px; }
.pod-row.has-art .pod-link { flex: 1; min-width: 0; display: flex; align-items: flex-start; padding: 4px 0 8px; }
/* The artwork is the favourite switch (app.js podcastRow); a favourite
   wears the headphones on its corner. */
.pod-fav { position: relative; flex: none; margin: 4px 0 0; padding: 0; border: 0; background: none; cursor: pointer; border-radius: 6px; }
.pod-fav:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pod-fav-mark {
  display: none; position: absolute; top: -4px; right: -6px;
  width: 22px; height: 22px; padding: 3px; border-radius: 50%;
  background: var(--surface); box-shadow: 0 0 0 1px var(--line-strong), 0 2px 6px rgba(var(--shadow-rgb), 0.16);
}
.pod-fav.is-fav .pod-fav-mark { display: block; }
.pod-fav-mark svg { display: block; width: 16px; height: 16px; fill: none; stroke: var(--amber); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.pod-row.has-art .pod-art {
  flex: none; display: block; width: 48px; height: 48px; margin-top: 2px;
  border-radius: 6px; object-fit: cover;
  background: var(--surface-sunk); box-shadow: 0 0 0 1px var(--accent-line);
}
.pod-row.has-art .pod-text { flex: 1; min-width: 0; }
.pod-row.has-art .pod-title {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pod-row.has-art .pod-meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The one line that will not wrap must not widen its grid column (and with
   it the page on a phone): grid items default to min-width: auto. */
.podcasts { min-width: 0; }

/* The back of the book, in a card of its own, so it reads as the book's
   description rather than as the first of the reviews. */
.blurb {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px 14px;
}
.blurb-body p { font-size: 20px; }
@media (max-width: 640px) {
  .blurb { padding: 14px 15px 12px; }
  .blurb-body p { font-size: 17.5px; }
}

/* Printed bookmarks (js/bookmarks.js) ----------------------------------- *
 *
 * The picker and the preview live in the watch sheet's overlay. The pages
 * are laid out in millimetres and always black on white, whatever the
 * colour scheme: they are for paper.
 * ------------------------------------------------------------------ */

.st-bookmarks { margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--line); }
.st-bookmarks .tl-intro { margin-top: 4px; }
.st-bookmarks-btn { margin-top: 12px; }

.bm-card { padding-top: 20px; }
.bm-card-wide { width: min(1040px, 100%); }
.bm-close {
  position: absolute; top: 10px; right: 10px; width: 36px; height: 36px;
  border: 0; border-radius: 50%; background: none; cursor: pointer;
  font-size: 24px; line-height: 1; color: var(--muted);
}
.bm-close:hover, .bm-close:focus-visible { background: var(--surface-sunk); color: var(--ink); }
.bm-group legend { display: flex; align-items: baseline; gap: 12px; width: 100%; }
.bm-all {
  margin-left: auto; padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 12px; letter-spacing: 0; text-transform: none; color: var(--accent);
}
.bm-all:hover { color: var(--accent-deep); text-decoration: underline; }
.bm-none { margin: 18px 0 0; color: var(--muted); }
.bm-actions {
  position: sticky; bottom: -18px; z-index: 1;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin: 16px -22px -18px; padding: 14px 22px 18px;
  background: var(--surface);
}
.bm-card-wide .bm-actions { position: static; margin: 14px 0 0; padding: 0; }
.bm-count { font-size: 14px; color: var(--muted); }

.bm-preview { margin-top: 18px; overflow: hidden; }
.bm-pages { width: 297mm; transform-origin: top left; display: grid; gap: 8mm; }

.bm-page {
  width: 297mm; height: 210mm; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  background: #fff; color: #000;
  box-shadow: 0 0 0 1px var(--line), 0 4px 18px rgba(var(--shadow-rgb), 0.12);
  page: bookmarks;
}
.bm-row { display: flex; }
.bm-mark {
  width: 50mm; height: 190mm; box-sizing: border-box;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 9mm 5mm 8mm;
  border: 0.25mm dashed #8a8a8a;             /* the cut lines */
  color: #000;
}
.bm-mark + .bm-mark { border-left: 0; }
.bm-logo { display: block; width: 30mm; height: auto; }
.bm-pitch {
  margin: 6mm 0 0;
  font-family: 'Simonetta', Georgia, serif; font-size: 9pt; line-height: 1.3; color: #000;
  text-wrap: balance;
}
.bm-qr { width: 34mm; margin-top: 4mm; }
.bm-qr svg { display: block; width: 100%; height: auto; }
.bm-title {
  margin: 7mm 0 0;
  font-family: 'Simonetta', Georgia, serif; font-weight: 900;
  font-size: 15pt; line-height: 1.18; color: #000;
  overflow-wrap: anywhere; hyphens: auto;
}
.bm-title.is-mid  { font-size: 13pt; }
.bm-title.is-long { font-size: 11pt; }
.bm-author {
  margin: 2.5mm 0 0;
  font-family: 'Simonetta', Georgia, serif; font-style: italic;
  font-size: 10.5pt; line-height: 1.25; color: #000;
}
.bm-fleuron {
  margin: 5mm 0 0;
  font-family: 'Simonetta', Georgia, serif; font-size: 17pt; line-height: 1; color: #000;
  font-variant-emoji: text;
}
.bm-book { display: block; width: 24mm; height: auto; margin-top: auto; }

@page bookmarks { size: A4 landscape; margin: 0; }

@media print {
  html.bm-printing body > *:not(.bm-sheet) { display: none !important; }
  html.bm-printing, html.bm-printing body { background: #fff !important; margin: 0; padding: 0; }
  html.bm-printing .bm-sheet { position: static; display: block; padding: 0; background: none; opacity: 1; }
  html.bm-printing .bm-card {
    width: auto; max-height: none; overflow: visible; padding: 0;
    background: none; box-shadow: none; border-radius: 0; transform: none;
  }
  html.bm-printing .bm-card > :not(.bm-preview) { display: none !important; }
  html.bm-printing .bm-preview { height: auto !important; margin: 0; overflow: visible; }
  html.bm-printing .bm-pages { transform: none !important; gap: 0; }
  html.bm-printing .bm-page { box-shadow: none; break-after: page; }
  html.bm-printing .bm-page:last-child { break-after: auto; }
  html.bm-printing * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* The Commonplace button as the book drawing, in the accent of the mark
   beside the wordmark, so every scheme recolours both together. */
.settings-launch.is-book { border: 0; padding: 4px; border-radius: var(--radius-s); }
.settings-launch .launch-book { width: 40px; height: 27px; stroke: none; transition: transform .15s ease; }
.settings-launch .lb-cover { fill: var(--accent-vivid); }
.settings-launch .lb-pages { fill: var(--surface); }
.settings-launch.is-book:hover .launch-book,
.settings-launch.is-book[aria-expanded="true"] .launch-book { transform: translateY(-1px) rotate(-4deg); }

/* ================================================================== *
 * TRIAL, October 2026: FLOATING SEARCH BAR
 *
 * The field floats over the page as a card with slightly rounded corners
 * and a shadow all round; the bar behind it is see-through and the fade
 * under it is gone. Sticky at every width, and it peeks: html.bar-tucked
 * (set by the scroll code in js/app.js) slides it up out of view while you
 * scroll down, and it slides back when you scroll up. While a search is
 * reporting progress (html.model-working) it always shows.
 *
 * To roll back: set FLOAT_BAR to false in js/app.js. Nothing here applies
 * without html.float-bar. Delete this block too, to tidy up.
 * ================================================================== */

html.float-bar .searchbar {
  position: sticky;
  top: 0;
  background: none;
  padding-block: 12px 14px;
  transition: transform .32s cubic-bezier(.3, .7, .2, 1);
  will-change: transform;
}
html.float-bar .searchbar::after { display: none; }

html.float-bar .field {
  border-radius: 10px;
  border-color: var(--line);
  box-shadow:
    0 1px 2px rgba(var(--shadow-rgb), 0.06),
    0 6px 24px rgba(var(--shadow-rgb), 0.13);
}
html.float-bar .field:focus {
  border-color: var(--accent);
  box-shadow:
    0 0 0 3px var(--accent-wash),
    0 6px 24px rgba(var(--shadow-rgb), 0.13);
}

/* Out of view: its own height, and the shadow's reach, above the top. */
html.float-bar.bar-tucked:not(.model-working) .searchbar {
  transform: translateY(calc(-100% - 28px));
}

/* The book card's sticky offset follows the bar in and out. */
html.float-bar .book-pane { transition: top .32s cubic-bezier(.3, .7, .2, 1); }

@media (max-width: 640px) {
  html.float-bar .searchbar { padding-block: 8px 10px; }
}

@media (prefers-reduced-motion: reduce) {
  html.float-bar .searchbar, html.float-bar .book-pane { transition: none; }
}

/* ===================================== END FLOATING SEARCH BAR ====== */

/* Podcast and YouTube lists, easier to read: the line under each title in
   the darker ink rather than the muted grey, and both lines larger, most
   of all on a phone, where Simonetta's small x-height bit hardest. */
.pod-title { font-size: 16.5px; line-height: 1.3; }
.pod-meta  { font-size: 13.5px; color: var(--ink-2); }
@media (max-width: 640px) {
  .pod-title { font-size: 18px; }
  .pod-meta  { font-size: 14.5px; margin-top: 4px; }
  .pod-row.has-art .pod-art { width: 54px; height: 54px; }
  .pod-row + .pod-row { padding-top: 12px; }
}

/* The critic's verdict, beside the outlet and date (REVIEWS.verdict). */
.verdict-tag {
  flex: none;
  font-size: 11px;
  letter-spacing: 0.03em;
  line-height: 1;
  padding: 3px 7px;
  border-radius: 999px;
  white-space: nowrap;
  align-self: center;
}
.verdict-tag.is-praise   { background: var(--accent); color: var(--on-ink, #fff); }
.verdict-tag.is-positive { background: var(--accent-wash); color: var(--accent-deep); box-shadow: inset 0 0 0 1px var(--accent-line); }
.verdict-tag.is-negative { background: var(--amber-wash); color: var(--amber); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--amber) 25%, var(--amber-wash)); }
.review-top { flex-wrap: wrap; row-gap: 4px; }

/* "I strongly recommend": the front page, three books and the signature. */
.recs { max-width: 560px; }
.recs-lede { margin: 0 0 22px; font-family: var(--serif); font-weight: 900; font-size: 34px; line-height: 1.15; color: var(--title); }
.recs-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.recs-book {
  display: flex; align-items: center; gap: 16px;
  padding: 12px 16px 12px 12px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  color: inherit; text-decoration: none;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.recs-book:hover { border-color: var(--accent-line); box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.08); transform: translateY(-1px); }
.recs-book:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.recs-cover { flex: none; width: 54px; height: 80px; object-fit: cover; border-radius: 3px; background: var(--surface-sunk); box-shadow: 0 1px 3px rgba(var(--shadow-rgb), 0.18); }
.recs-text { min-width: 0; }
.recs-title { display: block; font-family: var(--serif); font-size: 21px; line-height: 1.25; color: var(--title); }
.recs-author { display: block; margin-top: 3px; font-size: 15px; color: var(--ink-2); }
.intro img.recs-sig[src$="-sig.svg"] { display: block; height: 76px; width: auto; margin: 48px 6px 0 auto; }   /* right, under the cards */
@media (max-width: 640px) {
  .recs-lede { font-size: 28px; }
  .recs-title { font-size: 19px; }
}

/* A Swedish book's English reviews, under the title they were found by. */
.rev-group {
  margin: 34px 0 6px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-family: var(--serif); font-weight: 400; font-size: 22px; line-height: 1.25;
  color: var(--title);
}
.rev-group em { font-style: italic; }
.review-items + .rev-group { margin-top: 30px; }

/* The awards the book won, at the foot of the clerk's summary. */
/* Alone, when there was nothing to sum up: no rule above it. */
.clerk-text:empty + .clerk-awards { margin-top: 0; padding-top: 0; border-top: 0; }
.clerk-awards-line { display: block; }
.clerk-awards-credit { display: block; margin-top: 4px; font-family: var(--sans); font-style: normal; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.clerk-awards-credit a { color: var(--accent-deep); }
.clerk-awards {
  margin: 10px 0 0;
  padding-top: 8px;
  border-top: 1px solid var(--accent-line);
  font-family: var(--serif);
  font-size: 16px;
  line-height: 1.4;
  font-style: italic;
  color: var(--accent-deep);
}
