/* ===========================================================================
   GREENLIGHT GUIDES — the storefront stylesheet.

   Hand-written and never regenerated. build_site.py rewrites everything else
   under site/; it does not touch this file or store.js.

   THE DESIGN ARGUMENT, IN ONE LINE
   Everybody who buys here is over sixty, so the type is the design. This site
   is set at 125% of the browser's own base size — about 20px where a normal
   site sets 16 — and it never goes below 17px anywhere, for anything,
   including the small print. That is the whole risk of the thing. It will look
   slightly too big on a designer's monitor and exactly right on the machine it
   is for.

   TWO GROUNDS, AND THE SWITCH MEANS SOMETHING
   Paper is where you read: the cream the paperback is actually printed on, and
   the ground of all thirty covers. Teal is where the imprint speaks: the panel
   colour off those same covers, used for the pages where the shop makes a
   claim rather than shows a book — the nine hundred days, the two-line pair,
   the free dictionary. Sold on paper, argued on teal.

   WHERE THE COLOUR COMES FROM
   Not a mood board. Sampled across the thirty finished covers, the ground is
   #F8F0E8, the ink #283030, the teal #085058 and the amber #F0B048. Those four,
   rounded to a system, are the palette. Every pairing that carries text was
   solved to the floor — 4.5:1 for text, 3.0:1 for a border or a mark that
   carries meaning — and site_audit.py re-checks all of them on every run.

   WHERE THE SHAPES COME FROM
   The interior illustrations have one vocabulary: flat fills inside a heavy
   charcoal outline, corners generously rounded, no gradients, no bevels.
   Cards, buttons and panels are drawn the same way, so the furniture of the
   shop belongs to the world of the pages it is selling. Covers get the only
   soft shadow, because a cover is a physical object and the rest of this is not.
   ========================================================================= */

@import url("https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wdth,wght@12..96,75..100,400..800&family=Literata:ital,opsz,wght@0,7..72,400..700;1,7..72,400..600&family=Instrument+Sans:wght@400..700&display=swap");

:root {
  /* --- the paper ground ------------------------------------------------- */
  --paper:      #F7F0E4;
  --paper-hi:   #FDFAF4;
  --shelf:      #E9DEC7;   /* the board a cover stands on. Cream needs an edge */
  --rule:       #D5C6A9;
  --rule-soft:  #E3D7BE;
  --ink:        #23292B;   /* 12.4:1 on paper */
  --ink-2:      #58625F;   /*  5.3:1 on paper — secondary, never body copy */
  --paper-edge: #95886F;   /*  3.0:1 — interactive borders on paper */

  /* --- the teal ground -------------------------------------------------- */
  --teal:       #0C4E53;   /*  7.8:1 on paper */
  --teal-deep:  #073539;
  --teal-hi:    #13686F;
  --teal-wash:  #DCE7E2;
  --on-teal:    #F4EFE6;   /*  7.4:1 on teal */
  --on-teal-2:  #B9CDCB;   /*  4.8:1 on teal — muted label */
  --teal-edge:  #6E9A99;   /*  3.0:1 on teal — borders on teal */

  /* --- the two accents --------------------------------------------------- */
  --amber:      #EFB04A;   /* a ground and a mark, never type on paper */
  --amber-deep: #B87E1C;
  --amber-wash: #FAECD2;
  --coral:      #E0603F;   /* a graphic mark, never type */
  --coral-ink:  #A93A22;   /*  5.3:1 on paper — the one accent carrying words */

  /* --- three type roles -------------------------------------------------- */
  --display: "Bricolage Grotesque", "Archivo", "Helvetica Neue", Arial, sans-serif;
  --body:    "Literata", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --ui:      "Instrument Sans", "Segoe UI", system-ui, -apple-system, sans-serif;

  /* One rem is 20px here, not 16, so every value below is a quarter larger
     than the same number would be on an ordinary site. */
  --t-xs:   0.80rem;   /* 16px — the floor. Labels only */
  --t-sm:   0.90rem;   /* 18px */
  --t-base: 1rem;      /* 20px */
  --t-md:   1.15rem;
  --t-lg:   1.30rem;
  --t-xl:   clamp(1.15rem, 2.2vw, 1.5rem);
  --t-2xl:  clamp(1.45rem, 3.4vw, 2.1rem);
  --t-3xl:  clamp(1.70rem, 4.6vw, 2.7rem);
  --t-hero: clamp(2.00rem, 6.0vw, 3.6rem);

  --measure: 62ch;
  --page:    1200px;
  --gut:     clamp(20px, 4.5vw, 44px);
  --step:    clamp(48px, 7vw, 96px);

  --edge:      2.5px solid var(--ink);
  --edge-thin: 1.5px solid var(--ink);
  --round:     14px;
  --round-sm:  9px;
  --lift:      0 10px 22px -12px rgba(35, 41, 43, .45);

  /* The ground sets these; nothing else may. See "no ground rule targets a
     bare element" in the traps below. */
  --bg: var(--paper);
  --fg: var(--ink);
  --fg-2: var(--ink-2);
  --link: var(--teal);
  --border: var(--paper-edge);
  --card: var(--paper-hi);
}

/* Teal ground. It redefines tokens and nothing else — no descendant element
   selectors. A rule like `.on-teal a { color: … }` outranks every link class
   on the page, including the wordmark, which is exactly the bug the schema
   warns about. */
