@font-face{font-family:'Abril Fatface';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/abril-fatface-400.woff2') format('woff2')}
@font-face{font-family:'Merriweather';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/merriweather-400.woff2') format('woff2')}
@font-face{font-family:'Merriweather';font-style:normal;font-weight:700;font-display:swap;src:url('fonts/merriweather-700.woff2') format('woff2')}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:500;font-display:swap;src:url('fonts/jetbrains-mono-500.woff2') format('woff2')}

:root{
  /* Warm paper, not white. Every ink on it is measured AAA (7:1+). */
  --paper:#FBF6EA;
  --paper-2:#F2ECDE;
  --card:#FFFCF4;       /* a leaf laid on the paper — lifts, never glares */
  --ink:#1A1712;
  --muted:#5A5243;      /* 7.15:1 */
  --rule:#DCD2BC;
  --red:#8F2D07;        /* 7.65:1 — small text, labels, keywords */
  --red-big:#C1440E;    /* 4.75:1 — display sizes only, where 3:1 applies */
  --lagoon:#1F4B47;     /* 9.03:1 */

  --display:'Abril Fatface',Georgia,serif;
  --body:'Merriweather',Georgia,serif;
  --mono:'JetBrains Mono',ui-monospace,monospace;

  --bar-h:7.8rem;
  --pad:clamp(1.25rem,5vw,4.5rem);
}

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

html,body{height:100%}
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--body);
  /* 16-18px. An earlier scale ran clamp(1.16rem,...,1.3rem) — 18.5-20.8px —
     which on a freelancer's laptop reads as a large-print edition. Stripe,
     Linear and Vercel all sit at 16px; editorial sites run 18px for article
     body and 15-16px for everything that is not prose. */
  font-size:clamp(1rem,0.98rem + 0.2vw,1.125rem);
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
  overflow:hidden;               /* the page itself never scrolls */
}

/* ---- The deck: one screen per section, snapping ---- */
.deck{
  height:100dvh;
  overflow-y:scroll;
  /* proximity, not mandatory. Mandatory fights trackpad momentum and forces a
     full-viewport jump on every flick, which punishes the scan-and-compare
     reading that anyone evaluating a paid tool actually does. */
  scroll-snap-type:y proximity;
  scroll-behavior:smooth;
  scrollbar-width:none;
}
.deck::-webkit-scrollbar{display:none}

.panel{
  min-height:100dvh;
  /*
   * min-height only. NOT max-height, and NOT overflow-y.
   *
   * The pair used to be `max-height:100dvh; overflow-y:auto`, on the reasoning
   * that a panel outgrowing a phone should scroll itself rather than the page.
   * What that actually built was seven nested scroll containers inside a
   * scroll-snap deck, every one with its scrollbar hidden.
   *
   * Scrolling slowly over such a panel sends the wheel to the INNER scroller
   * first. It creeps through its own overflow with no scrollbar to explain
   * why, and only then does the deck move and snap. That reads as lag, and as
   * text that will not advance to the next section — because it is not
   * advancing, it is scrolling inside the section you are already on.
   *
   * Measured at 1920×975 only `#s-how` overflowed, by 15px. At 800px high that
   * became 102px, and at 640px — an ordinary laptop once browser chrome is
   * subtracted — FOUR panels overflowed, `#s-how` by 182px.
   *
   * Growing is the honest behaviour: a panel that needs more room takes it,
   * the deck scrolls continuously through it, and proximity snapping picks up
   * again at the next boundary. Panels that fit are unchanged, because
   * min-height still makes them exactly one screen.
   */
  scroll-snap-align:start;
  display:grid;
  align-content:center;
  gap:1.5rem;
  padding:calc(var(--bar-h) + 1.5rem) var(--pad) 2.5rem;
}

/* ---- Top bar: the section index, and the 47 years ---- */
.topbar{
  position:fixed;
  inset:0 0 auto 0;
  z-index:20;
  /*
   * OPAQUE behind the bar's own content. The fade lives below it, in ::after.
   *
   * This was `linear-gradient(var(--paper) 64%, transparent)` — opaque for the
   * first 64% of the bar and fading out over the rest. The bar is 96px tall, so
   * that put the transparent zone at roughly 61–96px, and the bar's SECOND ROW
   * — the timeline rule with "Four platforms" and "One number" — sits at about
   * 75–96px. Inside its own transparency.
   *
   * Page text scrolling past therefore passed BEHIND the bar's own labels and
   * collided with them: "ANNUAL" from the pricing panel printed on top of
   * "Four platforms". The fade was meant to dissolve content below the bar and
   * was instead dissolving it behind the bar's writing.
   *
   * Worst at a dark-to-light boundary, which is where the contrast makes the
   * collision unmissable — but it happened at every boundary.
   */
  background-color:var(--paper);
  padding:0.75rem var(--pad) 0;
}

/*
 * The dissolve, moved to where it was always meant to be: BELOW the bar.
 *
 * Same effect — content does not end at a hard line — with nothing of the bar's
 * own on top of it, so there is nothing for passing text to collide with.
 */
.topbar::after{
  content:'';
  position:absolute;
  left:0;
  right:0;
  top:100%;
  height:2.25rem;
  background:linear-gradient(var(--paper),rgba(251,246,234,0));
  pointer-events:none;
}
/* At 16px the keywords no longer fit beside the wordmark on a phone, so they
   take their own row there. Squeezing them back onto one line is what
   produced 11px labels in the first place. */
.topbar-row{
  display:flex;
  align-items:center;
  gap:0.2rem 1.5rem;
  flex-wrap:wrap;
}
.mark{
  font-family:var(--display);
  font-size:1.5rem;
  letter-spacing:0.02em;
  color:var(--ink);
  text-decoration:none;
  flex:none;
}
.mark span{color:var(--red-big)}

/* The one filled control in the navbar, so signing in is the obvious action. */
.signin{
  flex:none;
  display:inline-flex;
  align-items:center;
  min-height:44px;
  padding:0.5rem 1.15rem;
  background:var(--red);
  border:2px solid var(--red);
  color:var(--paper);            /* 7.4:1 */
  font-family:var(--mono);
  font-size:0.85rem;
  font-weight:500;
  letter-spacing:0.08em;
  text-transform:uppercase;
  text-decoration:none;
  transition:background .2s ease,border-color .2s ease;
}
.signin:hover{background:var(--ink);border-color:var(--ink)}
.signin:focus-visible{outline:2px solid var(--lagoon);outline-offset:3px}

