/* ======================================================================= *
 * askcal.css — the landing page's design system, in one file.
 *
 * Checked against scratchpad/DESIGN.md. If something here cannot be
 * justified from that file, one of the two is wrong.
 *
 * The governing rule: THE PAGE IS THE FRAME, THE PRODUCT IS THE ARTEFACT.
 * Everything page-side is neutral, gridded and grotesk. Serif, warm paper
 * and the app's literal palette appear only inside a .plate, which is the
 * app being shown rather than the page imitating it.
 * ======================================================================= */

/* ----------------------------------------------------------------------- *
 * Tokens
 *
 * Two greys and no more. An earlier pass had three and used all of them in
 * a single data row — label, value and number each a different tone —
 * which reads as indecision rather than hierarchy. The label is quiet;
 * everything that is an answer is ink.
 *
 * The neutrals are warm in both themes, and have to be, because the accent
 * is: a cool ground under a warm accent is what made the first pass look
 * dirty, and cool chalk ink on a warm dark ground is the same fault one
 * layer up.
 * ----------------------------------------------------------------------- */
:root {
  --ground:   #F2F1ED;
  --ground-2: #EAE8E2;   /* selected rows, hover, recessed cells */
  --line:     #DBD8D1;   /* the quiet rule — organises, never contains */
  --line-2:   #16171A;   /* the loud rule — ink, only at a figure's two ends */
  --ink:      #16171A;
  --ink-3:    #7C7A80;

  /* Askcal's own hue at 15–16°, with the chroma put back. The app ships
     #B4654A, which is 42% saturated: correct on the app's warm cream, mud
     on a near-white page. Same colour, corrected for this ground.

     It appears on the score and the selected mark. Nothing else — not
     links, not nav, not buttons, not rules. */
  --accent:   #BB5B38;
  --shadow:   rgba(22, 23, 26, .13);
  --grain: .045;
  --grain-blend: multiply;

  /* Three voices, and each one owns a job. Display sets headings and
     nothing else. Sans sets everything written. Mono sets everything
     measured — a rule the app itself keeps, so a number always looks like
     a number. */
  /* Two faces, and only two. There was a third — the system monospace —
     doing the labels, the data and the nav, and it was the one borrowed
     register on the page: SF Mono is what Liffy is set in, and this is not
     that project.
     
     What mono was providing is now provided by weight and tracking instead,
     which is why the family ships four weights. The one thing genuinely
     lost is tabular figures: Blauer Nue has no `tnum` and its digits are
     proportional (the 1 is a third narrower than the 0), so every numeric
     column on this page is right-aligned and none of them are compared
     down a column by eye. */
  --display: "Elegancy", "Bodoni 72", Didot, "Playfair Display", Georgia, serif;
  --sans: "Blauer Nue", -apple-system, BlinkMacSystemFont, "Helvetica Neue", system-ui, sans-serif;
  --mono: "Blauer Nue", -apple-system, BlinkMacSystemFont, "Helvetica Neue", system-ui, sans-serif;

  --page: 72rem;
  --gutter: clamp(18px, 4vw, 40px);
  --nav-h: 3.25rem;

  /* Askcal's literal values, from Askcal/DesignSystem/Paper.swift. Used
     INSIDE .plate only, and never tuned — a plate is the app, not a
     rendering of the app in the page's colours. */
  --p-paper: #F5F0E6;
  --p-card:  #FBF8F1;
  --p-rule:  #CFC5AE;
  --p-margin:#B4654A;
  --p-ink:   #2A2724;
  --p-sub:   #6A635A;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="day"]) {
    --ground: #151513; --ground-2: #1D1C19; --line: #302E2A;
    --line-2: #E9E7E2; --ink: #E9E7E2; --ink-3: #8A8781;
    --accent: #D2714E;
    --shadow: rgba(0, 0, 0, .55);
    --grain: .05;
    --grain-blend: screen;

    --p-paper: #16191B; --p-card: #1E2224; --p-rule: #2E3336;
    --p-margin: #9C5B47; --p-ink: #E9ECE9; --p-sub: #949B98;
  }
}
:root[data-theme="night"] {
  --ground: #151513; --ground-2: #1D1C19; --line: #302E2A;
  --line-2: #E9E7E2; --ink: #E9E7E2; --ink-3: #8A8781;
  --accent: #D2714E;
  --shadow: rgba(0, 0, 0, .55);
  --grain: .05;
  --grain-blend: screen;

  --p-paper: #16191B; --p-card: #1E2224; --p-rule: #2E3336;
  --p-margin: #9C5B47; --p-ink: #E9ECE9; --p-sub: #949B98;
}


/* ----------------------------------------------------------------------- *
 * The ground — one line system, and it is the grid itself.
 *
 * This was horizontal ruling across the whole viewport, and it fought every
 * other line on the page: the margin rule, the strip dividers, every plate
 * border, every section rule. Four unrelated systems of line reads as
 * banding, not as a notebook.
 *
 * Now there is exactly one: the twelve column rules the layout is built on,
 * drawn faintly and running the full height. Every rule on the page is
 * either one of these or a content rule sitting on one — so the lines
 * cannot disagree, because they are the same lines. The accent takes the
 * first column, which is what makes it read as the margin of a page rather
 * than as a stripe someone added.
 *
 * Texture is grain, which has no direction and therefore nothing to clash
 * with.
 * ----------------------------------------------------------------------- */
.rules {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  display: flex; justify-content: center;
}
.rules-in {
  width: 100%; max-width: var(--page);
  padding: 0 var(--gutter);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(16px, 2vw, 28px);
}
.rules-in span { border-left: 1px solid var(--line); opacity: .55; }
/* Every column rule is neutral. The accent one used to live here, which
   meant it was fixed to the viewport: it began above the page, ended below
   it, and passed through every section without ever starting or stopping.
   A line that never terminates does not read as a margin, it reads as
   something stuck to the screen. It belongs to the content now — see
   main::before. */

body::after {
  content: "";
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: var(--grain);
  mix-blend-mode: var(--grain-blend);
}
@media (prefers-contrast: more) { .rules, body::after { display: none; } }
@media print { .rules, body::after { display: none; } }

.nav, main, .pg, .sec, footer { position: relative; z-index: 1; }

