/* site.css — the whole stylesheet.
 *
 * Implements the design handoff Jacob supplied: tokens-root.css verbatim, hooks.css as the base
 * layer, and this site's own class names mapped onto the same language.
 *
 * No webfonts. A font request is a network request and this site claims to make none, so Georgia
 * carries the display voice and a local mono stack carries the prompt.
 *
 * Light only, per the handoff. There is no prefers-color-scheme block anywhere in this file, and
 * `color-scheme: light` is set so form controls do not invert underneath the paper texture.
 *
 * The texture is a same-origin greyscale mask multiplied over --paper, not an opaque bitmap. That
 * way the grain follows the paper token instead of baking a colour in, and the page degrades to
 * flat cream rather than to nothing if the image is unavailable.
 */

/* ============================================================
   the token block, from the design handoff
   light only. no webfonts. no dark override.
   ============================================================ */

:root{
  color-scheme: light;

  /* ---- the eight ---- */
  --ink:          #1B1A17;  /* pen black — all body copy, all outlines */
  --paper:        #FAF6EC;  /* cream ground — never #fff */
  --green:        #3C6357;  /* accent 1 — sage */
  --blue:         #215663;  /* accent 2 — tide */
  --muted:        #6B675E;  /* secondary copy, captions, metadata. 5.2:1 on --paper */
  /* The handoff's contrast table covers --ink on the washes but not --muted, and --muted fails AA
     on two of them: 4.39 on --wash-blue and 4.28 on --wash-flag. Rather than move a token that is
     correct on paper, washed containers use this slightly darker variant — worst case 5.05 across
     all seven grounds, which holds the same visual relationship the paper value has. */
  --muted-on-wash: #605C54;
  --rule:         #8F856C;  /* hairline divider, 1px */
  --rule-strong:  #1B1A17;  /* drawn pen line, 2px — same value as --ink */
  --flag:         #A24827;  /* the only warm colour. errors and nothing else */

  /* ---- font stacks ---- */
  --font-serif: Georgia, "Iowan Old Style", "Palatino Linotype", Palatino, "Times New Roman", serif;
  --font-mono:  ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  /* ---- widths ---- */
  --measure: 62ch;    /* reading column */
  --wide:    1080px;  /* page container */

  /* paper depth — cards sit a shade lighter than the page */
  --paper-card: #FEFCF6;
  --paper-sunk: #F4EEDF;
  --paper-edge: #EAE2CE;

  /* washes, for callouts and selected rows. ink text on all of them. */
  --wash-green: #DEEAE5;
  --wash-blue:  #D6E6E9;
  --wash-cool:  #DCEAF1;
  --wash-flag:  #F2DCD1;

  /* the texture. same-origin, 512px tile, greyscale multiply mask. */
  --paper-tile: url("paper-tile.png");

  /* line weights */
  --stroke-hair: 1px;
  --stroke-pen:  2px;
  --stroke-mark: 3px;

  /* the house shadow: no blur, solid ink, offset only */
  --shadow-ink:       3px 3px 0 var(--ink);
  --shadow-ink-tight: 2px 2px 0 var(--ink);
  --shadow-ink-lift:  5px 5px 0 var(--ink);

  /* corners. nothing is uniformly round. */
  --radius-a:    14px 18px 12px 20px / 18px 12px 20px 14px;
  --radius-b:    22px 16px 24px 14px / 14px 24px 16px 22px;
  --radius-pill: 999px;
  --radius-tick: 6px 8px 5px 9px;

  /* spacing, 4px root */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px; --s5: 24px;
  --s6: 32px; --s7: 48px; --s8: 64px; --s9: 96px;

  /* type scale, in a lowercase Georgia setting */
  --t-display: 44px;
  --t-head:    28px;
  --t-sub:     21px;
  --t-body:    19px;
  --t-small:   16px;
  --t-label:   13px;

  --lh-tight: 1.12;
  --lh-snug:  1.3;
  --lh-body:  1.6;

  --track-display: .06em;
  --track-label:   .12em;

  /* motion. short, no overshoot. */
  --ease: cubic-bezier(.2,.7,.3,1);
  --dur-fast: 120ms;
  --dur-base: 200ms;
}

/* ---------- ground ---------- */

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

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