.on-teal {
  --bg: var(--teal);
  --fg: var(--on-teal);
  --fg-2: var(--on-teal-2);
  --link: var(--amber);
  --border: var(--teal-edge);
  --card: var(--teal-deep);
  background: var(--bg);
  color: var(--fg);
}

/* ===========================================================================
   RESET AND BASE
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }

html {
  /* The risk, in one declaration. A percentage rather than a pixel value so a
     reader who has already raised their browser's default text size keeps that
     increase on top of this one. */
  font-size: 125%;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--t-base);
  line-height: 1.65;
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  /* No `text-rendering: optimizeLegibility` here on purpose. It forces kerning
     and ligature lookups over the whole document — harmless at 14 KB, a visible
     stall at 50 KB of text in two variable fonts. Browsers kern properly
     without it. */
}

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.022em;
  margin: 0 0 .5em;
  text-wrap: balance;
  color: var(--fg);
}

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

a { color: var(--link); text-underline-offset: .18em; text-decoration-thickness: .08em; }

/* Width and height attributes on an <img> defeat aspect-ratio unless the reset
   also sets height:auto. Keep the attributes — they are what reserve the space
   and stop the page jumping — and fix it here. */
img { max-width: 100%; height: auto; display: block; }

ul, ol { margin: 0 0 1em; padding-left: 1.3em; }
li { margin-bottom: .4em; }
hr { border: 0; border-top: 1.5px solid var(--rule); margin: var(--step) 0; }
strong, b { font-weight: 700; }
::selection { background: var(--amber); color: var(--ink); }

/* Every figure on the site is set in the utility face with tabular numerals,
   so prices, page counts, day numbers and durations line up in a column. */