/* No accent margin rule.
 *
 * There was one down the first column, and it was wrong twice over. The
 * content is aligned to that same column line, so the rule ran through the
 * left edge of every element on the page — a margin rule is a line you
 * write to the RIGHT of, with air between; this one touched the letterforms.
 * And it broke the rule this file is built on: the accent marks Askcal's
 * own judgement — the score, the word "regret", the selected mark — and
 * never marks chrome. A full-height stripe is chrome.
 *
 * The notebook reads from the column rules and the grain. It does not need
 * a red line to announce itself. */

/* ----------------------------------------------------------------------- *
 * Type — the faces.
 *
 * Elegancy is self-hosted and subset to the 89 glyphs the headings use:
 * 9.5 KB, which is why a display cut can afford to be a real typeface
 * rather than whatever the operating system happened to ship.
 *
 * It has NO italic — one style, italicAngle 0, no swash set. So nothing on
 * this page may ask for italic in the display face: the browser would
 * synthesise an oblique by shearing the roman, and a sheared didone is a
 * forgery anyone who reads type will spot. The accent word is coloured
 * instead, which was doing the work anyway.
 *
 * It is also missing ≤ ≥ →, which is fine and load-bearing: those belong to
 * the data voice, and the display face is scoped to headings only. Set a
 * heading containing one and it will tofu.
 * ----------------------------------------------------------------------- */
@font-face {
  font-family: "Elegancy";
  src: url("fonts/elegancy-display.woff") format("woff");
  font-weight: 400;
  font-style: normal;      /* declared, so no synthesis is ever attempted */
  font-display: swap;
}

/* Blauer Nue, self-hosted — three weights, the three the page asks for.
 *
 * Licensed, and web use is explicitly granted: the foundry's own
 * documentation ships WOFF/WOFF2 for every weight and tells you to put them
 * in your site's directory. The woff2 files here are theirs as delivered,
 * not converted, which is why they are 12 KB each.
 *
 * No italic is shipped because the page asks for none. If one is ever
 * wanted, add the face rather than letting the browser shear the roman. */
@font-face {
  font-family: "Blauer Nue";
  src: url("fonts/blauernue-300.woff2") format("woff2");
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Blauer Nue";
  src: url("fonts/blauernue-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Blauer Nue";
  src: url("fonts/blauernue-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Blauer Nue";
  src: url("fonts/blauernue-600.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}



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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 1rem);
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.pg { max-width: var(--page); margin: 0 auto; padding: 0 var(--gutter); }

a { color: inherit; }
::selection { background: var(--ink); color: var(--ground); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.skip {
  position: absolute; left: -9999px; z-index: 100;
  background: var(--ground); color: var(--ink);
  border: 1px solid var(--ink); padding: .7rem 1rem;
  font-family: var(--mono); font-size: .75rem;
}
.skip:focus { left: 1rem; top: 1rem; }

/* ----------------------------------------------------------------------- *
 * Type — four roles, and no more.
 *
 * The first version of the figure below had six sizes, four of them between
 * 10 and 12px, which is most of why it read as cluttered rather than dense.
 * Density is a lot of information at one size. Clutter is a little
 * information at six.
 * ----------------------------------------------------------------------- */
/* Label and data used to differ from body by being another typeface. They
   differ by weight and tracking now: the label is Light and tracked wide,
   the data is Regular and untracked. */
.t-label {
  font-family: var(--mono); font-size: .75rem; font-weight: 300;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-3); margin: 0;
}
.t-data { font-family: var(--mono); font-size: .875rem; font-weight: 400; font-variant-numeric: tabular-nums; }
.t-body { font-size: 1rem; line-height: 1.45; }

h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -.02em; line-height: 1.1; }
/* A didone is not a grotesk and must not be tracked like one. The grotesk
   scale wanted -.038em to close its gaps; pulled that tight, Elegancy's
   hairlines collide with the stems beside them and the line turns to mud.
   It also carries more colour per line, so it can run bigger and lead
   tighter than the sans ever could. */
.t-display {
  font-family: var(--display);
  font-size: clamp(2.75rem, 8.5vw, 5.75rem);
  font-weight: 400;
  letter-spacing: -.015em; line-height: .96;
  max-width: 20ch;
}
.t-section {
  font-family: var(--display); font-weight: 400;
  font-size: clamp(2rem, 4.2vw, 3.1rem);
  letter-spacing: -.012em; line-height: 1.08;
  max-width: 20ch; text-wrap: balance;
}
/* The break is composed, not negotiated. Left to `balance`, the line came
   apart as "Your inbox, / ranked / by regret." and stranded a word.
   Blocks rather than a <br>: hiding a <br> narrow removes the line break
   AND the space with it, which is how "inbox,ranked" happened. The source
   whitespace between the spans survives when they go inline. */
.ln { display: block; }
@media (max-width: 34rem) { .ln { display: inline; } }

.t-heading { font-family: var(--display); font-weight: 400; font-size: 1.5rem; letter-spacing: -.008em; }

p { margin: 0; }
/* 28px exactly, to match the ruling behind it — text on a notebook sits on
   the lines, and ruling that runs at its own rhythm reads as wallpaper.
   Stated in px rather than as a ratio for that reason: the two numbers have
   to be the same number. */
.prose { font-size: 1.0625rem; line-height: 28px; max-width: 62ch; text-wrap: pretty; }
.prose + .prose { margin-top: .9rem; }
.prose code, .inline-code { font-family: var(--mono); font-size: .875em; }
.dim { color: var(--ink-3); }

/* ----------------------------------------------------------------------- *
 * Nav — no accent, per the spec. Chrome is chrome.
 * ----------------------------------------------------------------------- */
.nav {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--ground) 90%, transparent);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.nav-in {
  max-width: var(--page); margin: 0 auto; padding: 0 var(--gutter);
  height: var(--nav-h); display: flex; align-items: center; gap: .85rem;
}
.nav-links { margin-left: auto; display: flex; align-items: center; gap: .85rem; }
/* Flex items shrink by default. With `nowrap` on top of that, a shrunk link
   does not wrap — it overflows its own box and lands on its neighbour. */
.nav-links > * { flex: none; }
.nav-mark {
  text-decoration: none;
  font-family: var(--mono); font-size: .9375rem; font-weight: 600;
  letter-spacing: -.01em;
}
.nav-a {
  font-family: var(--mono); font-size: .75rem; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3); text-decoration: none; white-space: nowrap;
  padding: .4rem .2rem;
}
.nav-a:hover { color: var(--ink); }
.nav-b {
  font: inherit; font-family: var(--mono); font-size: .75rem; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3); background: none; border: 0; cursor: pointer;
  padding: .4rem .2rem;
}
.nav-b:hover { color: var(--ink); }
@media (max-width: 40rem) { .nav-a.nav-opt { display: none; } }