body {
  background-color: var(--paper);
  background-image: var(--paper-tile);
  background-repeat: repeat;
  background-size: 512px 512px;
  /* The tile is a greyscale mask, so multiplying it over the paper colour tints the grain rather
     than replacing the ground. Change --paper and the grain follows. */
  background-blend-mode: multiply;
  background-attachment: fixed;
  color: var(--ink);
  font-family: var(--font-serif);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  text-transform: lowercase;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* Proper nouns, references, code and anything quoted keep their own capitals. */
.cap, code, kbd, abbr, .ref, .tool-name, cite, #prompt-out { text-transform: none; }


/* ---------- type ---------- */

h1, h2, h3, h4 { font-weight: 400; line-height: var(--lh-snug); font-family: var(--font-serif); }
/* Caps and tracked — the display voice, and the only place caps appear besides the wordmark. A tool
   page opts out with .cap, because a product's name is spelled the way its maker spells it ("one
   sec", "ScreenZen") and shouting it would misreport it. */
h1 {
  font-size: clamp(30px, 5vw, var(--t-display));
  line-height: var(--lh-tight);
  text-transform: uppercase;
  letter-spacing: var(--track-display);
  margin: 0 0 var(--s4);
}
h1.cap { letter-spacing: 0; }
/* Section headings carry a drawn rule beneath them — the same 2px ink line as the masthead, so the
   page reads as ruled paper rather than as text with gaps in it. h3 takes the hairline instead, which
   makes the two levels tell apart at a glance without a size change doing all the work. */
h2 {
  font-size: var(--t-head);
  margin: var(--s7) 0 var(--s4);
  padding-bottom: var(--s2);
  border-bottom: var(--stroke-pen) solid var(--rule-strong);
  max-width: var(--wide);
}
h3 {
  font-size: var(--t-sub);
  margin: var(--s6) 0 var(--s3);
  padding-bottom: var(--s1);
  border-bottom: var(--stroke-hair) solid var(--rule);
  max-width: var(--measure);
}
h4 { font-size: var(--t-body); margin: var(--s5) 0 var(--s2); }

/* Inside a card or a callout the rule would fight the border it already sits in. */
.note h3, .note h4, .notice h3, .notice h4, .match h3, .match h4,
.recipe h3, .recipe h4, #diagnosis h3, .recipe-detail h3, .recipe-detail h4,
.tool-card h3, .tool-card h4 {
  border-bottom: 0; padding-bottom: 0; max-width: none;
}
/* A numbered rubric section is a heading and a marker at once; keep the rule short of the page edge. */
#mechanisms h2, #tools h2 { max-width: var(--wide); }

p { margin: 0 0 var(--s4); max-width: var(--measure); text-wrap: pretty; }
ul, ol { margin: 0 0 var(--s4); padding-left: var(--s5); max-width: var(--measure); }
li { margin-bottom: var(--s2); }
dl { margin: 0 0 var(--s4); }
strong { font-weight: 700; }
em { font-style: italic; }

small, .small { font-size: var(--t-small); line-height: 1.55; }
/* Small labels are lowercase and tracked, not uppercase — uppercase micro-labels fight the house
   style once everything else is down. */
.label {
  font-size: var(--t-label); letter-spacing: var(--track-label);
  color: var(--muted); display: inline-block;
}
.lede { font-size: var(--t-sub); line-height: 1.45; }
.muted { color: var(--muted); }
.flag { color: var(--flag); }
.measure, .narrow { max-width: var(--measure); }

a { color: var(--blue); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { text-decoration-style: wavy; }

a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible,
.opt:has(input:focus-visible), .recipe:has(input:focus-visible) {
  outline: var(--stroke-pen) solid var(--blue);
  outline-offset: 3px;
}
::selection { background: var(--wash-cool); }

hr, .rule { border: 0; border-top: var(--stroke-pen) solid var(--rule-strong); margin: var(--s6) 0; }
hr.hair, .rule.hair { border-top: var(--stroke-hair) solid var(--rule); }

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--paper-card); color: var(--ink);
  padding: var(--s3) var(--s4);
  border: var(--stroke-pen) solid var(--ink);
  border-radius: var(--radius-a);
  box-shadow: var(--shadow-ink);
  z-index: 20;
}
.skip:focus { left: var(--s3); top: var(--s3); }

.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ---------- page frame ---------- */

main, .page { width: 100%; max-width: var(--wide); margin: 0 auto; padding: var(--s5) var(--s6) var(--s8); }
main { flex: 1; }
main > h2:first-of-type { margin-top: var(--s6); }

/* masthead */
header.site { width: 100%; }
header.site > div, .masthead {
  max-width: var(--wide); margin: 0 auto;
  padding: var(--s5) var(--s6) var(--s4);
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s5);
  flex-wrap: wrap;
  border-bottom: var(--stroke-pen) solid var(--rule-strong);
}
header.site .home, .wordmark {
  font-size: 20px; line-height: 1.1;
  text-transform: uppercase; letter-spacing: .07em;
  color: var(--ink); text-decoration: none;
  max-width: 22ch;
}
/* The nav is set in the display voice: Georgia, caps, tracked — the same treatment as the wordmark
   and the page title, so the three read as one system instead of the nav looking like body copy. */