.num, .price, .particulars td, .ladder td, .ladder th, input[type="number"] {
  font-family: var(--ui);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

:focus-visible { outline: 3px solid var(--coral-ink); outline-offset: 3px; border-radius: 3px; }
.on-teal :focus-visible { outline-color: var(--amber); }

.skip {
  position: absolute; left: -9999px;
  background: var(--ink); color: var(--paper);
  padding: .7em 1.2em; z-index: 99; font-family: var(--ui); font-weight: 600;
}
.skip:focus { left: 12px; top: 12px; }

.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ===========================================================================
   MOTION — CSS only, and already finished if it never runs
   ========================================================================= */

@keyframes rise { from { opacity: 0; transform: translateY(10px); } }

.rise {
  /* `backwards` matters: without it the element is at its final state before
     the delay elapses, and with it the page is still correct if animations are
     switched off entirely. Nothing here is gated on a class a script adds. */
  animation: rise .5s ease-out backwards;
}
.rise-1 { animation-delay: .05s; }
.rise-2 { animation-delay: .12s; }
.rise-3 { animation-delay: .19s; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
}

/* ===========================================================================
   LAYOUT
   ========================================================================= */

.wrap { max-width: var(--page); margin: 0 auto; padding: 0 var(--gut); }
.wrap-narrow { max-width: 820px; margin: 0 auto; padding: 0 var(--gut); }

section { padding-block: var(--step); }
section + section { padding-top: 0; }
.on-teal + section, section.on-teal { padding-top: var(--step); }

.prose { max-width: var(--measure); }
.prose p { margin-bottom: 1.15em; }
.prose p:first-child { font-size: var(--t-md); }

.eyebrow {
  font-family: var(--ui); font-size: var(--t-xs); font-weight: 600;
  letter-spacing: .13em; text-transform: uppercase; color: var(--fg-2);
  margin: 0 0 .9em;
}
.eyebrow--teal { color: var(--teal); }

.head { margin-bottom: calc(var(--step) * .45); }
.head h1, .head h2 { font-size: var(--t-2xl); margin-bottom: .3em; }
.head h1 { font-size: var(--t-3xl); }
.head p { max-width: var(--measure); font-size: var(--t-md); color: var(--fg-2); }
.head::after {
  content: ""; display: block; height: 3px; background: currentColor;
  margin-top: 1.1rem; max-width: 96px; opacity: .85;
}
.head--plain::after { display: none; }

/* Any track that can hold a table, a <pre> or a long unbroken string needs an
   explicit zero floor: `1fr` means `minmax(auto, 1fr)`, whose floor is the
   content's min-content width, and one wide table pushes the page sideways. */
.split { display: grid; gap: clamp(24px, 3.5vw, 48px); align-items: start; }
@media (min-width: 860px) { .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.split--centre { align-items: center; }
.split .prose { max-width: none; }

/* ===========================================================================
   MASTHEAD
   ========================================================================= */

.masthead { border-bottom: var(--edge-thin); background: var(--paper); position: sticky; top: 0; z-index: 40; }
.masthead .wrap {
  display: flex; align-items: center; gap: clamp(12px, 2vw, 26px);
  min-height: 72px; flex-wrap: wrap; padding-block: 8px;
}

.wordmark {
  font-family: var(--display); font-weight: 800; font-size: var(--t-base);
  letter-spacing: -.01em; text-transform: uppercase; color: var(--ink);
  text-decoration: none; display: inline-flex; align-items: center; gap: .5em;
  line-height: 1;
}
/* The greenlight itself. One dot, teal, and the only literal thing on the
   site. It is also the list bullet further down, so the mark means "go ahead"
   in both places. */
.wordmark::before {
  content: ""; width: .72em; height: .72em; border-radius: 50%;
  background: var(--teal); flex: none;
}

.nav { display: flex; align-items: center; gap: clamp(10px, 1.8vw, 24px); flex-wrap: wrap; }
.nav a {
  font-family: var(--ui); font-weight: 500; font-size: var(--t-sm);
  color: var(--ink); text-decoration: none; white-space: nowrap;
  padding: .55em 0; border-bottom: 3px solid transparent;
}
.nav a:hover, .nav a[aria-current="page"] { border-bottom-color: var(--teal); color: var(--teal); }

.basket-link {
  margin-left: auto; font-family: var(--ui); font-size: var(--t-sm); font-weight: 600;
  border: 1.5px solid var(--paper-edge); border-radius: var(--round-sm);
  padding: .45em .9em; background: var(--paper-hi); color: var(--ink);
  text-decoration: none; display: inline-flex; align-items: center; gap: .5em;
  min-height: 46px;
}
.basket-link:hover { border-color: var(--ink); color: var(--ink); }
.basket-link b {
  font-variant-numeric: tabular-nums; background: var(--teal); color: #fff;
  border-radius: 999px; min-width: 1.7em; text-align: center; padding: 0 .35em;
}

@media (max-width: 1080px) {
  .masthead .wrap { min-height: 0; }
  .nav { order: 3; flex-basis: 100%; border-top: 1.5px solid var(--rule-soft); padding-top: 4px; }
}

/* ===========================================================================
   BUTTONS
   ========================================================================= */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55em;
  font-family: var(--ui); font-weight: 600; font-size: var(--t-base);
  line-height: 1.2; text-decoration: none;
  padding: .78em 1.5em; min-height: 56px;      /* a real target, on a real hand */
  border: var(--edge); border-radius: var(--round);
  background: var(--paper-hi); color: var(--ink);
  cursor: pointer; text-align: center;
  transition: background .14s ease, color .14s ease;
}
.btn:hover { background: var(--amber-wash); color: var(--ink); }
.btn--go { background: var(--teal); border-color: var(--teal-deep); color: #fff; }
.btn--go:hover { background: var(--teal-hi); color: #fff; }
.btn--go.is-added { background: var(--amber); border-color: var(--amber-deep); color: var(--ink); }
.btn--quiet { border-color: var(--border); background: transparent; color: var(--fg); }
.btn--quiet:hover { border-color: var(--fg); background: color-mix(in srgb, var(--fg) 8%, transparent); }
.btn[disabled], .btn[aria-disabled="true"] {
  border-color: var(--rule); color: var(--ink-2); background: transparent; cursor: not-allowed;
}
.btn-row { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 1.6rem; }

/* ===========================================================================
   THE SIGNATURE — nine hundred days
   ---------------------------------------------------------------------------
   Thirty guides down, thirty days across. Every one of the 900 cells is a real
   fifteen-minute action written for that book, and the grid is the only object
   on the site that shows the whole series at once. It is the shop's index and
   the series' argument in one: a row is a book, a column is a day, and the
   shape of it is what the imprint sells. Spend the boldness here, nowhere else.
   ========================================================================= */

.days {
  display: grid;
  grid-template-columns: minmax(0, 11em) minmax(0, 1fr);
  gap: 4px clamp(10px, 1.6vw, 20px);
  align-items: center;
  font-family: var(--ui);
}
.days-head { font-size: var(--t-xs); letter-spacing: .1em; text-transform: uppercase; color: var(--fg-2); }
.days-title {
  font-size: var(--t-sm); line-height: 1.2; text-align: right;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.days-title a { color: var(--fg); text-decoration: none; }
.days-title a:hover { text-decoration: underline; }
.days-row { display: grid; grid-template-columns: repeat(30, minmax(0, 1fr)); gap: 2px; }
.days-row span {
  aspect-ratio: 1; border-radius: 2px; background: var(--teal-hi);
  animation: rise .4s ease-out backwards;
}
/* Four weeks and two rest days: the shape every plan actually has. */
.days-row span:nth-child(7n) { background: var(--amber); }
.days-row a { display: contents; }
.days-legend {
  display: flex; flex-wrap: wrap; gap: .5em 1.4em; margin-top: 1.6rem;
  font-family: var(--ui); font-size: var(--t-sm); color: var(--fg-2);
}
.days-legend i { display: inline-block; width: .9em; height: .9em; border-radius: 2px; margin-right: .5em; }
@media (max-width: 700px) {
  .days { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .days-title { text-align: left; margin-top: .7em; }
  .days-head { display: none; }
}

/* One day, quoted in full. */
.day-quote {
  border-left: 5px solid var(--amber); padding-left: 1.1em;
  font-size: var(--t-md); max-width: var(--measure);
}
.day-quote b { font-family: var(--ui); display: block; font-size: var(--t-sm); color: var(--fg-2); }

/* The per-book plan, published in full. */
.plan { list-style: none; padding: 0; margin: 0; counter-reset: day; }
.plan li {
  counter-increment: day; display: flex; gap: 1em; align-items: baseline;
  padding: .6em 0; border-bottom: 1.5px solid var(--rule-soft); margin: 0;
}
.plan li::before {
  content: counter(day); font-family: var(--ui); font-variant-numeric: tabular-nums;
  font-weight: 700; font-size: var(--t-sm); color: var(--teal);
  flex: none; min-width: 2.2em;
}

/* ===========================================================================
   THE SHELF — covers aligned by height, the way a shelf holds them
   ========================================================================= */

.shelf {
  --shelf-h: 168px; --board: 4px;
  background: var(--shelf); border: var(--edge-thin); border-radius: var(--round);
  padding: clamp(24px, 3.4vw, 40px) clamp(18px, 3vw, 32px);
}
/* A grid, not a wrapping flex row, so the rows are uniform however many covers
   there are. Each cover draws the piece of board beneath it and the pieces meet
   across the gaps, which leaves the last row's board stopping where the books
   stop — which is what a half-full shelf looks like. */
.shelf-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(94px, 1fr));
  gap: calc(var(--shelf-h) * .22) clamp(10px, 1.4vw, 18px);
  align-items: end; justify-items: center;
}
.shelf-grid a { display: block; line-height: 0; position: relative; }
.shelf-grid a::after {
  content: ""; position: absolute;
  left: calc(clamp(10px, 1.4vw, 18px) / -2 - 1px);
  right: calc(clamp(10px, 1.4vw, 18px) / -2 - 1px);
  bottom: calc(var(--board) * -2.5); height: var(--board); background: var(--ink);
}
.shelf-grid img {
  height: var(--shelf-h); width: auto;
  border: var(--edge-thin); border-radius: 2px;
  box-shadow: 0 6px 14px -8px rgba(35, 41, 43, .5);
  transition: transform .16s ease;
}
.shelf-grid a:hover img, .shelf-grid a:focus-visible img { transform: translateY(-7px); }
@media (max-width: 700px) {
  .shelf { --shelf-h: 118px; }
  .shelf-grid { grid-template-columns: repeat(auto-fill, minmax(70px, 1fr)); }
}

/* ===========================================================================
   CARDS
   ========================================================================= */

.grid {
  display: grid; gap: clamp(20px, 2.6vw, 34px);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), minmax(0, 1fr)));
}