/* The keywords. On a narrow phone this strip scrolls sideways — nav, never page. */
.keys{
  display:flex;
  flex:0 1 auto;
  gap:1.7rem;
  overflow-x:auto;
  scrollbar-width:none;
  /* The auto left margin is what pushes the keywords across to sit beside
     Sign in. It has to be in the shorthand: a separate margin-left:auto above
     this line was silently cancelled by the `margin:0` that followed it. */
  margin:0 0 0 auto;
  padding:0;
  list-style:none;
  -webkit-overflow-scrolling:touch;
}
.keys::-webkit-scrollbar{display:none}
.keys a{
  font-family:var(--mono);
  font-size:0.84rem;
  font-weight:500;
  letter-spacing:0.09em;
  text-transform:uppercase;
  color:var(--muted);
  text-decoration:none;
  white-space:nowrap;
  display:flex;
  align-items:center;
  min-height:44px;               /* real touch target */
  transition:color .2s ease;
}
.keys a:hover{color:var(--ink)}
.keys a[aria-current="true"]{color:var(--red)}
.keys a:focus-visible,.mark:focus-visible,.btn:focus-visible{
  outline:2px solid var(--lagoon);
  outline-offset:3px;
}

/* The timeline. The marker is the active section — the nav IS the 45 years. */
.timeline{position:relative;height:2.2rem}
.timeline-rule{position:absolute;top:0.42rem;left:0;right:0;height:1px;background:var(--rule)}
.bead{
  position:absolute;top:0;
  width:0.64rem;height:0.64rem;
  border-radius:50%;
  background:var(--red-big);
  transform:translateX(-50%);
  transition:left .45s cubic-bezier(.6,.05,.2,1);
  box-shadow:0 0 0 4px var(--paper);
}
.years{
  position:absolute;top:0.85rem;left:0;right:0;
  display:flex;justify-content:space-between;
  font-family:var(--mono);
  font-size:0.8rem;
  letter-spacing:0.1em;
  color:var(--muted);
  font-variant-numeric:tabular-nums;
}