header.site nav {
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5);
  font-family: var(--font-serif);
  font-size: 15px;
  text-transform: uppercase;
  letter-spacing: var(--track-display);
}
header.site nav a {
  color: var(--ink);
  text-decoration: none;
  padding-bottom: 2px;
  border-bottom: var(--stroke-hair) solid var(--rule);
}
header.site nav a:hover { border-bottom-color: var(--ink); border-bottom-width: var(--stroke-pen); }
header.site nav a[aria-current='page'] {
  color: var(--green);
  border-bottom: var(--stroke-pen) solid var(--green);
}

footer.site { margin-top: auto; }
footer.site > div, .footer {
  max-width: var(--wide); margin: 0 auto;
  padding: var(--s4) var(--s6) var(--s7);
  margin-top: var(--s8);
  border-top: var(--stroke-hair) solid var(--rule);
  font-size: var(--t-small); color: var(--muted);
}
footer.site p { margin-bottom: var(--s2); }

/* ---------- buttons ---------- */

button, .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  font-family: inherit; font-size: var(--t-small); text-transform: lowercase;
  padding: 10px 20px; cursor: pointer;
  background: var(--blue); color: var(--paper);
  border: var(--stroke-pen) solid var(--ink);
  border-radius: var(--radius-a);
  box-shadow: var(--shadow-ink);
  transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
  text-decoration: none;
}
button:hover, .btn:hover { transform: translate(1px, 1px); box-shadow: var(--shadow-ink-tight); }
button:active, .btn:active { transform: translate(3px, 3px); box-shadow: none; }
.btn.green, button.green { background: var(--green); }
.btn.quiet, button.quiet { background: var(--paper-card); color: var(--ink); }
.btn.ghost, button.ghost {
  background: none; border-color: transparent; box-shadow: none; transform: none; padding: 10px 4px;
  color: var(--blue);
}
.btn.ghost:hover, button.ghost:hover { text-decoration: underline wavy; transform: none; box-shadow: none; }
.btn.lg, button.lg { font-size: var(--t-body); padding: 13px 26px; }
.btn.sm, button.sm { font-size: var(--t-label); letter-spacing: 0; padding: 6px 14px; }
button[disabled], .btn[disabled], .btn[aria-disabled='true'] { opacity: .45; pointer-events: none; }

/* The bottom margin has to clear the 3px offset shadow as well as the button, or whatever follows
   sits under it. */
.actions { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; margin: var(--s6) 0 var(--s5); }

/* ---------- notices ---------- */

.note, .notice {
  border: var(--stroke-pen) solid var(--ink);
  background: var(--wash-green);
  padding: var(--s4) var(--s5);
  border-radius: var(--radius-b);
  margin: var(--s5) 0;
  max-width: var(--measure);
  font-size: var(--t-small);
}
.note.cool, .notice.cool { background: var(--wash-cool); }
.note.plain, .notice.plain { background: var(--paper-card); }
.note.green, .notice.green { background: var(--wash-green); }
.note.loud, .notice.loud { background: var(--wash-flag); border-color: var(--flag); }
.note > :last-child, .notice > :last-child { margin-bottom: 0; }
.note h3, .note h4, .notice h3, .notice h4 {
  font-size: var(--t-label); letter-spacing: var(--track-label);
  color: var(--muted); margin: 0 0 var(--s2);
}
.note.loud h3, .note.loud h4 { color: var(--flag); }
/* Secondary copy sits on a coloured ground here, so it takes the wash variant. */
.note .muted, .notice .muted, .note h3, .note h4, .notice h3, .notice h4,
.note .label, .notice .label, .note small, .notice small {
  color: var(--muted-on-wash);
}
.note.loud h3, .note.loud h4 { color: var(--flag); }
.opt.on .note, .opt.on .onote { color: var(--paper-edge); }

blockquote {
  border-left: var(--stroke-mark) solid var(--green);
  padding-left: var(--s4);
  margin: var(--s5) 0;
  max-width: var(--measure);
  font-style: italic;
}
blockquote em, blockquote i { font-style: normal; }

details { max-width: var(--measure); margin-bottom: var(--s4); }
summary { cursor: pointer; color: var(--blue); }

/* ---------- the instrument ---------- */