/* ----------------------------------------------------------------------- *
 * Sections — the grid shows. A spec sheet states its own construction.
 * ----------------------------------------------------------------------- */
.sec { padding-block: clamp(3rem, 7vw, 5.5rem); }
.sec.ruled { border-top: 1px solid var(--line); }
.sec-hd {
  display: grid;
  grid-template-columns: 7rem minmax(0, 1fr);
  gap: 1rem 1.5rem;
  align-items: start;
  margin-bottom: clamp(1.75rem, 4vw, 2.75rem);
}
@media (max-width: 46rem) { .sec-hd { grid-template-columns: minmax(0, 1fr); gap: .5rem; } }
.sec-hd .prose { grid-column: 2; }
@media (max-width: 46rem) { .sec-hd .prose { grid-column: 1; } }

/* ----------------------------------------------------------------------- *
 * HERO — a composition, not two columns side by side.
 *
 * The previous hero was a 1fr + 27rem grid with both halves vertically
 * centred. That arrangement has no idea in it: the card's top edge aligned
 * to nothing, its bottom edge aligned to nothing, and the pair floated in
 * the middle of the viewport with dead space above, below and to the right.
 * It is the same skeleton every generated landing page has, and no amount
 * of typeface fixes a skeleton.
 *
 * What replaces it: the headline is set at masthead scale and its three
 * short lines step down the left, which carves an L-shaped void out of the
 * upper right. The app plate is placed INTO that void — overlapping the
 * type block's columns, bottom-aligned to the row the buttons sit on, and
 * hanging past the rule that closes the section. Type and object share two
 * axes and one edge, which is what harmony actually is.
 *
 * The base strip gives the whole thing a floor. Without it the composition
 * trails off into whitespace, which is the other half of why it read as
 * placed rather than composed.
 * ----------------------------------------------------------------------- */
/* clip, not hidden — the plate is pushed past the container edge on
   purpose, and this stops that becoming a horizontal scrollbar. Safe here
   because nothing inside the hero is sticky. */
.hero { position: relative; padding-block: clamp(2.25rem, 5vw, 4rem) 0; overflow-x: clip; }

.hero-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(16px, 2vw, 28px);
}

/* Both children occupy row 1 and overlap by two columns. The overlap is the
   whole point — it is what stops them reading as two separate objects that
   happen to be near each other. */
.hero-type { grid-area: 1 / 1 / 2 / 9; position: relative; z-index: 2; }

/* The caption, in the counter-shape's own corner. Two jobs: it labels the
   artefact — a spec sheet never shows a thing without saying what it is —
   and it occupies the top-right void, which was the last part of the
   composition still reading as leftover space rather than shaped space.
   The rule under it drops toward the plate it is talking about. */
/* The upper right was the last real void, and a void that large reads as
   an unfinished layout however good the type is. It gets the thesis —
   set as a dictionary entry, which is a magazine device and happens to be
   the most economical way to say what the whole product means. */
.hero-note { grid-area: 1 / 9 / 2 / 13; align-self: start;
  border-top: 1px solid var(--line-2); padding-top: .85rem; }
.def-w {
  font-family: var(--display); font-size: clamp(1.5rem, 2.4vw, 2.1rem);
  color: var(--accent); letter-spacing: -.01em;
}
.def-p { font-family: var(--mono); font-size: .75rem; color: var(--ink-3); margin-left: .5rem; }
.def-b {
  font-family: var(--mono); font-size: .75rem; line-height: 1.9;
  color: var(--ink-3); margin-top: .5rem; max-width: 34ch;
}
.def-b b { color: var(--ink); font-weight: 400; }
/* No leader line. There was one, and it pointed at nothing — a rule that
   goes nowhere is worse than no rule, because a reader looks for what it
   means. The caption sits under its own rule instead and lets proximity to
   the plate do the pointing. */
@media (max-width: 62rem) { .hero-note { display: none; } }
/* Runs off the right edge of the frame. A closed rectangle sitting wholly
   inside the page reads as a picture someone pasted on; one that is cropped
   by the frame reads as an object the page is showing part of. That single
   difference is most of what made these look like PNGs. */
.hero-art  { grid-area: 1 / 6 / 2 / 13; position: relative; z-index: 1;
             align-self: end;
             margin: 0 calc(-1 * (var(--gutter) + 5vw)) 0 0; }

/* Masthead scale. The old hero capped at 5.75rem inside a 1fr column, which
   at 1700px meant a headline occupying a third of the screen with two
   thirds of nothing beside it. */
.hero .t-display {
  font-size: clamp(2.75rem, 10.5vw, 8.5rem);
  max-width: none;
  margin-bottom: clamp(1.25rem, 2.5vw, 2rem);
}
/* Held to the left five columns, so it never runs under the plate. */
.hero-lede { max-width: 38ch; }
.hero .cta { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: clamp(1.5rem, 3vw, 2.25rem); }
.hero-kicker { margin-bottom: clamp(1rem, 2vw, 1.5rem); }

/* The plate as an object on a page: laid down slightly off-square, with a
   hard offset shadow and a piece of tape holding it. A notebook idiom, and
   the reason it reads as placed BY someone rather than merely placed. */
.hero-art .plate {
  transform: rotate(-1.5deg);
  box-shadow: 10px 12px 0 -1px var(--shadow);
}
.tape {
  position: absolute;
  z-index: 3;
  top: -13px; left: 12%;
  width: clamp(72px, 9vw, 104px); height: 26px;
  transform: rotate(-3.4deg);
  background: color-mix(in srgb, var(--accent) 16%, var(--ground));
  border-left: 1px solid color-mix(in srgb, var(--accent) 26%, transparent);
  border-right: 1px solid color-mix(in srgb, var(--accent) 26%, transparent);
  opacity: .85;
}