.card {
  display: flex; flex-direction: column;
  background: var(--paper-hi); border: var(--edge); border-radius: var(--round);
  overflow: hidden;
}
.card-cover {
  display: block; background: var(--shelf); border-bottom: var(--edge);
  padding: 22px 22px 0; text-align: center; line-height: 0;
}
.card-cover img {
  height: 250px; width: auto; margin: 0 auto;
  border: var(--edge-thin); border-radius: 2px;
  box-shadow: 0 8px 16px -9px rgba(35, 41, 43, .55);
  transition: transform .16s ease;
}
.card:hover .card-cover img { transform: translateY(-5px); }
.card-body { padding: clamp(18px, 2.2vw, 26px); display: flex; flex-direction: column; flex: 1; }
.card-shelf {
  font-family: var(--ui); font-size: var(--t-xs); font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase; color: var(--teal); margin: 0 0 .7em;
}
.card h3 { font-size: var(--t-lg); margin-bottom: .35em; }
.card h3 a { color: var(--ink); text-decoration: none; }
.card h3 a:hover { color: var(--teal); text-decoration: underline; }
.card-sub { font-size: var(--t-sm); color: var(--ink-2); margin-bottom: .9em; line-height: 1.45; }
.card-hook { font-size: var(--t-base); margin-bottom: 1.2em; }
.card-foot {
  margin-top: auto; padding-top: 1em; border-top: 1.5px solid var(--rule);
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
}
.card-price { font-family: var(--ui); font-variant-numeric: tabular-nums; font-weight: 700; font-size: var(--t-md); color: var(--teal); }
.card-foot .btn { min-height: 48px; padding: .5em 1.1em; font-size: var(--t-sm); margin-left: auto; }
@media (max-width: 620px) { .card-cover img { height: 210px; } }

/* ===========================================================================
   THE PAIR — what it is for, what it will not do
   ---------------------------------------------------------------------------
   Both halves at the same size, in the same face, in boxes of equal weight. In
   a category built on overpromising, printing the limit as large as the promise
   is the argument, and shrinking the second box would undo it.
   ========================================================================= */