/* The progress row is a line of dots, one per question, and sticks to the top as the form scrolls. */
.progress {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  /* Opaque, so the form does not show through as it scrolls under. The attachment matches the
     body's so the grain lines up rather than showing a seam at the sticky edge. */
  background-color: var(--paper);
  background-image: var(--paper-tile);
  background-size: 512px 512px;
  background-blend-mode: multiply;
  background-attachment: fixed;
  padding: var(--s3) 0;
  margin-bottom: var(--s5);
  border-bottom: var(--stroke-hair) solid var(--rule);
  max-width: var(--measure);
}
.progress .bar { display: flex; align-items: center; gap: 6px; flex: 0 1 auto; flex-wrap: wrap; }
.progress .bar span {
  display: block; width: 10px; height: 10px; border-radius: 50%;
  border: var(--stroke-pen) solid var(--ink); background: none;
  transition: background var(--dur-base) var(--ease);
}
.progress .bar span.done { background: var(--ink); }
.progress .bar span.now { width: 14px; height: 14px; background: var(--blue); }
.progress .label { color: var(--muted); }

.qblock { max-width: var(--measure); margin: 0 0 var(--s7); }
.qblock[hidden] { display: none; }
fieldset { border: 0; padding: 0; margin: 0; max-width: var(--measure); }
legend { font-size: var(--t-head); line-height: var(--lh-snug); padding: 0; margin-bottom: var(--s4); }
.qnum { color: var(--muted); font-variant-numeric: tabular-nums; }
.help { font-size: var(--t-small); color: var(--muted); margin-bottom: var(--s4); }

.opts { display: flex; flex-direction: column; gap: var(--s3); margin: 0 0 var(--s4); padding: 0; list-style: none; }
.opts li { margin: 0; }

.opt {
  display: flex; align-items: flex-start; gap: var(--s4); width: 100%; text-align: left;
  font-family: inherit; font-size: var(--t-body); text-transform: lowercase;
  background: var(--paper-card); color: var(--ink);
  border: var(--stroke-pen) solid var(--ink);
  border-radius: var(--radius-a);
  box-shadow: var(--shadow-ink);
  padding: var(--s4) var(--s5); cursor: pointer;
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease),
              background var(--dur-base) var(--ease);
}
.opt:hover { transform: translate(-1px, -1px); box-shadow: var(--shadow-ink-lift); }
.opt::before {
  content: ""; flex: 0 0 auto; width: 20px; height: 20px; margin-top: 5px; border-radius: 50%;
  border: var(--stroke-pen) solid var(--ink); background: none;
}
/* The real input stays in the markup and keeps every native affordance — keyboard, form semantics,
   :checked, and the announced state — because ::before only draws the marker. It is stretched over
   the whole option and made transparent rather than shrunk to a pixel: a 1px input is unclickable
   by a pointer and unreachable by anything driving the page, so the whole row has to be the target. */
/* Stacking, deliberately: the transparent input sits ON TOP of the row so the entire option is one
   hit target for a pointer and for anything driving the page. The label text underneath is not
   separately selectable, which matches how a single control should behave. The one exception is the
   free-text field, which is lifted above the overlay so it can still be typed into. */
.opt { position: relative; }
.opt input {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0;
  opacity: 0; cursor: pointer; z-index: 1;
}
.opt[aria-checked="true"], .opt.on {
  background: var(--blue); color: var(--paper); transform: none; box-shadow: var(--shadow-ink);
}
.opt[aria-checked="true"]::before, .opt.on::before {
  border-color: var(--paper);
  background: radial-gradient(circle, var(--paper) 0 4px, transparent 4px);
}
.opt .txt { display: block; }
.opt .note, .opt .onote {
  display: block; font-size: var(--t-small); color: var(--muted); margin-top: 2px;
  border: 0; padding: 0; background: none; max-width: none;
}
.opt[aria-checked="true"] .note, .opt.on .note,
.opt[aria-checked="true"] .onote, .opt.on .onote { color: var(--paper-edge); }
.opt .rank {
  font-size: var(--t-label); letter-spacing: var(--track-label);
  color: var(--muted); margin-left: var(--s2);
}
.opt.on .rank { color: var(--paper-edge); }
/* A multi-select marker is a squared-off tick box; a single-select one stays a circle. */
.opts.multi .opt::before { border-radius: var(--radius-tick); }

/* Above the overlay, or it could not be typed into. */
.opt input[type="text"] {
  position: relative; z-index: 2; inset: auto; opacity: 1; width: 100%; height: auto; cursor: text;
  font: inherit; text-transform: none; margin-top: var(--s2);
  background: var(--paper); color: var(--ink);
  border: var(--stroke-hair) solid var(--rule);
  border-radius: var(--radius-tick); padding: var(--s2) var(--s3);
}