/* The floor. Mono, ruled, full width — the composition ends on a line
   instead of dissolving. */
/* The plate is bottom-aligned to the row the buttons sit on, so this gap is
   the only thing between it and the strip. It was -4.5rem of overhang and
   the plate landed on top of the strip's third column. */
.hero-foot { border-top: 1px solid var(--line); margin-top: clamp(2.75rem, 4.5vw, 4rem); }
.foot-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
}
.foot-strip > div { padding: .85rem 0 .95rem 1rem; border-left: 1px solid var(--line); }
.foot-strip > div:first-child { padding-left: 0; border-left: 0; }
.foot-strip span {
  display: block; font-family: var(--mono); font-size: .6875rem;
  letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3);
  margin-bottom: .2rem;
}
.foot-strip b { font-family: var(--mono); font-size: .8125rem; font-weight: 400; color: var(--ink); }

@media (max-width: 62rem) {
  .hero-type { grid-area: 1 / 1 / 2 / 13; }
  .hero-art  { grid-area: 2 / 1 / 3 / 13; margin: 2.5rem 0 -2.5rem; }
  .hero-lede { max-width: 46ch; }
}
@media (max-width: 40rem) {
  .foot-strip { grid-template-columns: 1fr 1fr; }
  .foot-strip > div:nth-child(3) { padding-left: 0; border-left: 0; }
  .foot-strip > div:nth-child(n+3) { border-top: 1px solid var(--line); }
}
@media (max-width: 30rem) {
  .hero-art .plate { transform: none; box-shadow: 5px 6px 0 -1px var(--shadow); }
  .tape { display: none; }
}
@media (prefers-reduced-motion: reduce) { .hero-art .plate { transform: none; } }

/* ----------------------------------------------------------------------- *
 * FIGURES — rules, not boxes.
 *
 * The first pass put every element inside a border: the plate, the picker,
 * each option, each row. Three nested boxes deep is what "cluttered" meant.
 * Swiss organises with rules; it does not contain with boxes.
 * ----------------------------------------------------------------------- */
/* The figure is a panel, not a pair of open rules.
 *
 * It was transparent, which let the twelve column rules run straight
 * through the readout — vertical lines crossing a table of numbers that
 * already has its own dotted leaders. Two line systems inside one figure,
 * and no edge anywhere, so it read as unbounded.
 *
 * An opaque surface fixes both at once: the grid stops at the panel edge,
 * and the panel has a boundary. It is the page's own surface, not the
 * app's — this is an instrument the page provides, and a plate is the
 * product. The two must not look like the same kind of object. */
.fig-panel {
  background: var(--ground);
  border: 1px solid var(--line-2);
  box-shadow: 6px 8px 0 -1px var(--shadow);
}
.fig-hd {
  display: flex; align-items: baseline; gap: 1rem 1.25rem; flex-wrap: wrap;
  background: var(--ground-2);
  border-bottom: 1px solid var(--line-2);
  padding: .85rem 1.5rem;
}
.fig-t { font-size: 1.0625rem; font-weight: 600; letter-spacing: -.012em; }
.fig-src { margin-left: auto; font-family: var(--mono); font-size: .75rem; font-weight: 300; letter-spacing: .04em; color: var(--ink-3); }
@media (max-width: 34rem) { .fig-src { margin-left: 0; } }

.fig { display: grid; grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); }
@media (max-width: 48rem) { .fig { grid-template-columns: minmax(0, 1fr); } }

.fig-pick { border-right: 1px solid var(--line); padding: 24px 24px 32px; }
.fig-out  { padding: 24px 32px 32px; }
@media (max-width: 48rem) {
  .fig-pick { border-right: 0; border-bottom: 1px solid var(--line); padding: 24px 20px 28px; }
  .fig-out  { padding: 24px 20px 28px; }
}

/* Options are separated by air, not by rules. */
.fig-opt {
  display: grid; grid-template-columns: .75rem minmax(0, 1fr);
  gap: .75rem; align-items: start; position: relative;
  width: 100%; text-align: left; font: inherit; color: inherit;
  background: none; border: 0; cursor: pointer;
  padding: 10px 12px 10px 8px;
}
.fig-opt:hover { background: var(--ground-2); }
.fig-opt[aria-checked="true"] { background: var(--ground-2); }
.fig-opt-m { width: 8px; height: 8px; border-radius: 50%; border: 1px solid var(--ink-3); margin-top: .42rem; }
.fig-opt[aria-checked="true"] .fig-opt-m { background: var(--accent); border-color: var(--accent); }
.fig-opt-f { display: block; margin-top: .15rem; }

/* The leader line: the selected message reaches across the rule into the
   readout, so the two halves read as one statement rather than as two
   panels sitting next to each other. It is the page's structural signature
   and it earns its keep only when it points at something. */
.fig-opt[aria-checked="true"]::after {
  content: ""; position: absolute; right: -24px; top: 1.05rem;
  width: 24px; height: 1px; background: var(--ink);
}
@media (max-width: 48rem) { .fig-opt[aria-checked="true"]::after { display: none; } }

/* A row is a label, a value, a leader and a number. The leader is not
   decoration: at full width the value and its number are 500px apart, and
   a dotted rule between them is how every printed data sheet has always
   solved that. It is also why the row is flex rather than grid — the value
   has to hug its own text so the leader can take what is left. */