.pair { display: grid; gap: 20px; }
@media (min-width: 760px) { .pair { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.pair-half {
  border: var(--edge); border-radius: var(--round);
  padding: clamp(20px, 2.6vw, 32px); font-size: var(--t-base); line-height: 1.55;
}
.pair-for { background: var(--teal); border-color: var(--teal-deep); color: var(--on-teal); }
.pair-not { background: var(--paper-hi); color: var(--ink); }
.pair-half h2, .pair-half h3 {
  font-family: var(--display); font-weight: 800; font-size: var(--t-lg);
  letter-spacing: -.02em; margin-bottom: .55em; line-height: 1.15;
}
.pair-for h2, .pair-for h3 { color: #fff; }
.pair-not h2, .pair-not h3 { color: var(--coral-ink); }
.pair-half p { margin: 0; }

/* ===========================================================================
   A VOLUME PAGE
   ========================================================================= */

.crumbs { font-family: var(--ui); font-size: var(--t-sm); color: var(--ink-2); padding-top: 1.6rem; margin: 0; }
.crumbs a { color: var(--ink-2); }
.crumbs span { padding: 0 .45em; }

.book-top { padding-top: 1.8rem; }
@media (min-width: 900px) {
  .book-top .wrap { display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: var(--step); align-items: start; }
  .book-cover { position: sticky; top: 100px; }
}
.book-cover img { width: 100%; border: var(--edge-thin); border-radius: 3px; box-shadow: var(--lift); }
.book-cover figcaption { font-family: var(--ui); font-size: var(--t-xs); color: var(--ink-2); margin-top: .9em; text-align: center; }
.book-title { font-size: var(--t-3xl); margin-bottom: .22em; }
.book-sub { font-size: var(--t-xl); line-height: 1.3; color: var(--ink-2); font-weight: 400; margin: 0 0 1.1rem; max-width: 30ch; }
.book-hook { font-size: var(--t-md); border-left: 5px solid var(--amber); padding-left: 1.1em; margin: 0 0 1.8rem; max-width: var(--measure); }

/* The three formats, priced, each with its own add-to-basket. */
.formats { list-style: none; margin: 0 0 1.5rem; padding: 0; }
.formats li {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4em 1em;
  padding: 1em 0; border-top: 1.5px solid var(--rule); margin: 0;
}
.formats li:last-child { border-bottom: 1.5px solid var(--rule); }
.fmt-name { font-family: var(--ui); font-weight: 700; font-size: var(--t-base); min-width: 7.5em; }
.fmt-price { font-family: var(--ui); font-variant-numeric: tabular-nums; font-weight: 700; font-size: var(--t-md); color: var(--teal); min-width: 4em; }
.fmt-note { font-size: var(--t-sm); color: var(--ink-2); flex-basis: 100%; margin: 0; }
.formats .btn { min-height: 48px; padding: .5em 1.2em; font-size: var(--t-sm); margin-left: auto; }
.fmt-blocked { font-family: var(--ui); font-size: var(--t-sm); color: var(--coral-ink); margin-left: auto; font-weight: 600; }

.contents { display: grid; gap: var(--step) clamp(28px, 4vw, 60px); }
@media (min-width: 800px) { .contents { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); } }

.chapters { list-style: none; counter-reset: ch; padding: 0; margin: 0; }
.chapters li {
  counter-increment: ch; display: flex; gap: 1em; align-items: baseline;
  padding: .9em 0; border-bottom: 1.5px solid var(--rule-soft); margin: 0;
}
.chapters li::before {
  content: counter(ch, decimal-leading-zero);
  font-family: var(--ui); font-variant-numeric: tabular-nums; font-weight: 700;
  font-size: var(--t-sm); color: var(--teal); flex: none; min-width: 2.2em;
}
.chapters b { display: block; font-size: var(--t-md); font-weight: 600; margin-bottom: .15em; }
.chapters span { display: block; font-size: var(--t-sm); color: var(--ink-2); line-height: 1.5; }

.backmatter { list-style: none; padding: 0; margin: 0; }
.backmatter li {
  padding: .55em 0 .55em 1.6em; position: relative; font-size: var(--t-base);
  border-bottom: 1.5px solid var(--rule-soft); margin: 0;
}
.backmatter li::before {
  content: ""; position: absolute; left: 0; top: 1.05em;
  width: .6em; height: .6em; border-radius: 50%; background: var(--teal);
}

.pages-grid { display: grid; gap: clamp(20px, 3vw, 38px); grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), minmax(0, 1fr))); }
@media (min-width: 900px) { .pages-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.pages-grid figure { margin: 0; }
.pages-grid img { width: 100%; border: var(--edge-thin); border-radius: var(--round-sm); background: var(--paper-hi); }
.pages-grid figcaption { font-family: var(--ui); font-size: var(--t-xs); color: var(--ink-2); margin-top: .7em; line-height: 1.45; }

/* Tables. Any of these can be wider than its track on a phone, so each one
   scrolls inside its own box rather than pushing the page sideways. */
.table-scroll { overflow-x: auto; }
.particulars, .ladder { width: 100%; border-collapse: collapse; font-size: var(--t-base); }
.particulars th, .particulars td, .ladder th, .ladder td {
  text-align: left; padding: .8em .8em .8em 0; border-bottom: 1.5px solid var(--rule-soft); vertical-align: top;
}
.particulars th { font-family: var(--ui); font-weight: 600; color: var(--ink-2); width: 12em; font-size: var(--t-sm); }
.ladder thead th { font-family: var(--ui); font-size: var(--t-sm); color: var(--ink-2); border-bottom-color: var(--rule); }
.ladder td b { font-variant-numeric: tabular-nums; }

/* The set row is the offer worth reading twice: it is the only row that also
   carries the ebook and the audiobook, so it is the only row with a ground. */
.ladder-set td { background: var(--amber-wash); border-bottom: none; }
.ladder-set td:first-child { border-radius: var(--round-sm) 0 0 var(--round-sm); }
.ladder-set td:last-child { border-radius: 0 var(--round-sm) var(--round-sm) 0; }
.ladder-set span {
  display: block; font-family: var(--ui); font-size: var(--t-sm);
  color: var(--ink-2); margin-top: .2em;
}

/* The set's own line, which is where the money on this bill actually goes. */
.line--set { background: var(--amber-wash); border-radius: var(--round-sm); padding-inline: 1rem; }

/* A basket line the set has already paid for. Not a strikethrough: there is no
   earlier price to cross out, the line simply costs nothing. */
.line-free { color: var(--teal); font-family: var(--ui); font-size: var(--t-base); }

/* A link in the Spanish footer whose page is written in English. Said
   once, quietly, rather than as a badge: it is a fact about the target,
   not a warning. */
.en-note { font-size: var(--t-xs); opacity: .78; }

.terms { margin: 0; }
.terms > div { padding: 1em 0; border-bottom: 1.5px solid var(--rule-soft); display: grid; gap: .15em .5em; }
@media (min-width: 780px) { .terms > div { grid-template-columns: minmax(0, 15em) minmax(0, 1fr); gap: 1.5em; } }
.terms dt { font-family: var(--display); font-weight: 700; font-size: var(--t-md); line-height: 1.2; margin: 0; }
.terms dd { margin: 0; font-size: var(--t-base); }
.terms .from { font-family: var(--ui); font-size: var(--t-sm); color: var(--ink-2); }

.letter { font-size: var(--t-2xl); margin: var(--step) 0 .4em; padding-bottom: .1em; border-bottom: 3px solid var(--fg); scroll-margin-top: 96px; }
.letter:first-of-type { margin-top: 1rem; }

.editions { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 12px; }
.editions a {
  display: flex; align-items: center; gap: .7em;
  border: 1.5px solid var(--border); border-radius: var(--round-sm);
  padding: .6em 1em; text-decoration: none; color: var(--fg);
  font-family: var(--ui); font-size: var(--t-sm); background: var(--card); min-height: 52px;
}

/* ===========================================================================
   THE SHOP FILTER
   ========================================================================= */

.filters {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  padding-bottom: 1.6rem; border-bottom: 1.5px solid var(--rule); margin-bottom: var(--step);
}
.filters .lab { font-family: var(--ui); font-size: var(--t-sm); font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-2); margin-right: .5em; }
.chip {
  font-family: var(--ui); font-size: var(--t-sm); font-weight: 500;
  border: 1.5px solid var(--paper-edge); border-radius: 999px; background: var(--paper-hi);
  padding: .5em 1.05em; min-height: 46px; cursor: pointer; color: var(--ink);
  display: inline-flex; align-items: center;
}
.chip:hover { background: var(--amber-wash); }
.chip[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.count { font-family: var(--ui); font-size: var(--t-sm); color: var(--ink-2); margin-left: auto; }
nav.filters { gap: 8px; }
nav.filters .chip { min-width: 46px; justify-content: center; }

/* ===========================================================================
   SHELF BLOCKS, FACTS, PANELS, ART
   ========================================================================= */

.shelf-block { padding: clamp(24px, 3vw, 38px) 0; border-top: 1.5px solid var(--rule); }
.shelf-block:first-of-type { border-top: 0; }
@media (min-width: 860px) { .shelf-block { display: grid; grid-template-columns: minmax(0, 20em) minmax(0, 1fr); gap: clamp(28px, 4vw, 56px); } }
.shelf-block h3 { font-size: var(--t-xl); margin-bottom: .4em; }
.shelf-block h3 a { color: var(--fg); text-decoration: none; }
.shelf-block h3 a:hover { color: var(--teal); text-decoration: underline; }
.shelf-block .blurb { font-size: var(--t-sm); color: var(--fg-2); margin: 0; }
.mini { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-end; }
.mini a { line-height: 0; }
.mini img { height: 148px; width: auto; border: var(--edge-thin); border-radius: 2px; box-shadow: 0 6px 13px -8px rgba(35, 41, 43, .5); transition: transform .16s ease; }
.mini a:hover img, .mini a:focus-visible img { transform: translateY(-6px); }

.facts { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), minmax(0, 1fr))); }
.fact { border: var(--edge); border-radius: var(--round); padding: clamp(18px, 2.2vw, 26px); background: var(--paper-hi); }
.fact b { display: block; font-family: var(--display); font-weight: 800; font-size: var(--t-2xl); line-height: 1; letter-spacing: -.03em; margin-bottom: .18em; font-variant-numeric: tabular-nums; }
.fact span { font-family: var(--ui); font-size: var(--t-sm); color: var(--ink-2); }
.fact:nth-child(1) { background: var(--teal-wash); }
.fact:nth-child(2) { background: var(--amber-wash); }