.scale2 { margin-bottom: var(--s5); }
.scale2 .sub { font-size: var(--t-body); margin-bottom: var(--s3); }

/* the slider */
.slider-wrap { margin-bottom: var(--s4); }
.slider-ends {
  display: flex; justify-content: space-between; gap: var(--s4);
  font-size: var(--t-label); letter-spacing: var(--track-label); color: var(--muted);
  margin-bottom: var(--s2);
}
input[type="range"] {
  width: 100%; margin: 0; accent-color: var(--blue);
  height: 28px; background: none;
}
/* A short descriptive label, not a sentence narrating the reader's intent back at them. */
.slider-live { margin-top: var(--s2); color: var(--ink); font-size: var(--t-small); min-height: 1.6em; }

.err {
  border: var(--stroke-pen) solid var(--flag);
  background: var(--wash-flag);
  color: var(--ink);
  padding: var(--s3) var(--s4);
  border-radius: var(--radius-a);
  margin: var(--s3) 0 0;
  max-width: var(--measure);
  font-size: var(--t-small);
}
.err strong { color: var(--flag); }
.err:empty { display: none; }

/* ---------- the diagnosis ---------- */

#diagnosis {
  border: var(--stroke-pen) solid var(--ink);
  background: var(--paper-card);
  box-shadow: var(--shadow-ink);
  border-radius: var(--radius-b);
  padding: var(--s5) var(--s6);
  margin: 0 0 var(--s7);
  max-width: var(--wide);
}
#diagnosis h2 { margin: 0 0 var(--s3); }
#diagnosis h3 { margin-top: var(--s5); }
#diagnosis p { font-size: var(--t-body); margin-bottom: var(--s3); }
#diagnosis .label { margin-bottom: var(--s2); }
#diagnosis > :last-child { margin-bottom: 0; }
/* Nested callouts inside the card sit on the wash rather than repeating the card treatment. */
#diagnosis .note { box-shadow: none; }

/* ---------- matches ---------- */

.match {
  display: grid; grid-template-columns: auto 1fr auto; gap: var(--s4) var(--s5);
  align-items: start;
  border: var(--stroke-pen) solid var(--ink);
  background: var(--paper-card);
  box-shadow: var(--shadow-ink);
  border-radius: var(--radius-b);
  padding: var(--s5);
  margin: 0 0 var(--s4);
}
.match .rank { font-size: 34px; line-height: 1; color: var(--blue); min-width: 38px; }
.match .body { min-width: 0; }
.match h3 { margin: 0 0 var(--s2); }
.match h4 {
  font-size: var(--t-label); letter-spacing: var(--track-label); color: var(--muted);
  margin: var(--s4) 0 var(--s2);
}
.match p { margin: 0 0 var(--s3); font-size: var(--t-small); }
.match > .tiers { display: flex; flex-direction: column; gap: 6px; align-items: flex-end; }
.match .tool-name { font-size: var(--t-sub); }

@media (max-width: 640px) {
  .match { grid-template-columns: auto 1fr; }
  .match > .tiers { grid-column: 1 / -1; flex-direction: row; align-items: flex-start; flex-wrap: wrap; }
}

.tier {
  display: inline-flex; align-items: center;
  font-size: var(--t-label); letter-spacing: var(--track-label);
  padding: 3px 11px; border-radius: var(--radius-pill);
  border: var(--stroke-hair) solid var(--ink);
  background: var(--paper-sunk); color: var(--ink);
  white-space: nowrap;
}
.tier.t1 { background: var(--green); color: var(--paper); border-color: var(--ink); }
.tier.t2 { background: var(--wash-green); color: var(--ink); }
.tier.kind { background: var(--wash-cool); color: var(--ink); }
.badge-row { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; margin-bottom: var(--s4); }

/* definition lists */
.match dl, .recipe dl, dl.facts, dl.match {
  margin: 0; display: grid; grid-template-columns: auto 1fr;
  gap: var(--s1) var(--s4); font-size: var(--t-small);
  border-top: var(--stroke-hair) solid var(--rule); padding-top: var(--s3);
  max-width: var(--measure);
}
.match dl dt, .recipe dl dt, dl.facts dt, dl.match dt {
  color: var(--muted); font-size: var(--t-label); letter-spacing: var(--track-label);
  align-self: center;
}
.match dl dd, .recipe dl dd, dl.facts dd, dl.match dd { margin: 0; }
@media (max-width: 520px) {
  .match dl, .recipe dl, dl.facts, dl.match { grid-template-columns: 1fr; }
  .match dl dt, dl.facts dt, dl.match dt { margin-top: var(--s2); }
}