.row {
  display: flex; align-items: baseline; gap: 1rem;
  padding: .5rem 0;
}
.row + .row { border-top: 1px solid var(--line); }
.row .k { flex: 0 0 7.5rem; color: var(--ink-3); }
.row .v { flex: 0 1 auto; color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .lead { flex: 1 1 auto; min-width: 1.5rem; border-bottom: 1px dotted var(--line); transform: translateY(-.3em); }
.row .n { flex: 0 0 3.25rem; text-align: right; font-variant-numeric: tabular-nums; color: var(--ink); }
.row.mul .v, .row.mul .n { color: var(--ink-3); }

.total {
  display: grid; grid-template-columns: 7.5rem minmax(0, 1fr) auto;
  gap: 1rem; align-items: baseline;
  border-top: 1px solid var(--ink); margin-top: .1rem; padding: .9rem 0 .2rem;
}
.total .n {
  font-family: var(--mono); font-size: 3rem; line-height: 1; font-weight: 500;
  letter-spacing: -.045em; color: var(--accent);
  font-variant-numeric: tabular-nums; text-align: right;
}

/* NAMING: components own a prefix. `.gates` and `.g` were generic, and the
   gate TABLE further down also calls itself `.gates` — its `display: table`
   lost to this `display: grid` and the table collapsed to two-thirds of its
   panel. Second time a bare name has done this here; `.opt` was the first. */
.fig-gates { margin-top: 1.1rem; display: grid; gap: .35rem; }
.fig-g { display: grid; grid-template-columns: .9rem minmax(0, 1fr); gap: .6rem; align-items: baseline; }
.fig-g .m { color: var(--ink-3); }
.fig-g span:last-child { color: var(--ink); }
.fig-g.no .m, .fig-g.no span:last-child { color: var(--ink-3); }
.verdict { margin-top: .9rem; color: var(--ink); }

.fig-note { margin-top: 20px; max-width: 52ch; color: var(--ink-3); }
.fig-note code { color: var(--ink); }

@media (max-width: 34rem) {
  /* Narrow, the value needs every pixel — `automated_system` read as
     `autom…` is a row that has stopped saying anything. The leader is the
     first thing to go, and the label gives up width after it. */
  .row { gap: .6rem; }
  .row .k { flex: 0 0 5.5rem; }
  .row .v { flex: 1 1 auto; }
  .row .lead { display: none; }
  .row .n { flex: 0 0 2.75rem; }
  .total { grid-template-columns: 5.5rem minmax(0, 1fr) auto; gap: .6rem; }
  .total .n { font-size: 2.5rem; }
}

/* ----------------------------------------------------------------------- *
 * Without scripts.
 *
 * The figure still reads: it renders one message fully worked, which is the
 * whole argument. What must not survive is the chrome around it — a theme
 * button that cannot change the theme and five picker buttons that cannot
 * pick are worse than not offering them, because a dead control reads as a
 * broken page rather than as a simpler one.
 * ----------------------------------------------------------------------- */
html:not(.js) .nav-b { display: none; }
html:not(.js) .fig-opt { cursor: default; }
html:not(.js) .fig-opt:hover { background: none; }
html:not(.js) .fig-opt:not([aria-checked="true"]) { opacity: .5; }
html:not(.js) .fig-opt:not([aria-checked="true"]) .fig-opt-m { border-style: dotted; }

/* ----------------------------------------------------------------------- *
 * Motion — the whole budget, spent here.
 *
 * `.settling` exists only inside this query, so with reduced motion the
 * readout is simply its answer rather than a thing waiting to be revealed.
 * ----------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .row .v, .row .n { transition: opacity .18s ease, transform .18s ease; }
  .settling .row .v, .settling .row .n { opacity: 0; transform: translateY(-3px); }
  .fig-g, .verdict { transition: opacity .2s ease; }
  .settling .fig-g, .settling .verdict { opacity: 0; }
}

/* ======================================================================= *
 * PLATES — the app, drawn.
 *
 * This is where the governing rule earns its keep: the page is neutral and
 * grotesk, and inside a plate everything switches to Askcal's own palette,
 * its serif, and its terracotta margin rule. A plate is the product being
 * shown, not the page imitating it — which is why these use the literal
 * --p-* values from Paper.swift and are never tuned to match the page.
 *
 * Drawn in markup rather than screenshotted: a screenshot goes stale the
 * moment a colour moves, and this cannot, because it is reading the same
 * numbers the app compiles.
 * ======================================================================= */
.plate {
  background: var(--p-paper);
  border: 1px solid var(--line);
  position: relative;
  overflow: hidden;
  font-family: var(--sans);
}
/* The margin rule. In the app it is the single warm accent in the whole
   palette; here it is what tells you which of these surfaces is the
   product. */
.plate::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: 2px; background: var(--p-margin);
}

.plate-hd, .plate-ft {
  display: flex; align-items: baseline; gap: 1rem;
  padding: .7rem 1rem .7rem 1.5rem;
  font-family: var(--mono); font-size: .6875rem;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--p-sub);
}
.plate-hd { border-bottom: 1px solid var(--p-rule); }
.plate-ft { border-top: 1px solid var(--p-rule); }
.plate-hd .right, .plate-ft .right { margin-left: auto; }

.plate-rows { padding: .25rem 0; }
.prow {
  display: grid;
  grid-template-columns: 3.4rem 1.1rem minmax(0, 1fr) auto;
  gap: .8rem; align-items: center;
  padding: .62rem 1rem .62rem 1.5rem;
}
.prow + .prow { border-top: 1px solid var(--p-rule); }
.prow-t { font-family: var(--mono); font-size: .75rem; color: var(--p-sub); font-variant-numeric: tabular-nums; }

/* One check shape, the app's. Drawn inside its row and never outside it —
   the app learned that the hard way, when a checkbox hung into the margin
   rendered perfectly and could not be tapped. */
.pmark {
  width: 15px; height: 15px; border-radius: 50%;
  border: 1.5px solid var(--p-rule); display: grid; place-items: center;
}
.prow.done .pmark { background: var(--p-ink); border-color: var(--p-ink); }
.pmark svg { width: 9px; height: 9px; stroke: var(--p-paper); fill: none; stroke-width: 2.2; opacity: 0; }
.prow.done .pmark svg { opacity: 1; }

/* New York for anything written — the app's rule, and the reason a plate
   reads as a different object from the page around it. */
.prow-s {
  font-family: ui-serif, "New York", "Iowan Old Style", Georgia, serif;
  font-size: .9375rem; color: var(--p-ink); min-width: 0;
}
.prow.done .prow-s { color: var(--p-sub); text-decoration: line-through; }
.prow-pin { font-family: var(--mono); font-size: .625rem; color: var(--p-sub); }

@media (max-width: 30rem) {
  .prow { grid-template-columns: 3rem 1.1rem minmax(0, 1fr) auto; gap: .55rem; padding-left: 1.15rem; padding-right: .7rem; }
  .plate-hd, .plate-ft { padding-left: 1.15rem; padding-right: .7rem; letter-spacing: .08em; }
}