.panel { border: var(--edge); border-radius: var(--round); padding: clamp(22px, 3vw, 38px); background: var(--card); }
.panel--amber { background: var(--amber-wash); }

.art img { width: 100%; border: var(--edge-thin); border-radius: var(--round); background: var(--paper-hi); }
.art--banner { margin: 0 0 var(--step); display: block; }

/* The standing disclaimer. Set at body size on purpose: a limit printed in
   small grey type is a limit somebody hopes you will not read. */
.disclaimer { border-top: 3px solid var(--fg); border-bottom: 3px solid var(--fg); padding: clamp(20px, 2.6vw, 30px) 0; margin: var(--step) 0 0; }
.disclaimer p { max-width: var(--measure); margin: 0; font-size: var(--t-base); }
.disclaimer .eyebrow { color: var(--coral-ink); }

/* A gap the project has not closed yet, printed rather than hidden. */
.todo {
  font-family: var(--ui); font-size: var(--t-sm);
  background: repeating-linear-gradient(45deg, var(--amber-wash) 0 12px, var(--paper) 12px 24px);
  border: 1.5px dashed var(--amber-deep); border-radius: var(--round-sm);
  padding: .8em 1em; color: var(--ink); display: inline-block;
}

/* ===========================================================================
   THE FREE READ
   ========================================================================= */

.read { max-width: var(--measure); margin: 0 auto; }
.read h2 { font-size: var(--t-xl); margin: 2.2em 0 .6em; }
.read h2:first-child { margin-top: 0; }
.read p { font-size: var(--t-md); line-height: 1.72; margin-bottom: 1.15em; }
.read-end { margin-top: var(--step); border-top: 3px solid var(--ink); padding-top: clamp(22px, 3vw, 34px); }

/* ===========================================================================
   THE BASKET
   ========================================================================= */