.terms { list-style: none; padding: 0; margin: 0 0 var(--s3); font-size: var(--t-small); }
.terms li { display: flex; gap: var(--s3); margin-bottom: var(--s1); }
.t-label {
  flex: 0 0 11rem; color: var(--muted);
  font-size: var(--t-label); letter-spacing: var(--track-label);
}
@media (max-width: 520px) { .terms li { flex-direction: column; gap: 0; } .t-label { flex: none; } }

.unverified { color: var(--flag); }
.penalty { color: var(--flag); }

/* ---------- recipes ---------- */

.recipe-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--s4); margin: 0 0 var(--s6);
}
.recipe {
  display: flex; flex-direction: column; gap: var(--s2);
  border: var(--stroke-pen) solid var(--ink);
  background: var(--paper-card);
  box-shadow: var(--shadow-ink);
  border-radius: var(--radius-b);
  padding: var(--s5);
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease),
              background var(--dur-base) var(--ease);
}
.recipe:hover { transform: translate(-1px, -1px); box-shadow: var(--shadow-ink-lift); }
.recipe input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
/* Chosen is pressed in: the shadow flattens and the tile moves toward the page. */
.recipe.chosen {
  background: var(--wash-cool);
  transform: translate(3px, 3px);
  box-shadow: none;
}
.recipe h3, .recipe .recipe-name { font-size: var(--t-sub); margin: 0; line-height: var(--lh-snug); }
.recipe > .label, .recipe .recipe-id { margin-bottom: 0; }
.recipe p, .recipe .recipe-mech { font-size: var(--t-small); margin: 0; color: var(--ink); }
.recipe .recipe-meta {
  font-size: var(--t-label); letter-spacing: var(--track-label); color: var(--muted);
}
.recipe.chosen .recipe-meta, .recipe.chosen .label, .recipe.chosen .recipe-id { color: var(--muted-on-wash); }
.recipe .recipe-why { font-size: var(--t-small); color: var(--green); margin-top: var(--s1); }
.recipe.chosen .recipe-why { color: var(--blue); }
.recipe .tier { margin-right: 6px; align-self: flex-start; }

.howto-block { margin: var(--s4) 0 0; }
.howto-block h4 {
  font-size: var(--t-label); letter-spacing: var(--track-label); color: var(--muted);
  margin: 0 0 var(--s2);
}
.howto { margin: var(--s2) 0 var(--s3); padding: 0 0 0 var(--s5); font-size: var(--t-small); }
.howto li { margin-bottom: var(--s2); }
.howto li::marker { color: var(--muted); }
.howto.plain { list-style: none; padding-left: 0; }
.howto.plain li {
  display: flex; gap: var(--s3); padding-bottom: var(--s2);
  border-bottom: var(--stroke-hair) solid var(--rule);
}
.howto.plain li:last-child { border-bottom: 0; }

/* ---------- the prompt ---------- */

#prompt-out, pre {
  display: block; width: 100%;
  font-family: var(--font-mono); font-size: 15px; line-height: 1.55;
  text-transform: none;
  background: var(--paper-sunk); color: var(--ink);
  border: var(--stroke-pen) solid var(--ink);
  border-radius: var(--radius-a);
  padding: var(--s4) var(--s5);
  white-space: pre-wrap; word-break: break-word; overflow-x: auto;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.7), inset 0 -1px 0 rgba(27,26,23,.06);
  max-height: 30rem;
  margin: 0 0 var(--s4);
}
#prompt-out { white-space: pre; }
code { font-family: var(--font-mono); font-size: .88em; }

/* ---------- tables ---------- */

.scroll-x { overflow-x: auto; margin-bottom: var(--s4); }
table { border-collapse: collapse; width: 100%; font-size: var(--t-small); }
th, td {
  text-align: left; padding: var(--s2) var(--s4) var(--s2) 0;
  border-bottom: var(--stroke-hair) solid var(--rule); vertical-align: top;
}
th {
  border-bottom: var(--stroke-pen) solid var(--rule-strong); white-space: nowrap;
  font-size: var(--t-label); letter-spacing: var(--track-label); color: var(--muted);
}
td.num, th.num { text-align: right; padding-right: var(--s4); font-variant-numeric: tabular-nums; }
.thin { color: var(--flag); font-weight: 700; }

/* The axis bars on a tool page. Scoped to .axis-bar rather than to any span in the cell: the
   uncoded axes put a "not coded" label in the same cell, and painting that blue put ink text on a
   blue ground at 2.13:1. */