/* ======================================================================= *
 * THE TURN — two papers on a desk.
 *
 * This was two cards side by side with an arrow and captions between them,
 * which is the explainer-diagram every SaaS site ships. Worse, both cards
 * sat wholly inside the frame, which is what made them read as images
 * pasted on rather than as things the page contains.
 *
 * Now they overlap and the second runs off the edge — the same two moves
 * that fixed the hero. The relationship is stated by the overlap itself,
 * so the arrow explaining it is not needed and is gone.
 * ======================================================================= */
.turn {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(16px, 2vw, 28px);
  align-items: start;
}
/* They meet on a column line rather than overlapping across it. The first
   attempt had them share two columns, and the second plate landed on the
   first one's timestamps and on its own caption — layering that hides what
   it is layering is just a collision with a nicer name. The offset, the
   rotations and the right-hand bleed carry the desk feeling instead. */
.turn-a { grid-area: 1 / 1 / 2 / 7;  z-index: 1; }
.turn-b { grid-area: 1 / 7 / 2 / 13; z-index: 2; margin-top: 4rem;
          margin-right: calc(-1 * (var(--gutter) + 5vw)); }
.turn-a .plate { transform: rotate(-.9deg); box-shadow: 8px 10px 0 -1px var(--shadow); }
.turn-b .plate { transform: rotate(1deg);   box-shadow: 10px 12px 0 -1px var(--shadow); }
.turn-cap { margin-bottom: .7rem; }

@media (max-width: 62rem) {
  .turn-a { grid-area: 1 / 1 / 2 / 13; }
  .turn-b { grid-area: 2 / 1 / 3 / 13; margin-top: 2rem; }
}
@media (max-width: 30rem) {
  .turn-a .plate, .turn-b .plate { transform: none; box-shadow: 5px 6px 0 -1px var(--shadow); }
}

/* The mail that arrived: same construction, no margin rule — an inbox is
   not a page of the notebook. */