.line { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 1em; align-items: center; padding: 1.1em 0; border-bottom: 1.5px solid var(--rule-soft); }
.line-what b { display: block; font-size: var(--t-md); }
.line-what span { font-family: var(--ui); font-size: var(--t-sm); color: var(--ink-2); }
.line-qty input { width: 5em; min-height: 52px; font: inherit; font-size: var(--t-base); padding: .4em .5em; border: 1.5px solid var(--paper-edge); border-radius: var(--round-sm); background: var(--paper); color: var(--ink); text-align: center; }
.line-cost { font-family: var(--ui); font-variant-numeric: tabular-nums; font-weight: 700; font-size: var(--t-md); text-align: right; min-width: 6em; }
.line-cost span { display: block; font-weight: 400; font-size: var(--t-sm); color: var(--ink-2); }
.empty { font-size: var(--t-md); padding: 2em 0; }

.totals { margin-top: 1.6rem; font-family: var(--ui); font-variant-numeric: tabular-nums; }
.totals div { display: flex; justify-content: space-between; gap: 2em; padding: .55em 0; font-size: var(--t-base); }
.totals div:last-child { border-top: 3px solid var(--ink); margin-top: .5em; padding-top: .8em; font-size: var(--t-lg); font-weight: 700; }

.field { display: block; margin: 1.4rem 0; font-family: var(--ui); }
.field span { display: block; font-size: var(--t-sm); font-weight: 600; margin-bottom: .5em; }
.field select, .field input {
  width: 100%; max-width: 24em; min-height: 56px; font: inherit; font-size: var(--t-base);
  padding: .55em .7em; border: var(--edge); border-radius: var(--round-sm);
  background: var(--paper); color: var(--ink);
}

/* ===========================================================================
   FOOTER
   ========================================================================= */

.foot { border-top: var(--edge-thin); margin-top: var(--step); padding: var(--step) 0 3rem; background: var(--shelf); }
.foot-cols { display: grid; gap: clamp(24px, 3vw, 48px); grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), minmax(0, 1fr))); margin-bottom: var(--step); }
.foot h4 { font-family: var(--ui); font-size: var(--t-xs); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-2); margin-bottom: 1em; }
.foot ul { list-style: none; padding: 0; margin: 0; }
.foot li { margin-bottom: .55em; }
.foot a { color: var(--ink); font-size: var(--t-sm); font-family: var(--ui); }
.foot-fine { border-top: 1.5px solid var(--rule); padding-top: 1.8rem; font-family: var(--ui); font-size: var(--t-sm); color: var(--ink-2); display: flex; flex-wrap: wrap; gap: .6em 1.6em; }

/* ===========================================================================
   PRINT
   ========================================================================= */