.axes td.barcell { width: 40%; min-width: 6rem; padding-right: 0; }
.axes td.barcell .axis-bar {
  display: block; height: 8px; background: var(--blue);
  border: var(--stroke-hair) solid var(--ink);
}
.axes td.barcell .null { color: var(--muted); background: none; }

/* ---------- sketches ---------- */

.sketch { display: block; max-width: 100%; height: auto; mix-blend-mode: multiply; }
figure.sketch-fig { margin: 0; display: inline-block; }
figure.sketch-fig figcaption {
  margin-top: var(--s2); font-size: var(--t-small); color: var(--muted);
  text-align: center; font-style: italic;
}

/* ---------- motion respect ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; animation-duration: 0s !important; }
  .opt:hover, .recipe:hover, .btn:hover, button:hover { transform: none; }
}

/* ---------- print ---------- */

@media print {
  body { background: #fff; }
  .progress, .actions, .skip { display: none; }
  .match, .recipe, #diagnosis, .opt { box-shadow: none; break-inside: avoid; }
}

/* ---------- the fork: use something, or build something ---------- */

/* Two routes, presented as a real choice rather than as section order — the site's claim is that a
   person can pick or make the thing that fits them. Related to .btn but deliberately not a button:
   wider, two-line, and drawn with the heavier pen weight so it reads as a route rather than an
   action. */
.choices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  gap: var(--s4);
  margin: 0 0 var(--s7);
  max-width: var(--wide);
}

.choice {
  display: flex; flex-direction: column; gap: var(--s1);
  padding: var(--s4) var(--s5);
  background: var(--paper-card);
  color: var(--ink);
  border: var(--stroke-mark) solid var(--ink);
  border-radius: var(--radius-b);
  box-shadow: var(--shadow-ink);
  text-decoration: none;
  transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease),
              background var(--dur-base) var(--ease);
}
.choice:hover {
  background: var(--wash-cool);
  transform: translate(1px, 1px);
  box-shadow: var(--shadow-ink-tight);
  text-decoration: none;
}
.choice:active { transform: translate(3px, 3px); box-shadow: none; }
.choice-head {
  font-family: var(--font-serif); font-size: var(--t-sub); line-height: var(--lh-snug);
}
/* The arrow says "this moves you down the page" without spelling it out. */
.choice-head::after { content: " ↓"; color: var(--blue); }
.choice-sub { font-size: var(--t-small); color: var(--muted); }
.choice:hover .choice-sub { color: var(--muted-on-wash); }

/* ---------- resources ---------- */

.harm-group { margin-bottom: var(--s7); }
.tool-list { list-style: none; padding: 0; margin: 0; max-width: var(--wide); }
.tool-list > li {
  border-top: var(--stroke-hair) solid var(--rule);
  padding: var(--s4) 0;
  margin: 0;
  max-width: var(--measure);
}
.tool-list > li:last-child { border-bottom: var(--stroke-hair) solid var(--rule); }
.tool-list-head { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: baseline; margin-bottom: var(--s2); }
.tool-list p { margin-bottom: var(--s1); }

.recipe-detail {
  border-left: var(--stroke-mark) solid var(--rule-strong);
  padding: 0 0 0 var(--s4);
  margin-bottom: var(--s5);
  max-width: var(--measure);
}
.recipe-detail h3 { margin-top: 0; }
.recipe-detail > :last-child { margin-bottom: 0; }

/* ---------- resources: the four problems, and a grid under each ---------- */

/* A jump nav so no group is more than one click away. Drawn as the tile language in miniature —
   ink border, asymmetric corner, offset shadow that flattens on press. */