/* ---- Type ---- */
.eyebrow{
  font-family:var(--mono);
  font-size:0.82rem;font-weight:500;
  letter-spacing:0.14em;text-transform:uppercase;
  color:var(--red);margin:0;
}
.display{
  font-family:var(--display);font-weight:400;
  font-size:clamp(3.1rem,15vw,8.5rem);
  line-height:0.86;letter-spacing:-0.02em;
  margin:0;text-wrap:balance;
}
.display .quiet{color:var(--muted);display:block}
h2.title{
  font-family:var(--display);font-weight:400;
  font-size:clamp(2.1rem,8vw,4rem);
  line-height:0.98;margin:0;text-wrap:balance;
}
.lede{margin:0;max-width:34ch;color:#3B342A}
.fine{
  font-family:var(--mono);font-size:0.82rem;
  letter-spacing:0.1em;text-transform:uppercase;
  color:var(--muted);margin:0;
}

/* ---- Actions: underlined, not boxed. No rounded pills anywhere. ---- */
.actions{display:flex;flex-wrap:wrap;gap:1.7rem;margin-top:0.4rem}
.btn{
  font-family:var(--mono);font-size:0.9rem;font-weight:500;
  letter-spacing:0.08em;text-transform:uppercase;
  color:var(--ink);text-decoration:none;
  border-bottom:2px solid var(--red-big);
  min-height:44px;display:inline-flex;align-items:flex-end;
  padding-bottom:0.35rem;
  transition:color .2s ease,border-color .2s ease;
}
.btn:hover{color:var(--red)}
.btn.quiet{border-bottom-color:var(--rule);color:var(--muted)}
.btn.quiet:hover{color:var(--ink);border-bottom-color:var(--muted)}

/* ---- Ruled list: the contents page of a printed souvenir ---- */
.ruled{list-style:none;margin:0.5rem 0 0;padding:0;max-width:48ch}
/* A fixed key column, not `auto`. With `auto` each row sized its own first
   column, so PASSPHRASE and INVITED pushed their text to different left edges
   and the list read as unrelated rows rather than one index. */
.ruled li{
  display:grid;grid-template-columns:8.5rem 1fr;
  gap:0.35rem 1.5rem;padding:1.1rem 0;
  border-top:1px solid var(--rule);
}
@media (max-width:34rem){
  .ruled li{grid-template-columns:1fr}
}
.ruled li:last-child{border-bottom:1px solid var(--rule)}
.ruled .k{
  font-family:var(--mono);font-size:0.82rem;
  letter-spacing:0.1em;text-transform:uppercase;
  color:var(--lagoon);padding-top:0.4rem;
}
.ruled .v{font-size:1.15rem;color:#3B342A;margin:0}
.ruled .v strong{color:var(--ink);font-weight:700;display:block}

/* ---- The date, set like a title page ---- */
.datestack{display:grid;gap:0.25rem}
.datestack .big{
  font-family:var(--display);
  font-size:clamp(3.4rem,17vw,9rem);
  line-height:0.82;font-variant-numeric:tabular-nums;margin:0;
}
.datestack .big em{font-style:normal;color:var(--red-big)}
.count{
  font-family:var(--mono);font-size:1.05rem;
  letter-spacing:0.1em;text-transform:uppercase;
  color:var(--muted);font-variant-numeric:tabular-nums;
}

/* ---- One inverted panel, so the deck has a change of air ---- */
.panel.ink{background:var(--ink);color:var(--paper)}
.panel.ink .lede,.panel.ink .ruled .v{color:#D8CFBC}
.panel.ink .eyebrow{color:#E4762F}
.panel.ink .fine,.panel.ink .count{color:#A99C84}
.panel.ink .ruled li{border-color:#3A342A}
.panel.ink .ruled .k{color:#7FB3AD}
.panel.ink .ruled .v strong,.panel.ink .btn{color:var(--paper)}
.panel.ink .datestack .big em{color:#E4762F}
.panel.ink .btn.quiet{color:#A99C84;border-bottom-color:#3A342A}

@media (min-width:52rem){
  :root{--bar-h:5.8rem}
  .keys{flex:0 1 auto}
  .panel{gap:1.9rem}
  .split{
    display:grid;grid-template-columns:1.15fr 1fr;
    gap:clamp(2rem,6vw,6rem);align-items:center;
  }
}

@media (prefers-reduced-motion:reduce){
  .deck{scroll-behavior:auto}
  .bead{transition:none}
}

/* ---- Forms ---------------------------------------------------------------
   Labels are mono and lagoon, exactly like the keys in a ruled list, because
   they do the same job: naming the thing beside them. */
.field{display:grid;gap:0.45rem;margin:0 0 1.7rem}
.field label{
  font-family:var(--mono);
  font-size:0.82rem;font-weight:500;
  letter-spacing:0.1em;text-transform:uppercase;
  color:var(--lagoon);
}
.field .hint{margin:0;font-size:0.95rem;color:var(--muted)}
.field input{
  width:100%;
  min-height:56px;                 /* well over the 44px floor */
  padding:0.7rem 0.9rem;
  border:2px solid var(--ink);
  border-radius:0;                 /* print has no rounded corners */
  background:var(--paper);
  color:var(--ink);
  font-family:var(--body);
  font-size:1.1rem;
}
.field input:focus-visible{outline:2px solid var(--lagoon);outline-offset:2px}

/* Held to the same measure as the lede above it. Left to fill the panel, a
   single email box would stretch most of a desktop screen. */
.signin-form{max-width:30rem;margin:0.4rem 0 0}

/* The submit. Same filled block as the navbar's Sign in, so the page's one
   action looks like the action that brought you here. */
.btn-solid{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:56px;padding:0.6rem 1.6rem;
  background:var(--red);border:2px solid var(--red);
  color:var(--paper);
  font-family:var(--mono);font-size:0.9rem;font-weight:500;
  letter-spacing:0.08em;text-transform:uppercase;
  text-decoration:none;cursor:pointer;
  transition:background .2s ease,border-color .2s ease;
}
.btn-solid:hover{background:var(--ink);border-color:var(--ink)}
.btn-solid:focus-visible{outline:2px solid var(--lagoon);outline-offset:3px}

/* The back link in the bar, where Sign in sits on the other pages.
   It carries the same padding and an invisible border so its box is exactly
   as tall as that button: without them the bar was 3px shorter here and the
   whole page sat 3px higher than the homepage. */
.barlink{
  flex:none;
  margin-left:auto;                /* far right, where Sign in is on index */
  display:inline-flex;align-items:center;min-height:44px;
  padding:0.5rem 0;
  border:2px solid transparent;
  font-family:var(--mono);font-size:0.82rem;font-weight:500;
  letter-spacing:0.09em;text-transform:uppercase;
  color:var(--muted);text-decoration:none;
  transition:color .2s ease;
}
.barlink:hover{color:var(--ink)}
.barlink:focus-visible{outline:2px solid var(--lagoon);outline-offset:3px}

/* ---- Sign in: one centred column, and nothing else ------------------------
   The page has one job. Everything sits in the middle of the screen: the
   column is centred horizontally, the panel centres it vertically, and the
   text is centred within it. */
.auth .panel{padding-left:1.5rem;padding-right:1.5rem}

.auth-box{
  width:100%;
  max-width:27rem;
  margin:0 auto;
  text-align:center;
  display:grid;
  gap:1.1rem;
  justify-items:center;
}

.auth-box .display{font-size:clamp(3rem,7vw,4.4rem)}
.auth-box .lede{max-width:30ch;margin:0 auto}

.auth-box .signin-form{width:100%;max-width:none;margin:0.6rem 0 0}
.auth-box .field{text-align:left;margin-bottom:1.3rem}
.auth-box .btn-solid{width:100%}

/* The other ways in. Quiet text links, not a ruled list - a list of rows
   would weigh as much as the form it sits under. */
.auth-alt{
  display:grid;gap:0.7rem;
  margin:0.6rem 0 0;padding:1.4rem 0 0;
  border-top:1px solid var(--rule);
  width:100%;
}
.auth-alt a{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;
  font-family:var(--mono);font-size:0.82rem;font-weight:500;
  letter-spacing:0.06em;
  color:var(--muted);text-decoration:underline;text-underline-offset:4px;
  transition:color .2s ease;
}
.auth-alt a:hover{color:var(--red)}
.auth-alt a:focus-visible{outline:2px solid var(--lagoon);outline-offset:3px}

/* ---- Signed in: page links on row one, this page's sections on row two ----
   Signed out, the first row carries the keywords for the one public page.
   Signed in there are five pages to move between, so the pages take that row
   and the page's own sections drop underneath. Same mono index either way. */
body.member{--bar-h:7.2rem}

.pages{
  display:flex;
  gap:1.4rem;
  margin-left:auto;
  min-width:0;
  overflow-x:auto;
  scrollbar-width:none;
}
.pages::-webkit-scrollbar{display:none}

.pages a{
  flex:none;
  display:flex;align-items:center;
  min-height:44px;
  font-family:var(--mono);
  font-size:0.82rem;font-weight:500;
  letter-spacing:0.09em;text-transform:uppercase;
  white-space:nowrap;
  color:var(--muted);text-decoration:none;
  transition:color .2s ease;
}
.pages a:hover{color:var(--ink)}

/* Current page by colour AND an underline — never colour alone. */
.pages a[aria-current="page"]{
  color:var(--red);
  box-shadow:inset 0 -3px 0 var(--red);
}

/* Beats the auto margin on .barlink so the name sits right after the pages
   rather than both of them splitting the free space. */
.pages + .barlink{margin-left:1.5rem}

.topbar-sections{
  margin-top:0.2rem;
  padding-top:0.1rem;
  border-top:1px solid var(--rule);
}
.topbar-sections .keys{margin:0}

/* ---- Small pieces the member pages need ---------------------------------- */

/* A row's own action, e.g. "Change who can see this". */
.linklike{
  font-family:var(--mono);
  font-size:0.95rem;letter-spacing:0.04em;
  color:var(--muted);
  text-decoration:underline;text-underline-offset:3px;
}
.linklike:hover{color:var(--red)}

/* A ruled row whose whole width is a link. */
.ruled a.row{
  display:grid;grid-template-columns:subgrid;grid-column:1 / -1;
  gap:inherit;min-height:44px;
  color:inherit;text-decoration:none;
}
.ruled a.row:hover .v strong{color:var(--red)}
@supports not (grid-template-columns:subgrid){.ruled a.row{display:block}}

/* Nothing here yet — an invitation, never a dead end. */
.empty{
  border:1px dashed var(--rule);
  padding:2.4rem 1.6rem;
  text-align:center;
  display:grid;gap:0.9rem;justify-items:center;
}
.empty h2{font-family:var(--display);font-weight:400;font-size:2rem;margin:0}
.empty p{margin:0;max-width:38ch;color:var(--muted)}

/* State of a memory: who can see it. Text, never colour alone. */
.chip{
  display:inline-block;
  font-family:var(--mono);
  font-size:0.95rem;font-weight:500;
  letter-spacing:0.06em;text-transform:uppercase;
  color:var(--lagoon);
}
.chip-public{color:var(--red)}

/* The member's name in the bar, when it is the page you are on. */
.barlink[aria-current="page"]{
  color:var(--red);
  box-shadow:inset 0 -3px 0 var(--red);
}

/* ---- A centred column, for any page you type into -------------------------
   Same treatment as the sign-in page. A form pinned to the left edge of a
   1500px screen with nothing beside it reads as broken; centred, the page has
   a middle and the eye knows where to start.

   Kept separate from .auth-box rather than merged with it: sign-in is a single
   short form and holds a narrower measure, this has to fit ruled rows too. */
.centred{
  width:100%;
  max-width:32rem;
  margin:0 auto;
  text-align:center;
  display:grid;
  gap:1.1rem;
  justify-items:center;
}

.centred .display{font-size:clamp(3rem,7vw,4.4rem)}
.centred .title{font-size:clamp(2rem,4vw,2.8rem)}
.centred .lede{max-width:34ch;margin:0 auto}
.centred .signin-form{width:100%;max-width:none;margin:0.4rem 0 0}
.centred .field{text-align:left;margin-bottom:1.3rem}
.centred .btn-solid{width:100%}
.centred .actions{justify-content:center}

/* Rows stay left-aligned inside the centred column — centred list text is
   unreadable once a row runs to two lines. */
.centred .ruled{width:100%;max-width:none;text-align:left}

/* ---- Centred column, corrected ---------------------------------------------
   32rem was a measure for prose, and the ruled rows were living in it too: the
   value column came out about 280px and "Show it to the batch" wrapped into
   the line above. The column is now sized for the widest thing it holds, and
   the narrow things are held narrow individually. */
.centred{max-width:44rem}
.centred .signin-form{max-width:30rem;margin-inline:auto}
.centred .lede{max-width:36ch}

/* A row's action belongs on its own line. Inline, it read as the tail of the
   sentence before it and broke across two lines mid-phrase. */
.ruled .v .linklike{display:inline-block;margin-top:0.45rem}

/* ---- The right-hand pane ---------------------------------------------------
   What the section means, and where it stands. It is a margin note, not a
   panel: a hairline rule and space, no fill and no border box, so it reads as
   part of the printed page rather than as a widget stuck beside it.

   Below 64rem it drops under the content instead of squeezing both. */
.with-pane{display:grid;gap:clamp(2rem,5vw,4rem);align-items:start;width:100%}

@media (min-width:64rem){
  .with-pane{grid-template-columns:1fr 21rem}
  .pane{
    border-left:1px solid var(--rule);
    padding-left:clamp(1.5rem,2.5vw,2.5rem);
  }
}

.pane{display:grid;gap:1.2rem;align-content:start}

.pane h3{
  margin:0;
  font-family:var(--mono);
  font-size:0.82rem;font-weight:500;
  letter-spacing:0.12em;text-transform:uppercase;
  color:var(--lagoon);
}

.pane p{margin:0;font-size:0.95rem;color:var(--muted)}

/* The numbers. Tabular so the column of figures lines up. */
.figures{list-style:none;margin:0;padding:0;display:grid;gap:0}
.figures li{
  display:flex;justify-content:space-between;align-items:baseline;gap:1rem;
  border-top:1px solid var(--rule);
  padding:0.6rem 0;
  font-family:var(--mono);font-size:0.82rem;
  color:var(--muted);
}
.figures li:last-child{border-bottom:1px solid var(--rule)}
.figures b{font-weight:500;color:var(--ink);font-variant-numeric:tabular-nums}

/* ---- The flipbook preview, on the souvenir page ---------------------------
   Two facing pages, drawn rather than photographed: the book is not printed
   yet and a fake photograph would be a lie about what is in it. */
.book{
  width:100%;
  border:1px solid var(--rule);
  background:var(--card);
  display:grid;grid-template-columns:1fr 1fr;
}
.book-page{padding:0.9rem;display:grid;gap:0.6rem;align-content:start}
.book-page + .book-page{border-left:1px solid var(--rule)}
.book-slot{
  aspect-ratio:3/4;
  background:var(--paper-2);
  border:1px solid var(--rule);
  display:grid;place-items:center;
  font-family:var(--mono);font-size:0.82rem;
  letter-spacing:0.1em;text-transform:uppercase;
  color:var(--muted);
}
.book-caption{
  font-family:var(--mono);font-size:0.82rem;
  letter-spacing:0.06em;
  color:var(--ink);
}
.book-caption span{display:block;color:var(--muted)}
.book-foot{
  display:flex;justify-content:space-between;gap:1rem;
  font-family:var(--mono);font-size:0.82rem;color:var(--muted);
  font-variant-numeric:tabular-nums;
}

/* The content column inside .with-pane needs its own vertical rhythm.
   As children of .panel these elements got its 1.5rem grid gap; wrapped in a
   plain div they got nothing, and since .display and .lede both carry
   margin:0 the descender of a 136px Didone landed on the line beneath it. */
.with-pane > :not(.pane){
  display:grid;
  gap:1.5rem;
  align-content:start;
  min-width:0;
}

/* ---- The pane, made readable ----------------------------------------------
   It was set at 1rem beside 20.8px body text, so it read as fine print rather
   than as part of the page. Contrast was never the problem — the muted ink is
   7.15:1 on paper — the size was. */
@media (min-width:64rem){
  .with-pane{grid-template-columns:1fr 24rem}
}

.pane{gap:1.4rem}
.pane h3{font-size:1.05rem;letter-spacing:0.1em}
.pane p{font-size:1.15rem;line-height:1.6}

.figures li{font-size:1.08rem;padding:0.7rem 0}

.book-caption,.book-foot,.book-slot{font-size:1.05rem}

/* ---- The souvenir spread, given room --------------------------------------
   The book was living in the same 24rem pane as a paragraph of text, which
   left each page about 170px wide — a thumbnail of a thing whose whole point
   is that you can see it. The souvenir page gets a wider second column, and
   the spread is drawn as a printed object: an outer frame, a margin inside it,
   and a spine down the middle. */
@media (min-width:64rem){
  .with-pane-wide{grid-template-columns:1fr 32rem}
}

.book{
  padding:0.55rem;                 /* the frame around the spread */
  background:var(--card);
  border:1px solid var(--rule);
  align-items:stretch;
}

.book-page{
  padding:1.2rem 1.1rem;
  gap:0.85rem;
}

/* The spine. Doubled deliberately — one rule reads as a table border, two
   close together read as the fold between two facing pages. */
.book-page + .book-page{
  border-left:1px solid var(--rule);
  box-shadow:inset 3px 0 0 -2px var(--rule);
}

.book-slot{
  aspect-ratio:4/5;
  background:var(--paper);
  border:1px solid var(--rule);
}

.book-caption{line-height:1.45}
.book-foot{padding-top:0.2rem}

/* ===========================================================================
   THE APP
   ---------------------------------------------------------------------------
   Everything above this line was built for a landing deck: four panels, one
   screen each, snapped. That is right for a page you read once and wrong for
   a page you work in. A transactions list is a document — it wants to scroll
   continuously, be searched with the browser's own find, and show a scrollbar
   so you know there is more.

   So the app keeps the paper, the type, the rules and the mono index, and
   drops the deck. `body.app` unpicks the snapping without touching the markup:
   the pages still declare `.deck` and `.panel`, so the keyword navbar built by
   app.js keeps working unchanged.
   ========================================================================== */

/* The viewport scrolls, not the body. `overflow:auto` on a height:100% body
   makes body its own scroll container, which leaves window.scrollY pinned at 0
   — and with it browser find-on-page, scroll restoration, :target anchors and
   the wheel over anything that isn't the body box. Release the height instead. */
body.app{height:auto;min-height:100%;overflow:visible}

body.app .deck{
  height:auto;
  overflow-y:visible;
  scroll-snap-type:none;
}

body.app .panel{
  min-height:0;
  max-height:none;
  overflow-y:visible;
  scroll-snap-align:none;
  align-content:start;
  padding-top:2.6rem;
  padding-bottom:2.6rem;
}

/* The bar is fixed, so the first section has to clear it itself. */
body.app .panel:first-child{padding-top:calc(var(--bar-h) + 1.6rem)}

/* A hairline between sections, the way a printed report separates its parts.
   Not a card, not a shadow — this system has no boxes. */
body.app .panel + .panel{border-top:1px solid var(--rule)}

/* ---- The tally: gross, fees, net -------------------------------------------
   The one thing the whole product exists to answer. Set like the date on a
   title page — figure large in the display face, its name small in mono
   beneath — and ruled into columns so the three read as one statement rather
   than three unrelated numbers.

   Abril Fatface has no tabular figures, so it is used only where numbers sit
   alone. Anything that has to line up vertically is mono. */
.tally{
  display:grid;
  grid-template-columns:1fr;
  border-top:1px solid var(--rule);
  border-bottom:1px solid var(--rule);
}
@media (min-width:44rem){
  .tally{grid-template-columns:repeat(3,1fr)}
  .tally-cell + .tally-cell{border-left:1px solid var(--rule);padding-left:clamp(1rem,2.5vw,2rem)}
}
.tally-cell{padding:1.4rem 0;display:grid;gap:0.3rem;align-content:start}
.tally-cell + .tally-cell{border-top:1px solid var(--rule)}
@media (min-width:44rem){
  .tally-cell + .tally-cell{border-top:0}
}
.tally-cell .k{
  font-family:var(--mono);font-size:0.82rem;font-weight:500;
  letter-spacing:0.12em;text-transform:uppercase;
  color:var(--lagoon);
}
.tally-cell .n{
  font-family:var(--display);font-weight:400;
  font-size:clamp(2.6rem,7vw,4.2rem);
  line-height:0.9;letter-spacing:-0.01em;
  color:var(--ink);
}
/* Money leaving is set in the same red the rest of the system uses for
   emphasis — ledgers have always written what is owed in red ink. */
.tally-cell .n.out{color:var(--red-big)}
.tally-cell .sub{
  font-family:var(--mono);font-size:0.82rem;
  letter-spacing:0.06em;color:var(--muted);
  font-variant-numeric:tabular-nums;
}

/* ---- The bar chart ---------------------------------------------------------
   Drawn, not plotted. No library, no SVG, no fills that would put a block of
   colour on the paper: each month is a hairline-ruled column of paper-2, and
   the figure sits under it in mono. Every bar carries its value as text, so
   the chart is readable with the stylesheet off and by a screen reader —
   the height is decoration, the number is the data. */
.chart{
  display:grid;
  grid-auto-flow:column;
  grid-auto-columns:1fr;
  align-items:end;
  gap:clamp(0.3rem,1.2vw,0.8rem);
  height:clamp(9rem,22vh,14rem);
  margin:0;padding:0;list-style:none;
  border-bottom:1px solid var(--ink);
}
/* `1fr auto`, not `align-content:end`. With content-sized rows the bar's
   percentage height had no definite track to resolve against and collapsed to
   its 2px minimum — the chart drew as twelve hairlines. The 1fr row gives the
   percentage something real to measure, and align-items:end stands the bar on
   the axis. */
.chart li{
  display:grid;grid-template-rows:1fr auto;align-items:end;
  gap:0.5rem;height:100%;text-align:center;
}
.chart .bar{
  background:var(--paper-2);
  border:1px solid var(--rule);
  border-bottom:0;
  min-height:2px;
}
.chart li[aria-current="true"] .bar{background:var(--red-big);border-color:var(--red-big)}
.chart .m{
  font-family:var(--mono);font-size:0.95rem;
  letter-spacing:0.06em;text-transform:uppercase;
  color:var(--muted);
}
.chart-figures{
  display:flex;justify-content:space-between;
  font-family:var(--mono);font-size:0.82rem;
  color:var(--muted);font-variant-numeric:tabular-nums;
  margin:0.7rem 0 0;
}

/* ---- Sync state ------------------------------------------------------------
   Named, never coloured alone — the same rule the navbar follows. The word is
   the state; the colour only agrees with it. */
.state{
  font-family:var(--mono);font-size:0.95rem;font-weight:500;
  letter-spacing:0.06em;text-transform:uppercase;
  color:var(--lagoon);
  display:inline-flex;align-items:center;gap:0.5rem;
}
.state::before{content:'';width:0.5rem;height:0.5rem;border-radius:50%;background:currentColor;flex:none}
.state-stale{color:var(--red)}
.state-off{color:var(--muted)}

/* ---- A figure worth calling out --------------------------------------------
   The cost-of-conversion number is the one thing no other tool shows, so it
   gets the weight of a pull quote rather than a row in a table. */
.callout{
  border-left:3px solid var(--red-big);
  padding:0.2rem 0 0.2rem 1.3rem;
  display:grid;gap:0.5rem;max-width:44ch;
}
.callout .n{
  font-family:var(--display);font-size:clamp(2rem,5vw,3rem);
  line-height:1;color:var(--ink);
}
.callout p{margin:0;color:#3B342A}

/* Present to a screen reader and to a browser with no stylesheet, absent to
   the eye. The chart uses it to carry each bar's value as real text. */
.vh{
  position:absolute;width:1px;height:1px;
  margin:-1px;padding:0;border:0;
  clip-path:inset(50%);overflow:hidden;white-space:nowrap;
}

/* A row's sync state belongs under the row, not trailing the sentence above
   it — same correction the row action needed. `inline-flex` was not enough:
   an inline box with a top margin still sits on the line it was born on. It
   has to be block-level to claim its own. */
.ruled .v .state{display:flex;margin-top:0.5rem}

/* The bar, on a page that scrolls under it.
   The landing deck fades the bar out at 64% because a snapped panel centres
   its content and nothing ever passes beneath. A document scrolls continuously,
   so that fade let live rows show through the navbar. Solid paper and a
   hairline instead — the bar is a rule across the top of the page, like a
   running head. */
body.app .topbar{
  background:var(--paper);
  border-bottom:1px solid var(--rule);
  padding-bottom:0.3rem;
}
body.app .topbar-sections{border-top:0;margin-top:0}

/* The keyword index scrolls sections into view, so every section has to stop
   clear of the bar rather than under it. */
body.app .panel{scroll-margin-top:calc(var(--bar-h) + 0.5rem)}

/* ---- Consent ---------------------------------------------------------------
   Unticked by default and never a condition of the request: consent to be
   marketed to is a separate thing from asking for a place, and bundling the
   two is precisely what the law forbids. Set at body size rather than as fine
   print — text nobody can read is not consent. */
.consent{
  display:grid;grid-template-columns:auto 1fr;
  gap:0.85rem;align-items:start;
  margin:0 0 1.5rem;cursor:pointer;
  max-width:36rem;
}
.consent input{
  width:1.15rem;height:1.15rem;margin:0.32rem 0 0;
  accent-color:var(--red);flex:none;cursor:pointer;
}
.consent input:focus-visible{outline:2px solid var(--lagoon);outline-offset:3px}
.consent span{font-size:1.05rem;line-height:1.5;color:#3B342A}

/* ---- The bar over an inverted panel ---------------------------------------
   The bar fades to transparent at 64% so content passing beneath it dissolves
   rather than being cut off. Over the ink panel that fade handed the rail and
   its labels a near-black backdrop and they went dark-on-dark — present in the
   original template too, wherever an inverted panel sat under the bar.

   app.js already knows which panel is active, so the bar simply changes ink
   with it. Colours are the ones .panel.ink already establishes, so the bar
   agrees with the panel rather than inventing a second dark palette. */
/*
 * background-COLOR, and only on the bar itself.
 *
 * This was `transition:background .35s ease` on BOTH .topbar and .topbar::after.
 * The ::after is a linear-gradient, so that transition animated a
 * background-IMAGE: the browser regenerated the gradient bitmap every frame for
 * 350ms, on a full-width position:fixed element lying over a scrolling
 * container, which re-composites everything beneath it for the duration.
 *
 * #s-hidden is the only .ink panel on the site, so this fired exactly twice —
 * entering Hidden fees and leaving it — and nowhere else. That is the stall,
 * the whole page going soft, and it recovering a beat later, reported at
 * exactly that boundary and nowhere else.
 *
 * The gradient now swaps instantly. It is a 36px band; nobody will see it
 * change a third of a second before the bar behind it finishes.
 */
.topbar{transition:background-color .35s ease}
.topbar.on-ink{background-color:var(--ink)}
/* The dissolve takes the panel's colour with the bar, or it fades cream into a
   near-black panel and draws a bright band across the top of it. */
.topbar.on-ink::after{background:linear-gradient(var(--ink),rgba(26,23,18,0))}
.topbar.on-ink .mark{color:var(--paper)}
.topbar.on-ink .keys a{color:#A99C84}
.topbar.on-ink .keys a:hover{color:var(--paper)}
.topbar.on-ink .keys a[aria-current="true"]{color:#E4762F}
.topbar.on-ink .years{color:#A99C84}
.topbar.on-ink .timeline-rule{background:#3A342A}
.topbar.on-ink .bead{box-shadow:0 0 0 4px var(--ink)}

@media (prefers-reduced-motion:reduce){
  .topbar{transition:none}
}

/* ---- The wordmark ----------------------------------------------------------
   A three-letter wordmark reads as a mark at 1.5rem; nine letters does not.
   "Tallyduck" is nine lowercase letters, and at that size a Didone's whole
   character (the thick-to-hairline contrast) falls below the threshold where
   you can see it: it stopped looking like an identity and started looking like
   a bold serif word.

   Two corrections, no illustration required. Size, because Didones need it.
   And the join shown, because a compound name that reads as one word reads as
   a typo — Tally + duck, with the second half stepped back. */
.mark{font-size:1.85rem;letter-spacing:-0.005em}
.mark span.duck{color:var(--muted)}      /* beats `.mark span` on specificity */

@media (max-width:34rem){
  .mark{font-size:1.6rem}
}

/* ---- Auth ------------------------------------------------------------------
   No section index and no rail on a page with one form and one job, so the bar
   is a single row and gives its height back to the page. */
body.auth{--bar-h:4.2rem}

/* The honeypot. Not `display:none`: taken out of the layout, out of the tab
   order and out of the accessibility tree, but still a real field in the DOM
   for anything that fills forms by parsing them. */
.honeypot{
  position:absolute;left:-9999px;
  width:1px;height:1px;overflow:hidden;
}

/* The chart, shown on the landing page beside a tally and a heading rather
   than alone on a dashboard section. It has to give up some height so the
   whole panel still fits one screen without the panel scrolling inside itself. */
.chart-sm{height:clamp(6rem,14vh,9rem)}

/* `hidden` must actually hide. The attribute only carries `display:none` from
   the UA stylesheet, so any author rule that sets display — .auth-box is
   display:grid, .ruled is display:grid, .tally too — silently outranks it and
   the element stays on screen. This is the one place !important is the correct
   tool: hidden is not a suggestion. */
[hidden]{display:none !important}

/* ---- Long-form documents (privacy, terms) --------------------------------
   These are read, not scanned, so they get a measure and a rhythm rather than
   the deck's one-idea-per-screen pacing. body.app already turns off scroll
   snapping and lets the page scroll normally; .doc only sets the type. */
/* max-width lives with the rest of the document layout at the end of this
   file. It is  there: the notice runs the full width of the page. */
.doc h2{
  font-family:var(--display);font-weight:400;
  font-size:clamp(1.5rem,3.4vw,2.1rem);line-height:1.15;
  margin:2.6rem 0 0.9rem;
}
.doc h2:first-of-type{margin-top:1.6rem}
.doc h3{
  font-family:var(--mono);font-size:0.95rem;font-weight:500;
  letter-spacing:0.02em;color:var(--muted);
  margin:1.6rem 0 0.5rem;
}
.doc p,.doc li{font-size:1.06rem;line-height:1.65;color:#3B342A}
.doc p{margin:0 0 0.9rem}
.doc ul{margin:0 0 1.1rem;padding-left:1.1rem}
.doc li{margin:0 0 0.4rem}
.doc a{color:var(--red);text-underline-offset:0.18em}
.doc .updated{
  font-family:var(--mono);font-size:0.9rem;color:var(--muted);
  border-top:1px solid var(--rule);padding-top:0.8rem;margin-top:2.6rem;
}
/* A visible marker for the things still to be decided. Better on the page in
   plain sight than quietly missing — and it will not survive to launch. */
.doc .todo{
  border-left:3px solid var(--red-big);padding:0.1rem 0 0.1rem 1rem;
  margin:0 0 1.1rem;color:#3B342A;
}

/* ---- The rate stack ------------------------------------------------------
   Three rates stacked, so the cost reads as ACCUMULATION — a spread inside the
   rate, then a fee on top of it — rather than as one number to be taken on
   trust. No statement anywhere puts those two beside each other.

   Everything here starts VISIBLE. GSAP hides these rows at init and only if it
   is actually going to animate them, so a blocked script leaves the figures
   readable instead of leaving an empty column. */
.rates{display:grid;gap:1.1rem;align-content:start}
.rate-list{list-style:none;margin:0;padding:0;display:grid}
.rate{
  display:grid;grid-template-columns:1fr auto auto;
  align-items:baseline;gap:0.5rem 1.1rem;
  padding:0.75rem 0;border-top:1px solid #3A342A;
}
.rate:last-child{border-bottom:1px solid #3A342A}
.rate-k{
  font-family:var(--mono);font-size:0.86rem;font-weight:500;
  letter-spacing:0.1em;text-transform:uppercase;color:#7FB3AD;
}
.rate-n{
  font-family:var(--mono);font-size:1.25rem;color:var(--paper);
  font-variant-numeric:tabular-nums;
}
/* Reserved width even when empty (the mid-market row has no delta), so the
   three numbers stay in one column instead of shifting as rows appear.
   6ch, not less: the widest delta is "+0.33%" at six characters, and reserving
   4.6ch pushed the mid-market figure ~10px right of the two below it. */
.rate-d{
  font-family:var(--mono);font-size:0.9rem;font-weight:500;color:#E4762F;
  font-variant-numeric:tabular-nums;min-width:6ch;text-align:right;
}
.rate-out{
  font-family:var(--display);font-size:clamp(2.6rem,9vw,4.6rem);
  line-height:0.9;color:var(--paper);margin:0.4rem 0 0;
  font-variant-numeric:tabular-nums;
}
.rate-out em{font-style:normal;color:#E4762F}
.rate-out span{
  display:block;font-family:var(--mono);font-size:0.86rem;font-weight:500;
  letter-spacing:0.1em;text-transform:uppercase;color:#A99C84;margin-top:0.6rem;
}

/* The deck is a custom scroll container and now takes focus, so it needs to be
   able to say so. --red-big rather than --lagoon: this outline has to be
   visible on the ink panel as well as on paper. */
.deck:focus-visible{outline:2px solid var(--red-big);outline-offset:-4px}

/* ---- Content links -------------------------------------------------------
   Without these, links inside body copy fall back to the UA stylesheet and
   render default blue/purple, which on warm paper is the loudest thing on the
   page. The navbar, buttons and .doc pages already had their own treatment;
   these are the ones that were missed. Author rules beat the UA stylesheet
   regardless of specificity, so :visited needs no separate declaration. */
.lede a,.fine a,.hint a,.ruled .v a,.consent a,.auth-alt a{
  color:var(--red);
  text-decoration:underline;
  text-decoration-thickness:1px;
  text-underline-offset:0.18em;
  transition:color .2s ease;
}
.lede a:hover,.fine a:hover,.hint a:hover,.ruled .v a:hover,
.consent a:hover,.auth-alt a:hover{color:var(--ink)}

/* --red is 7.65:1 on paper but far too dark on the ink panel. */
.panel.ink .lede a,.panel.ink .fine a,.panel.ink .ruled .v a{color:#E4762F}
.panel.ink .lede a:hover,.panel.ink .fine a:hover,
.panel.ink .ruled .v a:hover{color:var(--paper)}

/* ============================================================================
   PHONES — up to 40rem (640px)
   ============================================================================

   Everything above this line was written for a deck: one section per screen,
   snapping, with a fixed index across the top telling you where you are. That
   is a good desktop reading experience and it is the wrong object on a phone.

   Three things break at 390px, and they compound:

   1. `--bar-h` is 7.8rem — 125px, FIFTEEN PER CENT of an iPhone screen — and
      the 5.8rem override only starts at 52rem. The bar is the largest single
      element on the page before you have read a word.

   2. `.topbar-row` is `flex-wrap:wrap` holding the wordmark, the seven-item
      index and Sign in. The wordmark (~130px) and Sign in (~110px) do not
      shrink, so on a 390px screen the index is handed roughly 62px. It has
      `overflow-x:auto`, so it does not overflow — it becomes a 62px window
      scrolling sideways through a fragment of one word. Technically correct
      and visually broken.

   3. `body{overflow:hidden}` with the scroll on an inner `.deck`. This is the
      specific arrangement that stops iOS Safari collapsing its address bar:
      the browser only hides chrome when the DOCUMENT scrolls. So the phone
      keeps ~110px of chrome permanently, `100dvh` panels are measured against
      a viewport that then changes anyway, and proximity snapping re-fires on
      every one of those changes. That is the jerk you feel on every swipe.

   The fix is not to tune the deck. It is to stop being a deck: give the
   scrolling back to the document, let panels be as tall as their content, and
   drop the position indicator that only meant something inside a deck. */
@media (max-width:40rem){

  /* THE scroll fix. The document scrolls, so the address bar collapses, so
     the viewport stops changing size mid-gesture. */
  html,body{height:auto;overflow:visible}

  .deck{
    height:auto;
    overflow-y:visible;
    scroll-snap-type:none;
    /* Explicit `auto`: `smooth` plus a fixed bar makes an in-page jump drift
       under the header before it settles. */
    scroll-behavior:auto;
  }

  .panel{
    min-height:0;                /* content decides the height, not the screen */
    scroll-snap-align:none;
    align-content:start;         /* centring only makes sense in a fixed box */
    padding:3rem var(--pad);
    /* Anchors still land below the fixed bar now that nothing snaps. */
    scroll-margin-top:calc(var(--bar-h) + 0.5rem);
  }

  /* Sections need a boundary once they are no longer one-per-screen. A rule,
     not a card — this design has no boxes. */
  .panel + .panel{border-top:1px solid var(--rule)}
  .panel.ink + .panel,.panel + .panel.ink{border-top:0}

  /* THE navbar fix. Two things, both of which have to be reachable with a
     thumb: who this is, and the way in. */
  :root{--bar-h:3.9rem}
  .panel:first-child{padding-top:calc(var(--bar-h) + 2.5rem)}

  .topbar-row{flex-wrap:nowrap;justify-content:space-between;gap:1rem}
  .mark{font-size:1.45rem}

  /* The index and the progress bead are DECK instruments — they answer "which
     of seven screens am I on", a question that stops existing the moment the
     page scrolls continuously. Hiding them is not hiding content: every
     section is still one scroll away, which is the gesture people already use.
     A 62px sideways-scrolling strip was worse than nothing. */
  .keys,.timeline{display:none}

  .signin{padding:0.5rem 0.9rem;font-size:0.8rem}  /* min-height:44px kept */

  /* The bar is short now; the fade under it should be too, or it veils the
     first line of every section. */
  .topbar::after{height:1.2rem}
}

/* ============================================================================
   WIDE SCREENS — the empty right-hand half
   ============================================================================

   Measured at 1920px, taking the right edge of painted TEXT rather than of the
   block boxes (every block here is full width, so boxes report nothing):

     #s-how      69% of the column empty
     #s-open     47%
     #s-pricing  47%
     #s-mess     13%   } these three carry .split, which is
     #s-hidden   12%   } already a two-column layout
     #s-start     4%   }

   The pattern is not subtle. Every panel with a second column is fine; every
   panel without one strands half the screen. Two causes:

   1. `.ruled{max-width:48ch}` — right when the list sits in one column of a
      .split, wrong when it IS the panel. In #s-how and #s-pricing it holds a
      630px list in a 1776px column and leaves the rest white.

   2. `.display` caps at 8.5rem. `15vw` would be 18rem at this width, so the
      headline stops growing at less than half the space it has.

   Neither is fixed by inventing content to fill the gap. The list becomes
   columns because four steps and three prices ARE a table; the headline is
   allowed to grow because a Didone at the top of a page is supposed to. */

@media (min-width:64rem){
  /* Only when the list IS the panel. `.panel > .ruled` deliberately does not
     match #s-mess or #s-hidden, where .ruled sits inside .split and its 48ch
     measure is doing exactly the right job. */
  .panel > .ruled{
    max-width:none;
    display:grid;
    column-gap:clamp(2rem,4vw,4.5rem);
    /* Two, so four steps make a clean 2x2 and three prices are handled below.
       NOT auto-fit: `minmax(19rem,1fr)` fits three columns at about 1512px, so
       the fourth step dropped onto a row of its own and left two thirds of it
       empty. An orphan row is worse than the gap it was meant to close. */
    grid-template-columns:repeat(2,1fr);
  }
  /* Count the items and match the columns to them, so a row is never part
     empty at any width. Three prices read as a price table; four steps read as
     a sequence. */
  .panel > .ruled:has(> li:nth-child(3):last-child){grid-template-columns:repeat(3,1fr)}
  /* Four steps and three tiers each get their own ruled column, the way a
     printed table sets them. The per-item rule already exists; in columns it
     reads as a column head instead of a row divider. */
  .panel > .ruled li:last-child{border-bottom:0}
  .panel > .ruled li{border-bottom:0}

  /* The headline. 8.5rem to 11.5rem: still clamped, still balanced, now
     actually reaching the measure it was set in.
     `body:not([class])` is the LANDING PAGE and nothing else. privacy.html is
     `body.app.doc` and sets its panels to max-width:44rem, so a 184px heading
     there would break out of a 704px column. The landing page is the only page
     whose panels run the full width, so it is the only one that can take it. */
  body:not([class]) .display{font-size:clamp(3.1rem,15vw,11.5rem)}

  /* A lede under a headline that wide reads as a caption if it stays at 34ch.
     Not full width either — prose past ~60ch is hard to track back. */
  .panel > .lede{max-width:46ch}
}

/* Four across only once there is room for four readable columns. At 64rem a
   quarter-width column is about 190px, which sets three words to a line. */
@media (min-width:90rem){
  .panel > .ruled:has(> li:nth-child(4):last-child){grid-template-columns:repeat(4,1fr)}
}

/* The display face is set at line-height 0.86, which is right for a headline
   standing alone and wrong directly above body text: at 136px the descender of
   a "p" or "y" comes within about 20px of the first line of the lede. On the
   landing page a large gap follows the headline anyway. On a document page the
   lede sits immediately under it. */
.doc .panel > .display{margin-bottom:0.9rem}

/* ============================================================================
   THE DOCUMENT TEMPLATE
   ============================================================================

   The brief, in Taha's words: no sections crammed into a corner, and not all
   the content on the left.

   What was there first was `max-width:44rem` flush left, which stranded a
   thousand pixels of white down the right. What I replaced it with was worse:
   a narrow centred block with an index rail beside it, which is a corner and a
   left-hand column, i.e. exactly the two things he had already ruled out.

   The problem is real and has one honest answer. Body text cannot simply be
   stretched to 1920px, because at that width a line runs past 150 characters
   and stops being readable. To fill a page with a document you have to give it
   MORE COLUMNS, which is what every printed report and newspaper does and has
   always done.

   So each section is a row across the full page:

     WHAT WE COLLECT   │ the text of that section, set in two
                       │ columns so no line runs long
     ──────────────────┴──────────────────────────────────────

   The heading hangs in the left margin in mono caps, which is the same device
   `.ruled .k` already uses on the landing page. Nothing is centred, nothing is
   parked in a corner, and the page is used edge to edge. */

.doc .panel{max-width:none}

@media (min-width:64rem){
  .doc-sec{
    display:grid;
    grid-template-columns:14rem minmax(0,1fr);
    column-gap:clamp(2rem,4vw,4rem);
    border-top:1px solid var(--rule);
    padding-top:1.6rem;
    margin-top:0.6rem;
  }
  /* The heading hangs. `position:sticky` so it stays with its own text on a
     long section rather than scrolling away from it. */
  .doc-sec > h2{
    grid-column:1;
    grid-row:1 / span 999;
    position:sticky;
    top:calc(var(--bar-h) + 1.5rem);
    align-self:start;
    margin:0;
    font-family:var(--mono);
    font-size:0.8rem;
    font-weight:500;
    letter-spacing:0.1em;
    text-transform:uppercase;
    color:var(--lagoon);
    line-height:1.45;
  }
  .doc-sec > .doc-body{grid-column:2}
}

/* Two columns of prose, on the SECTION BODY and never on a paragraph.
   column-count on individual <p> elements halves each paragraph into a pair of
   stacks side by side, so you read four lines, jump right, read four lines,
   jump back. On the body the text simply runs down one column and continues
   into the next, which is how a printed notice is set.
   orphans/widows stop a single line being stranded alone at a column break. */
@media (min-width:76rem){
  .doc-body{column-count:2;column-gap:clamp(2.5rem,4vw,4.5rem);orphans:1;widows:1}
  /* A heading must never be the last thing in a column. */
  .doc-body h3{break-after:avoid;break-inside:avoid}
  /* NO break-inside:avoid on paragraphs. That was here, and it meant a
     paragraph could never cross a column boundary — so any section with a
     single short paragraph put the whole thing in column one and left column
     two empty. Which is the empty right-hand side, caused by the rule meant to
     tidy the layout. A paragraph running from the foot of one column to the
     head of the next is how every printed notice is set. orphans/widows still
     stop a lone line being stranded. */
  .doc-body li{break-inside:avoid}
  .doc-body > :first-child{margin-top:0}
}

/* The opening block. It was capped at 60ch and left flush left, so the FIRST
   SCREEN of the page — the part everyone sees before scrolling — was a narrow
   strip with the whole right-hand side empty, while the sections below it ran
   the full width. Every screenshot I took was scrolled past it.
   It is wrapped in .doc-body now, so it flows in the same two columns as
   everything else and no measure caps it. */
.doc-intro{margin-bottom:1.2rem}

/* The masthead. `.display` puts its second half on its own line via
   `.quiet{display:block}`, which on a full-width document page left "What we /
   keep." occupying about a quarter of the line and a void beside it. On one
   line, at a size chosen to reach the margin, it reads as the masthead of the
   document rather than a small heading adrift in a large page. */
@media (min-width:76rem){
  .doc .panel > .display{
    font-size:clamp(4rem,12vw,15rem);
    line-height:0.92;
    /* A descender at 240px reaches a long way. Without this the intro text sat
       inside the tail of the "p". */
    margin-bottom:1.5rem;
  }
  .doc .panel > .display .quiet{display:inline}
  /* The markup is `What we<span class="quiet">keep.</span>` with NO space
     between the two, because the span was display:block and supplied the break
     itself. Inline, that sets as "What wekeep." The space has to come from
     here rather than from editing his copy. */
  .doc .panel > .display .quiet::before{content:"\00a0"}
}