@media print {
  .masthead, .foot, .btn-row, .filters, .basket-link { display: none; }
  body { background: #fff; font-size: 11pt; }
  a::after { content: " (" attr(href) ")"; font-size: 9pt; color: #555; }
}

/* --- the words to use -------------------------------------------------- */

/* minmax(0, 1fr) on BOTH the one-column and the two-column case. A grid item
   defaults to min-width:auto, so a single long token inside a card -- these
   quote real sentences with bracketed placeholders in them -- makes the track
   as wide as the token and pushes the page sideways. The audit caught this at
   390px on three pages. */
.frames { display: grid; gap: 22px; margin-top: 1.4rem; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) { .frames { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.frame {
  border: var(--edge-thin); border-radius: var(--round);
  background: var(--card); padding: 1.5rem 1.6rem 1.3rem;
  display: flex; flex-direction: column; gap: .5rem;
}
.frame h3 {
  font-size: var(--t-lg); line-height: 1.15; margin: 0;
  text-wrap: balance; overflow-wrap: break-word;
}
/* The quoted lines carry bracketed placeholders and the odd long compound.
   They must break rather than widen the card. */
.frame, .frame * { min-width: 0; }
.frame blockquote, .frame-body { overflow-wrap: break-word; }

/* The line to say. Large, serif, and unmistakably the point of the card. */
.frame blockquote,
.frame-body blockquote {
  margin: .3rem 0; padding: .9rem 1.1rem;
  background: var(--amber-wash); border-left: 5px solid var(--amber-deep);
  border-radius: 0 var(--round-sm) var(--round-sm) 0;
  font-family: var(--body); font-size: var(--t-md); line-height: 1.45;
  color: var(--ink);
}
.frame-body { font-size: var(--t-base); }
.frame-body > :first-child { margin-top: 0; }
.frame-body p { margin: .5em 0; }
.frame-from {
  margin: auto 0 0; padding-top: .7rem; border-top: 1.5px solid var(--rule-soft);
  font-family: var(--ui); font-size: var(--t-sm); color: var(--fg-2);
}

/* A numbered sequence: the steps to run when something has already happened.
   Counters rather than list markers, so the number can be set in the UI face
   with tabular figures and still line up under a two-line step. */
.steps { list-style: none; counter-reset: step; padding: 0; margin: .6em 0; }
.steps li {
  counter-increment: step; position: relative;
  padding: 0 0 .55em 2.4em; font-size: var(--t-base);
}
.steps li::before {
  content: counter(step); position: absolute; left: 0; top: .05em;
  width: 1.7em; height: 1.7em; border-radius: 50%;
  background: var(--teal); color: var(--on-teal);
  font-family: var(--ui); font-variant-numeric: tabular-nums;
  font-size: var(--t-sm); font-weight: 700;
  display: grid; place-items: center;
}

.shelf-note { font-size: var(--t-base); color: var(--fg-2); max-width: 60ch; margin: .2em 0 0; }

/* --- the questions index ------------------------------------------------ */

.qgrid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); }
.qcard {
  display: grid; gap: .25em; align-content: start;
  border: var(--edge-thin); border-radius: var(--round);
  background: var(--card); padding: 1.4rem 1.5rem;
  text-decoration: none; color: var(--fg);
}
.qcard:hover, .qcard:focus-visible { border-color: var(--link); }
.qcard-n {
  font-family: var(--ui); font-variant-numeric: tabular-nums;
  font-size: var(--t-2xl); font-weight: 700; color: var(--link); line-height: 1;
}
.qcard-name { font-family: var(--display); font-weight: 700; font-size: var(--t-md); line-height: 1.2; }
.qcard-blurb { font-size: var(--t-sm); color: var(--fg-2); }

/* A blockquote anywhere else on the site: the books quote themselves often. */
.prose blockquote, .read blockquote {
  margin: 1.1em 0; padding: .2em 0 .2em 1.2em;
  border-left: 4px solid var(--amber-deep);
  font-size: var(--t-md); color: var(--fg);
}

/* --- the free band on the home page ------------------------------------- */
/* Four things, on the teal ground, sized so the count reads first. It is the
   band that has to answer "why would I trust these people" before the shop
   asks for anything. */
.free-grid {
  display: grid; gap: 18px; margin-top: 1.6rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
}
.freecard {
  display: grid; gap: .3em; align-content: start;
  border: 1.5px solid var(--teal-edge); border-radius: var(--round);
  padding: 1.3rem 1.4rem; text-decoration: none; color: var(--fg);
  background: rgba(255, 255, 255, .04);
}
.freecard:hover, .freecard:focus-visible { border-color: var(--link); }
.freecard-n {
  font-family: var(--ui); font-variant-numeric: tabular-nums;
  font-size: var(--t-3xl); font-weight: 700; color: var(--link); line-height: 1;
}
.freecard-name { font-family: var(--display); font-weight: 700; font-size: var(--t-md); line-height: 1.2; }
.freecard-blurb { font-size: var(--t-sm); color: var(--fg-2); }

/* --- the hero picture ---------------------------------------------------- */
/* The hero holds two things now: the picture of somebody using one of these,
   and one real day out of one real book. Stacked, because side by side at this
   width the day quote loses the argument to the image. */
.hero-side { display: grid; gap: 18px; align-content: start; }
.art--hero {
  display: block; border-radius: var(--round); overflow: hidden;
  border: 1.5px solid var(--teal-edge);
}
.art--hero img { display: block; width: 100%; height: auto; }

/* The kind-label above a sample on the free hub: what sort of thing this is,
   before the thing itself. */
.frame-kind {
  margin: 0; font-family: var(--ui); font-size: var(--t-xs);
  letter-spacing: .06em; text-transform: uppercase; color: var(--fg-2);
}

/* --- a book's contents page --------------------------------------------- */
/* One band per chapter, alternating nothing: the rhythm comes from the rule
   above each head, not from stripes. Thirty of these in a column, so anything
   decorative would be thirty times as loud as it looks once. */
.ch { padding-block: 0; }
.ch + .ch { border-top: 1.5px solid var(--rule-soft); }
.ch .wrap { padding-block: clamp(28px, 4vw, 48px); }
.ch-head { max-width: 62ch; }
.ch-head h2 { font-size: var(--t-2xl); margin: .1em 0 .35em; text-wrap: balance; }
.ch-opens {
  font-family: var(--body); font-size: var(--t-md); line-height: 1.5;
  color: var(--fg); margin: 0;
}
.ch-opens span {
  display: block; font-family: var(--ui); font-size: var(--t-xs);
  letter-spacing: .06em; text-transform: uppercase; color: var(--fg-2);
  margin-bottom: .2em;
}

.ch-body { display: grid; gap: 28px; margin-top: 1.6rem; align-items: start; }
@media (min-width: 900px) {
  .ch-body { grid-template-columns: minmax(0, 1fr) minmax(0, 300px); gap: 40px; }
}
.ch-body h3 {
  font-family: var(--ui); font-size: var(--t-sm); font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; color: var(--fg-2);
  margin: 0 0 .5em;
}
.ch-body .terms { margin-bottom: 1.4rem; }
.ch-body .terms > div { grid-template-columns: minmax(0, 1fr); gap: .3em; }
@media (min-width: 780px) {
  .ch-body .terms > div { grid-template-columns: minmax(0, 1fr); }
}

/* The one small thing to do. Amber, because it is the only instruction on the
   page and everything around it is description. */
.ch-do {
  border-left: 5px solid var(--amber-deep); background: var(--amber-wash);
  border-radius: 0 var(--round-sm) var(--round-sm) 0;
  padding: 1rem 1.2rem; margin-top: .4rem;
}
.ch-do h3 { color: var(--ink); margin-bottom: .3em; }
.ch-do p { margin: 0; font-size: var(--t-base); }

.ch-pic { margin: 0; }
.ch-pic img {
  display: block; width: 100%; height: auto;
  border: 1.5px solid var(--border); border-radius: var(--round-sm);
}

/* The chapter jump strip: numbers, so thirty of them fit on one line. */
.filters .chip { min-width: 2.6em; text-align: center; }

/* The publisher line under the copyright. Quiet: it is a fact a retailer's
   catalogue needs, not something a reader came for. */
.foot-pub { color: var(--fg-2); }