.plate.inbox::before { display: none; }
.plate.inbox .plate-hd, .plate.inbox .plate-ft { padding-left: 1rem; }
.mrow {
  display: grid; grid-template-columns: .5rem minmax(0, 1fr) auto;
  gap: .8rem; align-items: baseline;
  padding: .62rem 1rem;
}
.mrow + .mrow { border-top: 1px solid var(--p-rule); }
.mrow-dot { width: 6px; height: 6px; border-radius: 50%; border: 1px solid var(--p-sub); align-self: center; }
.mrow.unread .mrow-dot { background: var(--p-ink); border-color: var(--p-ink); }
.mrow-b { min-width: 0; }
.mrow-f {
  font-family: ui-serif, "New York", "Iowan Old Style", Georgia, serif;
  font-size: .9375rem; color: var(--p-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mrow-s { font-size: .8125rem; color: var(--p-sub); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mrow-t { font-family: var(--mono); font-size: .6875rem; color: var(--p-sub); white-space: nowrap; }

.dropped {
  margin: 0 1rem 1rem 1.5rem; padding: .6rem .8rem;
  border: 1px dashed var(--p-rule);
  font-family: var(--mono); font-size: .6875rem; line-height: 1.7; color: var(--p-sub);
}
.dropped b { color: var(--p-ink); font-weight: 600; }

/* ----------------------------------------------------------------------- *
 * Hero additions for the brief.
 * ----------------------------------------------------------------------- */
.hero-kicker { margin-bottom: 1.5rem; }
.hero .cta { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.75rem; }

/* The one word in the headline that is the whole idea. The spec says the
   accent marks Askcal's own judgement; "regret" is that judgement named, so
   this is the same rule rather than an exception to it. */
.accent { color: var(--accent); }

.btn {
  font-family: var(--mono); font-size: .75rem; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase;
  text-decoration: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .7rem 1.1rem; line-height: 1.4;
  border: 1px solid var(--line-2); background: none; color: var(--ink);
}
.btn.solid { background: var(--ink); color: var(--ground); }
.btn:not(.solid):hover { background: var(--ground-2); }
@media (prefers-reduced-motion: no-preference) {
  .btn { transition: background-color .12s ease, color .12s ease; }
}

/* ======================================================================= *
 * THE GATES — a table, on its own surface.
 * ======================================================================= */
/* fixed, with stated widths. Left to size themselves, the cells hugged
   their content and the whole table huddled into the left half of the panel
   with the header rule stopping wherever the text happened to end. */
.gates { width: 100%; border-collapse: collapse; table-layout: fixed; }
.gates col.c-mail { width: 30%; }
.gates col.c-act  { width: 9%; }
.gates col.c-csq  { width: 16%; }
.gates col.c-cnf  { width: 9%; }
.gates col.c-scr  { width: 9%; }
.gates col.c-vrd  { width: 27%; }
.gates th {
  font-family: var(--mono); font-size: .6875rem; font-weight: 400;
  letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3);
  /* 14px on top. It was 0, so the label sat hard against the row's own top
     border and read as clipped. */
  text-align: left; padding: 14px 16px 12px; border-bottom: 1px solid var(--line-2);
}
.gates th.n, .gates td.n { text-align: right; font-variant-numeric: tabular-nums; }
.gates td { padding: 14px 16px; border-bottom: 1px solid var(--line); vertical-align: baseline; }
/* At a wide panel the columns drifted so far apart that a value stopped
   reading as belonging to its heading. Column rules tie them back together,
   and they are the same rules the rest of the page is built on. */
.gates th + th, .gates td + td { border-left: 1px solid var(--line); }
.gates tr:last-child td { border-bottom: 0; }
.gates .mail { font-size: 1rem; }
.gates td.f, .gates td.n, .gates .why { font-family: var(--mono); font-size: .8125rem; color: var(--ink-3); }
.gates .why { font-size: .75rem; }
.gates tr.pass td.n.score { color: var(--accent); font-size: 1rem; }
.gates tr.pass .why { color: var(--ink); }
.gates .y { color: var(--ink); }
.gates .n-mark { color: var(--ink-3); }
/* Refused rows read as refused. The first pass struck them in --ink-3 at a
   hairline, which on a dark ground was invisible: the whole point of the
   figure is watching mail fall away, and it has to be unmissable. The line
   is the accent and 2px, and the rest of the row steps back with it. */
.gates tr.out .mail { text-decoration: none; }
.gates tr.out.lit .mail {
  color: var(--ink-3);
  text-decoration: line-through;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
}
.gates tr.out.lit td { opacity: .48; }
.gates tr.out.lit td:first-child { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  .gates tr.out td { transition: opacity .35s ease, color .35s ease; }
}

/* ── The table is locked while it is read ────────────────────────────────
   A tall empty track with the panel stuck inside it: scroll position across
   that height decides how many rows have been refused, so four of five
   falling away is something you drive rather than something that has
   already happened by the time you look.

   Both degradations collapse it to a plain table with every refusal already
   applied — the argument is the refusals, and it has to survive without the
   scrolling. */
.gates-track { position: relative; height: 240vh; }
/* The pane fills the viewport and centres its contents, so what locks is
   the whole argument — heading, the paragraph that sets it up, the table
   and the line that closes it — not the table alone with a screen of empty
   page under it, which is what a top-anchored sticky gave.

   svh, not vh: on mobile the collapsing URL bar is inside 100vh, so a 100vh
   pane is taller than what can be seen and its bottom edge sits below the
   fold until you scroll. */
.gates-stick {
  position: sticky;
  top: var(--nav-h);
  min-height: calc(100vh - var(--nav-h));
  min-height: calc(100svh - var(--nav-h));
  display: flex; flex-direction: column; justify-content: center;
  gap: clamp(1rem, 2.5vw, 1.75rem);
  padding-block: clamp(1rem, 3vh, 2.5rem);
}
.gates-stick .sec-hd { margin-bottom: 0; }
.gates-stick .fig-note { margin-top: 0; }
/* Too short to hold all four parts centred — stop centring and let it sit
   from the top rather than clipping the ends off. */
@media (max-height: 52rem) {
  .gates-stick { justify-content: flex-start; }
  .gates-stick .prose { font-size: 1rem; line-height: 1.5; }
}
@media (max-width: 54rem) { .gates-track { height: 200vh; } }
@media (prefers-reduced-motion: reduce) {
  .gates-track { height: auto; }
  .gates-stick { position: static; }
}
html:not(.js) .gates-track { height: auto; }
html:not(.js) .gates-stick { position: static; }

/* The counter, so the sequence says what it is doing. */
.gates-count {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: 12px 16px; border-top: 1px solid var(--line-2);
  font-family: var(--mono); font-size: .75rem; color: var(--ink-3);
}
.gates-count b { color: var(--ink); font-weight: 400; }
.gates-scroll { overflow-x: auto; }
@media (max-width: 54rem) { .gates { min-width: 40rem; } }

/* ======================================================================= *
 * THE CONSTANTS — four tables, printed. The densest block on the page, and
 * deliberately so: this is the one section where showing the actual numbers
 * argues better than any sentence about them.
 * ======================================================================= */
.consts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; }
@media (max-width: 66rem) { .consts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 34rem) { .consts { grid-template-columns: minmax(0, 1fr); } }
.const { border-left: 1px solid var(--line); padding: 20px 20px 22px; }
.const:first-child { border-left: 0; }
@media (max-width: 66rem) {
  .const:nth-child(3) { border-left: 0; }
  .const:nth-child(n+3) { border-top: 1px solid var(--line); }
}
@media (max-width: 34rem) {
  .const { border-left: 0; border-top: 1px solid var(--line); }
  .const:first-child { border-top: 0; }
}
.const h3 {
  font-family: var(--mono); font-size: .6875rem; font-weight: 400;
  letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3);
  margin-bottom: 14px;
}
.const dl { margin: 0; font-family: var(--mono); font-size: .8125rem; }
.const dl > div { display: flex; align-items: baseline; gap: .5rem; padding: 5px 0; }
.const dt { color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.const dl > div::after { content: ""; flex: 1 1 auto; min-width: .75rem; border-bottom: 1px dotted var(--line); transform: translateY(-.3em); }
.const dd { margin: 0; order: 3; color: var(--ink); font-variant-numeric: tabular-nums; font-weight: 500; }
.const dd.neg { color: var(--accent); }
.const p { margin-top: 14px; font-family: var(--mono); font-size: .6875rem; line-height: 1.8; color: var(--ink-3); }

/* ======================================================================= *
 * THE PLANNER — the day grid. Bleeds off the LEFT this time; a page that
 * crops everything to the same edge stops reading as composition and starts
 * reading as a template.
 * ======================================================================= */
.plan-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: clamp(16px, 2vw, 28px); align-items: center; }
.plan-art  { grid-area: 1 / 1 / 2 / 8; margin-left: calc(-1 * (var(--gutter) + 5vw)); }
.plan-copy { grid-area: 1 / 9 / 2 / 13; }
.plan-art .plate { transform: rotate(.8deg); box-shadow: 10px 12px 0 -1px var(--shadow); }
@media (max-width: 62rem) {
  .plan-art  { grid-area: 1 / 1 / 2 / 13; margin-left: calc(-1 * var(--gutter)); }
  .plan-copy { grid-area: 2 / 1 / 3 / 13; margin-top: 2rem; }
}
@media (max-width: 30rem) { .plan-art .plate { transform: none; } }

.hours { display: grid; grid-template-columns: 3.5rem minmax(0, 1fr); position: relative; --hr: 2.6rem; }
.hr-t { height: var(--hr); font-family: var(--mono); font-size: .6875rem; color: var(--p-sub);
        text-align: right; padding: 2px 10px 0 0; border-top: 1px solid var(--p-rule); font-variant-numeric: tabular-nums; }
.hr-c { height: var(--hr); border-top: 1px solid var(--p-rule); border-left: 1px solid var(--p-rule); }
/* One overlay for every block. Nested inside its hour cell, a block that
   spans two hours gets the next cell's border painted across its middle. */
.hr-layer { position: absolute; left: 3.5rem; right: 0; top: 0; bottom: 0; }
.blk {
  position: absolute; left: 6px; right: 6px; border-radius: 3px;
  display: flex; align-items: center; gap: .5rem; padding: 0 10px;
  font-family: var(--mono); font-size: .6875rem; line-height: 1.2; overflow: hidden;
  /* A twenty-minute task is twenty minutes tall, and at 2.6rem an hour that
     is 14px — shorter than the line it has to hold, so the label clipped.
     The floor is the label; below it, the block stops being readable. */
  min-height: 19px;
}
/* A busy block is a hard no-go zone, so it is drawn as one — hatched, not
   tinted. A tint reads as "somewhat busy". */