.group-nav {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  gap: var(--s3);
  margin: 0 0 var(--s6);
  max-width: var(--wide);
}
.group-nav a {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3);
  padding: var(--s3) var(--s4);
  background: var(--paper-card); color: var(--ink); text-decoration: none;
  border: var(--stroke-pen) solid var(--ink);
  border-radius: var(--radius-a);
  box-shadow: var(--shadow-ink-tight);
  font-size: var(--t-small);
  transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease),
              background var(--dur-base) var(--ease);
}
.group-nav a:hover { background: var(--wash-cool); transform: translate(1px, 1px); box-shadow: none; }
.group-nav-n {
  font-size: var(--t-label); letter-spacing: var(--track-label); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.group-nav a:hover .group-nav-n { color: var(--muted-on-wash); }

/* Each problem is a <details>, open by default. Its summary sticks while the grid scrolls past, so
   you always know which of the four you are inside, and it doubles as the fold control. */
.harm-group { margin-bottom: var(--s7); max-width: var(--wide); }
.harm-group > summary {
  position: sticky; top: 0; z-index: 4;
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s4);
  cursor: pointer;
  font-family: var(--font-serif); font-size: var(--t-sub);
  background-color: var(--paper);
  background-image: var(--paper-tile);
  background-size: 512px 512px;
  background-blend-mode: multiply;
  background-attachment: fixed;
  padding: var(--s3) 0 var(--s2);
  border-bottom: var(--stroke-pen) solid var(--rule-strong);
  list-style: none;
}
.harm-group > summary::-webkit-details-marker { display: none; }
/* A drawn caret rather than the platform triangle, so it matches the pen language. */
.harm-name::before {
  content: "–"; color: var(--green); display: inline-block; width: 1.1em;
}
.harm-group:not([open]) .harm-name::before { content: "+"; }
.harm-count {
  font-size: var(--t-label); letter-spacing: var(--track-label); color: var(--muted);
  white-space: nowrap;
}
.harm-group > summary:hover .harm-name { color: var(--green); }
.harm-group > summary:focus-visible { outline: var(--stroke-pen) solid var(--blue); outline-offset: 2px; }
.harm-body { padding-top: var(--s3); }

.tool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap: var(--s4);
  list-style: none; padding: 0; margin: var(--s4) 0 var(--s4);
  max-width: var(--wide);
}
.tool-card {
  display: flex; flex-direction: column; gap: var(--s2);
  margin: 0;
  padding: var(--s4);
  background: var(--paper-card);
  border: var(--stroke-pen) solid var(--ink);
  border-radius: var(--radius-b);
  box-shadow: var(--shadow-ink);
}
.tool-card h4 { margin: 0; font-size: var(--t-sub); line-height: var(--lh-snug); }
.tool-card p { margin: 0; max-width: none; }
.tool-card .badge-row { margin: 0; gap: var(--s1); }
.tool-card .tier { font-size: 11px; padding: 2px 8px; }
.tool-card-foot { margin-top: auto; line-height: 1.5; }

/* ---------- folded reference blocks ---------- */

/* Recipes are looked up, not read through, so each is folded shut with enough on the summary line to
   choose by. Drawn as a ruled row rather than a card: a stack of thirty cards is noisier than a list
   of thirty lines, and the card treatment is doing work elsewhere. */
.recipe-fold { max-width: var(--measure); border-bottom: var(--stroke-hair) solid var(--rule); }
.recipe-fold > summary {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s4);
  cursor: pointer; padding: var(--s3) 0; list-style: none;
}
.recipe-fold > summary::-webkit-details-marker { display: none; }
.fold-name { font-family: var(--font-serif); font-size: var(--t-body); }
.fold-name::before { content: "+"; color: var(--green); display: inline-block; width: 1.2em; }
.recipe-fold[open] .fold-name::before { content: "–"; }
.recipe-fold[open] > summary { border-bottom: var(--stroke-hair) solid var(--rule); }
.recipe-fold > summary:hover .fold-name { color: var(--green); }
.recipe-fold > summary:focus-visible { outline: var(--stroke-pen) solid var(--blue); outline-offset: 2px; }
.fold-meta {
  font-size: var(--t-label); letter-spacing: var(--track-label); color: var(--muted);
  white-space: nowrap; text-align: right;
}
.fold-body { padding: var(--s4) 0 var(--s4) var(--s5); }
.fold-body > :last-child { margin-bottom: 0; }
/* The target of a jump gets the wash briefly, so it is obvious which one opened. */
.recipe-fold:target > summary { background: var(--wash-cool); }

/* ---------- the epigraph ---------- */

/* Set apart with the pen rule rather than a card: an epigraph is a held breath before the page
   starts, and a bordered box would make it another block of furniture. */
.epigraph {
  margin: 0 0 var(--s6);
  max-width: var(--measure);
  border-left: var(--stroke-mark) solid var(--green);
  padding: var(--s2) 0 var(--s2) var(--s5);
}
.epigraph blockquote { border: 0; margin: 0; padding: 0; font-style: normal; }
/* The site un-italicises <em> inside a blockquote, because blockquotes are italic by default there.
   This one is not, so its emphasis has to be put back. */
.epigraph em, .epigraph i { font-style: italic; }
.epigraph blockquote p {
  font-size: var(--t-head); line-height: var(--lh-snug); margin: 0 0 var(--s2);
  text-transform: none;   /* a quotation keeps the capitals its author used */
}
.epigraph figcaption {
  font-size: var(--t-label); letter-spacing: var(--track-label); color: var(--muted);
  text-transform: none;
}