.blk.busy {
  background-image: repeating-linear-gradient(45deg, var(--p-rule) 0 1px, transparent 1px 6px);
  border: 1px solid var(--p-rule); color: var(--p-sub);
}
.blk.task { background: var(--p-card); border: 1px solid var(--p-ink); color: var(--p-ink); }
.blk.task.pin { border-color: var(--p-margin); border-width: 2px; }
.blk .r { margin-left: auto; color: var(--p-sub); flex: none; }
.blk .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ======================================================================= *
 * TRACKS — cards carrying the user's own sentence.
 * ======================================================================= */
/* Two up. Full width, each card was a short sentence adrift in a very wide
   rectangle — the emptiest thing on the page. */
.tracks { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 54rem) { .tracks { grid-template-columns: 1fr; } }
.trk {
  border: 1px solid var(--line); background: var(--ground);
  padding: 20px 22px 22px;
  display: flex; flex-direction: column;
}
.trk-h { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.trk-h b { font-family: var(--display); font-size: 1.5rem; font-weight: 400; letter-spacing: -.01em; }
.trk-h .w { margin-left: auto; font-family: var(--mono); font-size: .6875rem; color: var(--ink-3); }
.trk-d { margin-top: 10px; font-size: 1.0625rem; line-height: 1.5; color: var(--ink); }
.trk-d::before, .trk-d::after { content: "\201C"; color: var(--ink-3); }
.trk-d::after { content: "\201D"; }
.trk-m { margin-top: auto; padding-top: 16px; display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  font-family: var(--mono); font-size: .6875rem; color: var(--ink-3);
  border: 1px solid var(--line); padding: 3px 8px; white-space: nowrap;
}
.chip.on { border-color: var(--ink); color: var(--ink); }
.trk.off { opacity: .62; }
.lands { margin-top: 16px; font-family: var(--mono); font-size: .8125rem; color: var(--ink-3); }
.lands b { color: var(--ink); font-weight: 400; }

/* ======================================================================= *
 * WHAT IT COST — numbered notes, set as an editorial spread.
 * ======================================================================= */
.notes { columns: 2; column-gap: clamp(28px, 4vw, 56px); }
@media (max-width: 56rem) { .notes { columns: 1; } }
/* Each note gets a rule and its number in the margin. They were six blocks
   of prose in two columns with nothing between them — correct content, no
   structure, so they read as floating. */
.note { break-inside: avoid; border-top: 1px solid var(--line); padding: 16px 0 28px; }
.note-n { font-family: var(--mono); font-size: .6875rem; letter-spacing: .13em; color: var(--accent); }
.note h3 {
  font-family: var(--display); font-weight: 400;
  font-size: 1.5rem; letter-spacing: -.012em; line-height: 1.15;
  margin: 6px 0 8px; max-width: 26ch;
}
.note p { font-size: .9375rem; line-height: 1.6; color: var(--ink-3); max-width: 48ch; }
.note p b { color: var(--ink); font-weight: 400; }

/* ======================================================================= *
 * CLOSE + FOOTER
 * ======================================================================= */
.close { border-top: 1px solid var(--line-2); }
.close-in {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(16px, 2vw, 28px); align-items: end;
}
.close-t { grid-area: 1 / 1 / 2 / 9; }
.close-a { grid-area: 1 / 9 / 2 / 13; padding-bottom: 6px; }
@media (max-width: 62rem) {
  .close-t { grid-area: 1 / 1 / 2 / 13; }
  .close-a { grid-area: 2 / 1 / 3 / 13; margin-top: 2rem; padding-bottom: 0; }
}
.close-a .btn { width: 100%; justify-content: space-between; }
.close-note { margin-top: 14px; font-family: var(--mono); font-size: .75rem; line-height: 1.8; color: var(--ink-3); }

/* The footer is a band, not a line of small print: its own surface, running
   the full width of the page, with the columns a footer is expected to
   have. It was one row of text and it read as the page trailing off. */
.foot { background: var(--ground-2); border-top: 1px solid var(--line-2); }
.foot-grid {
  display: grid; grid-template-columns: minmax(0, 2fr) repeat(3, minmax(0, 1fr));
  gap: 28px clamp(20px, 3vw, 40px);
  padding-block: clamp(32px, 5vw, 48px) 28px;
}
@media (max-width: 62rem) { .foot-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 34rem) { .foot-grid { grid-template-columns: 1fr; } }
.foot-brand .m { font-family: var(--mono); font-size: 1rem; font-weight: 600; letter-spacing: -.01em; }
.foot-brand p { margin-top: 10px; font-size: .9375rem; line-height: 1.55; color: var(--ink-3); max-width: 34ch; }
.foot-col h4 {
  font-family: var(--mono); font-size: .6875rem; font-weight: 400;
  letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 12px;
}
.foot-col ul { list-style: none; margin: 0; padding: 0; }
.foot-col li { margin-bottom: 7px; }
.foot-col a, .foot-col span {
  font-family: var(--mono); font-size: .8125rem; color: var(--ink-3); text-decoration: none;
}
.foot-col a:hover { color: var(--ink); }
.foot-bar {
  display: flex; flex-wrap: wrap; gap: 8px 28px; align-items: baseline;
  border-top: 1px solid var(--line); padding-block: 16px 28px;
  font-family: var(--mono); font-size: .75rem; color: var(--ink-3);
}
.foot-bar .right { margin-left: auto; }
@media (max-width: 52rem) { .foot-bar .right { margin-left: 0; } }

/* ── The hero day is tickable. A day you can tick is the one gesture the
      whole product is about, and it costs one event listener. ─────────── */
.prow.live { cursor: pointer; }
.prow.live:hover .prow-s { color: var(--p-ink); }
.pmark { transition: none; }
@media (prefers-reduced-motion: no-preference) {
  .pmark, .pmark svg, .prow-s { transition: background-color .18s ease, border-color .18s ease, opacity .18s ease, color .18s ease; }
}
