/* ==========================================================================
   Ryan Purrington | Menu Engineering Consultant
   Editorial design system.
   Brand: deep green #18382E with gold #E3B55C as the action accent.
   Data:  good #109468, bad #C2451F, info #3B5BA5. Never used decoratively.
   ========================================================================== */

:root {
  --ink:        #161A18;
  --ink-2:      #353B37;
  --ink-3:      #58605B;
  --ink-4:      #8E9690;
  --white:      #FFFFFF;
  --paper:      #F7F9F7;
  --paper-2:    #EEF2EF;
  --paper-3:    #E4EAE6;
  --line:       #DCE3DD;
  --line-2:     #C2CCC5;

  /* Control edges. --line and --line-2 are decorative hairlines and are far
     too light to bound an interactive control; these meet the 3:1 that
     WCAG 1.4.11 requires for a UI component boundary. */
  --edge:       #79817C;
  --edge-dark:  #79817C;

  /* Deep green. The brand ground for the hero, the proof bands, the founder
     block and the footer, carrying roughly a quarter of the page against the
     cream. It is dark enough to sit deltaE 33.3 from --good, so it can be a
     brand colour without making the emerald in a figure ambiguous; a mid
     forest green measured 16.3 and could not, which is why this is green and
     not that green.

     --on-green-2 exists because the warm charcoal that reads as secondary text
     on cream measures 1.85:1 on this ground and is unusable there. Anything
     quiet inside a green section takes this instead. */
  /* The ground is white, not cream. The old #F5F0E7 had a 14 point R to B
     spread at 38.6 degrees, which is a measurable orange cast: that was the
     peach. Every neutral is now within 10 points of balanced and carries a
     faint green rather than orange bias, so the page reads white against the
     brand green instead of warm against it.

     The one warm thing left is the closing ask. --brass-wash is still a soft
     amber tint, deliberately: it is 5% of the page, it sits at the conversion
     moment, and amber only means act here if it is scarce. */
  --green:      #18382E;
  --green-2:    #214A3C;
  --green-wash: #E7EDEA;
  --on-green:   #F4F7F4;
  --on-green-2: #A9B9B1;
  /* The hairline that separates two adjacent green grounds. The --green to
     --green-2 luminance step is 0.0233, under a third of an ordinary band step
     on cream, so a tonal change alone does not make the edge: the closing ask
     and the footer would fuse into one dark mass exactly as ink did. This
     reads at 2.62:1 against --green, which a 1px line needs. */
  --green-line: #52796B;

  /* The amber pair the buttons used to hardcode. --on-accent is near black
     because white on this amber is 2.31:1: the fill is light, so its label
     must be dark and its border must be --brass-2 to clear the 3:1 that WCAG
     1.4.11 asks of a component boundary. --brass-2 is also the text safe amber
     for links on cream, at 4.99:1. */
  --on-accent:    #161A18;

  /* The focus ring, and it is its own token for a measured reason. It was
     --info blue, which is 6.15:1 on white and 1.96:1 on the brand green:
     anyone tabbing through the Results band or the founder block had a ring
     they could not see. A ring must clear 3:1 on every ground it can land on,
     and this mid amber is the only value that does on all three at once
     (3.24 white, 3.42 card, 3.73 green). */
  --focus:        #AE8420;
  --accent-hover: #EFC57A;

  /* Brand. One accent, and it means "action": every CTA, link and emphasis.
     Nothing else competes with it, so the call to action always wins the page. */
  --brass:      #E3B55C;
  --brass-2:    #8A6512;
  --brass-wash: #FBF7EE;

  /* Data signals. Never used for brand or decoration, so a colour in a figure
     always carries meaning: above target, below target, or analytic. */
  --good:       #047857;
  --good-2:     #046045;
  --good-wash:  #E3F3ED;
  --bad:        #C2451F;
  --bad-2:      #8F3115;
  --bad-wash:   #FBEBE6;
  --info:       #3B5BA5;
  --info-2:     #2A4478;
  --info-wash:  #EAEFF9;

  /* Literata for headings, Plex Sans for everything functional. Measured the
     market first: the six sites ranking for menu engineering all run a
     workhorse sans, but four of the five premium restaurant groups the buyers
     actually operate lead with a classical serif (Hawksmoor Palatino, Dishoom
     Cheltenham, St John Georgia, The Ivy Times). Sans is the B2B trade voice;
     serif is the hospitality premium voice. Earlier serif attempts failed
     because Fraunces, Newsreader and Spectral are contemporary designed faces,
     and the restaurant register is quiet and old. Literata has classical bones
     but was commissioned for screens, so it holds at 20px body and 64px hero. */
  --display: "Literata", "Iowan Old Style", Georgia, serif;
  --sans:    "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --mono:  "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --wrap: 1220px;
  --gut: clamp(1.25rem, 5vw, 4rem);
  --r: 4px;

  --shadow-sm: 0 1px 2px rgba(18,16,14,.04), 0 2px 8px rgba(18,16,14,.03);
  --shadow-md: 0 2px 4px rgba(18,16,14,.05), 0 12px 32px -8px rgba(18,16,14,.10);
  --shadow-lg: 0 4px 8px rgba(18,16,14,.06), 0 28px 60px -16px rgba(18,16,14,.18);
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 96px; }

body {
  margin: 0;
  background-color: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  font-feature-settings: "kern", "liga", "calt";
  -webkit-font-smoothing: antialiased;
  position: relative;
}

/* Fine paper grain. Sits above the background, below everything else. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}
body > * { position: relative; z-index: 1; }

img, svg { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 3px; }

::selection { background: var(--brass); color: var(--on-accent); }

/* ---------- Type ---------- */

h1, h2, h3 {
  font-family: var(--display);
  /* A serif carries its own weight at display size, so 500 rather than the 600
     a grotesque needed, and far less negative tracking. */
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1.08;
  margin: 0 0 0.6em;
  text-wrap: balance;
}
h4, .h-sm {
  font-family: var(--sans); font-weight: 600; letter-spacing: -0.006em;
  line-height: 1.35; margin: 0 0 0.5em; font-size: 1.04rem;
  font-variation-settings: normal;
}

/* Available to screen readers, out of the visual layout. Used for section
   headings that the design does not need but the document outline does. */
.vh {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

h1 { font-size: clamp(2.4rem, 5.3vw, 4rem); line-height: 1.04; letter-spacing: -0.022em; }
h2 { font-size: clamp(1.9rem, 3.7vw, 2.85rem); letter-spacing: -0.02em; }
h3 { font-size: clamp(1.22rem, 2.1vw, 1.55rem); line-height: 1.22; letter-spacing: -0.012em; }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

/* MEASURE IS SET IN em, NOT ch.
   `ch` is the advance of "0" and Chrome resolves it at initial style
   computation, before a swapped webfont has loaded, so the length can end up
   measured against the fallback face and never recomputed. Observed on .lede:
   declared 62ch, computed 863.6px, while 62ch for that same element actually
   resolves to 664.9px. Every page rendered its opening paragraph at about 96
   characters against a 60 to 75 target. em resolves against font-size alone,
   so it is stable whatever the font is doing. Inter averages ~0.41em a
   character, so 29em is about 71 characters at any size. */
.lede {
  font-size: clamp(1.13rem, 1.7vw, 1.38rem);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 30em;
  letter-spacing: -0.006em;
}

.eyebrow {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brass-2);
  margin: 0 0 1.4rem;
  display: flex;
  align-items: center;
  gap: 0.8rem;
}
.eyebrow::before {
  content: "";
  width: 7px; height: 7px;
  flex: none;
  background: var(--brass);
  transform: rotate(45deg);
}
.eyebrow--info { color: var(--info-2); }
.eyebrow--info::before { background: var(--info); }
.eyebrow--good { color: var(--good-2); }
.eyebrow--good::before { background: var(--good); }
.eyebrow--plain::before { display: none; }

.prose { max-width: 31em; }

/* Long-form pages put wrap--narrow and prose on the SAME element. Both declare
   max-width, so the wrap's 880px wins on source order and the 68ch reading
   measure is silently discarded, giving about 98 characters a line against the
   60 to 75 the brand spec sets. Constrain the text children instead, and let
   tables, charts and rules keep the full width so nothing starts scrolling
   that did not scroll before. */
.wrap--narrow.prose > :not(:where(.table-scroll, .matrix, figure, hr, table,
    .plates, .faq, .callout, .grid, .steps)) {
  max-width: 34em;
}
.prose h2 { margin-top: 2.5em; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { margin-top: 2em; }
.prose ul, .prose ol { margin: 0 0 1.35em; padding-left: 1.2em; }
.prose li { margin-bottom: 0.6em; padding-left: 0.3em; }
.prose li::marker { color: var(--brass); }
.prose ol li::marker { font-family: var(--mono); font-size: 0.8em; color: var(--info); }
.prose strong { font-weight: 600; }
.prose a { color: var(--info-2); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--info) 40%, transparent); transition: text-decoration-color .15s ease, color .15s ease; }
.prose a:hover { color: var(--brass-2); text-decoration-color: var(--brass); }

/* `.prose a` is 0-1-1 and `.btn` is 0-1-0, so a button placed inside a prose
   block lost its own colour to the link rule and rendered --info-2 blue on the
   amber fill at 4.14:1. The button is a control, not a link in running text. */
.prose a.btn, .prose a.btn:hover { color: var(--on-accent); text-decoration: none; }
.prose a.btn--ghost, .prose a.btn--ghost:hover { color: var(--ink); }
.prose a.btn--onink, .prose a.btn--onink:hover { color: var(--paper); }

/* Opening paragraph flourish. Opt in with class="opener" only. It used to
   fire automatically on any prose block starting h2 then p, which put it on
   ten pages including all four sectors and all four services. A flourish that
   appears everywhere stops being one. */
.prose > p.opener::first-letter {
  font-family: var(--display);
  font-size: 3.4em;
  line-height: 0.82;
  float: left;
  padding: 0.08em 0.1em 0 0;
  color: var(--brass-2);
}

/* A drop cap needs measure to sit in. At phone widths it indents the first two
   lines against a 40 character line, and a narrow letterform like "I" leaves an
   odd gutter beside it. Editorial flourish above 620px only. */
@media (max-width: 620px) {
  .prose > p.opener::first-letter {
    font-family: inherit; font-size: inherit; line-height: inherit;
    float: none; padding: 0; color: inherit;
    font-variation-settings: normal;
  }
}

.small { font-size: 0.86rem; color: var(--ink-3); line-height: 1.55; max-width: 31em; }
.num, .n { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ---------- Layout ---------- */

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gut); }
.wrap--narrow { max-width: 1060px; }

/* Long-form body runs at 20px, deliberately above the 17 to 18px the rest of
   the site uses. Leigh asked three times for a physically wider text column;
   the way to widen a column without stretching the line count is to set the
   type larger, so both moved together. 36em at 20px is a 720px column at
   about 77 characters, close to Medium's 21px over ~680px, which is the
   reference for comfortable long-form reading. Slightly over the 60 to 75
   house range, and chosen knowingly. */
.wrap--narrow.prose { font-size: 20px; }
.wrap--narrow.prose .small,
.wrap--narrow.prose .eyebrow,
.wrap--narrow.prose figcaption { font-size: revert; }

/* Three rhythm tiers, retuned down. The defaults were 108.8px top and bottom
   at 1280px, so any two adjacent sections put 217.6px of nothing between them,
   and two --air sections put 281.6px. On a page whose sections are mostly a
   heading and three short columns that reads as drift rather than breath. The
   ratio between the tiers is unchanged; all three are about a third shorter. */
section { padding-block: clamp(2.75rem, 5.5vw, 4.5rem); }
.section--tight { padding-block: clamp(2rem, 3.5vw, 3rem); }
.section--air   { padding-block: clamp(3.5rem, 7vw, 5.5rem); }

.band { background: var(--paper-2); border-block: 1px solid var(--line); }
/* White, for the one section that should read as a different surface. */
.band--white { background: var(--white); border-block: 1px solid var(--line); }
/* The one warm ground on the site, reserved for the closing ask. Amber means
   "act here" everywhere else in this system, so the surface the ask sits on
   belongs to the same family. Ink was the obvious alternative and is wrong:
   the footer is already ink, so an ink CTA fuses with it into a 938px dark
   mass with no edge between the ask and the small print. */
/* The closing ask. It is green, and that is a correction of a measured
   regression: as a warm wash it sat **0.0104** off the page ground, one sixth
   of an ordinary band step, so the most important moment on the page had the
   least presence of any section. Cutting the brass mix to tame the orange took
   it below the threshold where a band registers at all.

   Green only became available here when the footer went white. The reason it
   was ruled out before was green-on-green fusion with a green footer, and that
   no longer applies: the ask now cuts hard from the white above it (0.91) and
   hard into the white footer below (0.97), so the page finally has an ending.

   Everything inside had to move to the green set. The ghost button's --ink
   label measured **1.38:1** here. Its --edge border survives at 3.12:1. */
.band--brass {
  background: var(--green);
  color: var(--on-green);
  border-top: 0;
  border-bottom: 0;
}
.band--brass h1, .band--brass h2, .band--brass h3, .band--brass .h-sm { color: var(--on-green); }
.band--brass .lede, .band--brass .small { color: var(--on-green-2); }
.band--brass .eyebrow { color: var(--brass); }
.band--brass .btn--ghost { color: var(--on-green); border-color: var(--edge); background: transparent; }
.band--brass .btn--ghost:hover { color: var(--on-green); border-color: var(--on-green-2); background: rgba(255,255,255,0.06); }
/* The dark band is the brand ground now, not ink. Secondary text on it cannot
   use the cream greys: --ink-4 measures 3.85:1 on green and fails 1.4.3, so
   anything quiet here takes --on-green-2 at 6.24:1. */
.band--ink { background: var(--green); color: var(--on-green); }
.band--ink h1, .band--ink h2, .band--ink h3, .band--ink h4, .band--ink .h-sm { color: var(--on-green); }
.band--ink .lede { color: var(--on-green-2); }
.band--ink .small { color: var(--on-green-2); }
.band--ink .eyebrow { color: var(--brass); }

/* Ink bands are flat. No gradients anywhere in this system. */

.grid { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.18fr); gap: clamp(2rem, 5vw, 5rem); align-items: start; }
.split--even { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.split--wide-left { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); }

@media (max-width: 940px) {
  .g3, .g4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .split, .split--even, .split--wide-left { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 580px) { .g2, .g3, .g4 { grid-template-columns: minmax(0, 1fr); } }

.stack-sm > * + * { margin-top: 0.75rem; }
.stack > * + * { margin-top: 1.5rem; }
.stack-lg > * + * { margin-top: 3rem; }

/* Section heading block, used to vary rhythm */
.sec-head { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.1fr); gap: clamp(1.5rem,4vw,4rem); align-items: end; margin-bottom: clamp(2.5rem, 5vw, 3.75rem); }
@media (max-width: 940px) { .sec-head { grid-template-columns: minmax(0, 1fr); align-items: start; } }
.sec-head h2 { margin-bottom: 0; }

/* ---------- Logo mark ---------- */

.mark { width: 30px; height: 30px; flex: none; }
.mark .m-plate { fill: none; stroke: var(--ink); stroke-width: 1.6; }
.mark .m-a { fill: var(--brass); }
.mark .m-v { fill: var(--info); }
.mark .m-g { fill: var(--good); }
.site-footer .mark .m-plate { stroke: var(--ink); }

/* ---------- Header ---------- */

.site-header {
  position: sticky; top: 0; z-index: 60;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.site-header .wrap { display: flex; align-items: center; justify-content: space-between; gap: 2rem; min-height: 78px; }

/* Reading progress, injected by site.js only on long pages. Sits on the
   header's bottom border so it never covers content or adds layout. */
.readprog {
  position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: transparent; pointer-events: none;
}
.readprog-bar { height: 100%; width: 0; background: var(--brass); }
@media (prefers-reduced-motion: no-preference) {
  .readprog-bar { transition: width .08s linear; }
}

.wordmark { display: flex; align-items: center; text-decoration: none; }
/* The logo is a fixed-ratio lockup; height drives it and width follows. */
.wordmark img { height: 26px; width: auto; display: block; }
/* The footer column is narrower than this lockup needs at 30px, and the global
   img max-width clamps the width while the height stays fixed, so the mark was
   rendering 266x30 against a ratio that demands 310x30: squashed 14%. Driving
   it from width keeps the ratio and lets the column decide the size, which is
   what CLAUDE.md means by a wrong pair silently distorting it. */
.site-footer .wordmark img { width: 100%; max-width: 300px; height: auto; }
@media (max-width: 420px) { .wordmark img { height: 21px; } }
.wordmark .wm-text { display: flex; flex-direction: column; line-height: 1; }
.wordmark b { font-family: var(--display); font-weight: 500; font-size: 1.17rem; letter-spacing: -0.02em; }
.wordmark .wm-text > span { font-family: var(--mono); font-size: 0.58rem; letter-spacing: 0.19em; text-transform: uppercase; color: var(--ink-3); margin-top: 0.3rem; }
.wordmark .mark { transition: transform .3s cubic-bezier(.2,.7,.3,1); }
.wordmark:hover .mark { transform: rotate(-6deg) scale(1.05); }

/* Nav labels must never wrap. Flex items shrink by default, so a nav that is
   slightly too wide squeezes the labels into two and three lines rather than
   overflowing, which is how "Menu Engineering" ended up three lines tall.
   nowrap plus a tighter cap on the gap keeps all eight on one row. */
.nav { display: flex; align-items: center; gap: clamp(0.75rem, 1.5vw, 1.4rem); }
.nav a { white-space: nowrap; }
.nav a {
  text-decoration: none; font-size: 0.895rem; font-weight: 500; color: var(--ink-2);
  padding-block: 0.45rem; position: relative;
}
.nav a:not(.btn)::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 1.5px; background: var(--brass);
  transform: scaleX(0); transform-origin: left; transition: transform .22s cubic-bezier(.2,.7,.3,1);
}
.nav a:not(.btn):hover { color: var(--ink); }
.nav a:not(.btn):hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }
.nav a[aria-current="page"] { color: var(--ink); }
/* .nav a would otherwise out-specify .btn and override the button label colour */
.nav a.btn { color: var(--on-accent); }
.nav a.btn:hover { color: var(--on-accent); }

/* Dropdowns. No JavaScript: hover opens them where hover exists, and
   :focus-within opens them for keyboard users, so tabbing through works
   without a script or a focus trap. On touch the parent link still navigates
   to its index page, which lists the same children. */
.nav-item { position: relative; display: flex; align-items: center; }
.nav-menu {
  position: absolute; top: 100%; left: -0.9rem; z-index: 70;
  min-width: 15rem; padding: 0.5rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-md);
  display: flex; flex-direction: column;
  opacity: 0; visibility: hidden; transform: translateY(-4px);
}
@media (prefers-reduced-motion: no-preference) {
  .nav-menu { transition: opacity .12s ease, transform .12s ease; }
}
.nav-item:focus-within .nav-menu { opacity: 1; visibility: visible; transform: none; }
@media (hover: hover) {
  .nav-item:hover .nav-menu { opacity: 1; visibility: visible; transform: none; }
}
.nav-menu a {
  padding: 0.5rem 0.7rem; border-radius: var(--r);
  font-size: 0.875rem; color: var(--ink-2); white-space: nowrap;
}
.nav-menu a::after { content: none; }        /* no underline sweep in here */
.nav a { transition: color .15s ease; }
.nav-menu a:hover, .nav-menu a:focus-visible { background: var(--paper-2); color: var(--ink); }

.nav-toggle {
  /* 44px unconditionally, not behind (pointer: coarse). This control only ever
     renders on the mobile breakpoint, so the media query bought nothing and
     left the single most important control on a phone at 32px. */
  display: none; background: none; border: 1px solid var(--edge); border-radius: var(--r);
  min-height: 44px; min-width: 44px;
  align-items: center; justify-content: center;
  padding: 0.5rem 0.9rem; font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.12em;
  text-transform: uppercase; cursor: pointer; color: var(--ink);
  transition: border-color .15s ease, color .15s ease;
}
.nav-toggle:hover { border-color: var(--ink-3); }

@media (max-width: 1000px) {
  .nav-toggle { display: inline-flex; }
  .nav {
    display: none; position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper); border-bottom: 1px solid var(--line);
    padding: 0.5rem var(--gut) 1.35rem; box-shadow: var(--shadow-md);
    max-height: calc(100vh - 100%);
    max-height: calc(100dvh - 100%);
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  .nav.is-open { display: flex; }
  .nav a { padding-block: 0.75rem; border-bottom: 1px solid var(--line); }
  .nav a:not(.btn)::after { display: none; }
  .nav .btn { margin-top: 1rem; text-align: center; border-bottom: 0; }

  /* Inside the sheet there is no hover and nowhere to pop out to, so the
     groups become plain indented lists that are always visible. */
  .nav-item { display: block; position: static; }
  .nav-menu {
    position: static; opacity: 1; visibility: visible; transform: none;
    min-width: 0; padding: 0 0 0 1rem; margin: 0;
    background: none; border: 0; border-radius: 0; box-shadow: none;
  }
  .nav-menu a {
    padding: 0.6rem 0; border-radius: 0;
    border-bottom: 1px solid var(--line);
    font-size: 0.85rem; white-space: normal;
  }
  .nav-item > a { font-weight: 600; }
}

/* ---------- Buttons ---------- */

/* Primary action. Brass, not ink: on a page where every heading and paragraph
   is near black, an ink button is the least visually distinct thing on it. The
   darker border is not decoration, it carries the 3:1 boundary contrast WCAG
   1.4.11 requires, since the brass fill alone is only 2.47:1 against paper. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.6rem;
  padding: 0.82rem 1.45rem; border-radius: var(--r);
  border: 1px solid var(--brass-2); background: var(--brass); color: var(--on-accent);
  font-family: var(--sans); font-size: 0.9rem; font-weight: 600; text-decoration: none; cursor: pointer;
  transition: background .18s ease, color .18s ease, border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.btn:hover { background: var(--accent-hover); border-color: var(--brass-2); color: var(--on-accent); transform: translateY(-1px); box-shadow: var(--shadow-md); }

/* Secondary solid, for the rare place a second filled action is needed. */
.btn--ink { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.btn--ink:hover { background: var(--ink-2); border-color: var(--ink-2); color: var(--paper); }

/* Tertiary. Outline only, so it never competes with the primary. */
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--edge); }
.btn--ghost:hover { background: transparent; border-color: var(--ink); color: var(--ink); box-shadow: none; }

/* Retained so existing markup keeps working; identical to the primary now. */
.btn--brass { background: var(--brass); border-color: var(--brass-2); color: var(--on-accent); }
.btn--brass:hover { background: var(--accent-hover); border-color: var(--brass-2); color: var(--on-accent); }
.btn--onink { background: transparent; border-color: var(--edge-dark); color: var(--paper); }
.btn--onink:hover { background: transparent; border-color: var(--paper); color: var(--paper); }
.btn--sm { padding: 0.55rem 1rem; font-size: 0.82rem; }
.btn-row { display: flex; flex-wrap: wrap; gap: 0.8rem; align-items: center; }

.arrow-link {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-size: 0.875rem; font-weight: 500; text-decoration: none; color: var(--info-2);
  /* Standalone control, so it must clear the 24px minimum target size. */
  min-height: 24px;
}
.arrow-link::after { content: "\2192"; transition: transform .2s cubic-bezier(.2,.7,.3,1); }
.arrow-link:hover::after { transform: translateX(4px); }
.band--ink .arrow-link { color: var(--brass); }

/* ---------- Cards ---------- */

.card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: clamp(1.5rem, 2.6vw, 2.1rem);
  display: flex; flex-direction: column; gap: 0.8rem;
  position: relative; overflow: hidden;
}
/* accent hairline across the top, revealed on hover */
.card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: var(--brass);
  transform: scaleX(0); transform-origin: left;
  transition: transform .3s cubic-bezier(.2,.7,.3,1);
}
.card:nth-child(2n)::before { background: var(--info); }
.card:nth-child(3n)::before { background: var(--good); }
.card--link { text-decoration: none; transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease; }
.card--link:hover { border-color: var(--line-2); transform: translateY(-3px); box-shadow: var(--shadow-md); }
.card--link:hover::before { transform: scaleX(1); }
.card h3 { margin: 0; }
.card p { margin: 0; color: var(--ink-2); font-size: 0.945rem; }
.card .arrow-link { margin-top: auto; padding-top: 0.6rem; }

.card-index {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.16em;
  color: var(--brass-2); text-transform: uppercase;
}

/* ---------- Stats ---------- */

.stat { border-top: 2px solid var(--ink); padding-top: 1.05rem; }
.stat .figure {
  font-family: var(--display); font-size: clamp(2.1rem, 4.2vw, 3.1rem); line-height: 0.98;
  font-variant-numeric: tabular-nums; display: flex; align-items: baseline; gap: 0.32rem;
  margin-bottom: 0.6rem;
}
/* "3 AA" as the figure and "Rosette kitchens" as the start of the label split
   a single term across two typographic levels, so the number read as a count
   of three. The qualifier belongs with the numeral, set smaller so the numeral
   still leads. Percent signs get the same treatment for optical balance: a
   full size % competes with the number it modifies. */
.stat .unit {
  font-family: var(--sans); font-size: 0.3em; font-weight: 600;
  letter-spacing: 0.02em; color: var(--ink-3); line-height: 1.1;
  align-self: center; text-wrap: balance;
}
/* A bare symbol belongs tight to its numeral; a word needs the gap. */
.stat .figure > .unit:only-child:not(:has(*)) { margin-left: 0; }
.stat .unit--sym { font-size: 0.42em; margin-left: -0.16em; align-self: baseline; }
.stat .label { font-size: 0.845rem; color: var(--ink-3); line-height: 1.45; display: block; max-width: 26em; }
/* One accent in a row of figures, not four. Colour that distinguishes four
   equally weighted biography facts encodes nothing, and it spends --good and
   --info, both of which carry a specific meaning elsewhere, on decoration.
   The gross profit figure keeps --good because it IS positive performance,
   which is the one thing that token is reserved for. */
/* "Why it pays" reworked.

   All four figures take the gold. They are published industry findings, not
   this practice's own data, so none should borrow a --good or --info signal:
   a colour in a figure is meant to mean something here, and these four mean
   the same thing as each other.

   The per-column top rule goes. A rule above each figure read as four separate
   components; hairlines only between columns read as one table of evidence,
   which is what it is. */
.figures--gold > div { border-top: 0; padding-top: 0; }
.figures--gold .figure { color: var(--brass-2); }
.figures--gold .label { color: var(--ink-2); font-size: 0.9rem; max-width: 24em; }
/* A short gold rule separates the finding from its citation, so the source
   reads as provenance rather than as more of the claim. */
.figures--gold .source {
  position: relative; padding-top: 1.1rem; margin-top: 1rem;
  display: block; color: var(--ink-3);
}
.figures--gold .source::before {
  content: ""; position: absolute; top: 0; left: 0;
  width: 42px; height: 2px; background: var(--brass);
}

/* The evidence row, to Leigh's reference.

   This is deliberately the four column figure row that an earlier pass
   replaced with a ruled list, on the grounds that four equal stat columns is
   the most recognisable template component on the web. Leigh supplied a
   reference doing it properly and asked for it back, so the pattern is a
   decision rather than an oversight. What makes this version work where the
   first one did not: the figure is much larger and in the display face, the
   columns are divided by hairlines rather than floated as tiles, and a short
   gold rule separates the claim from its citation so the source reads as
   provenance instead of more claim.

   The reference's own standfirst, "real results from real restaurants", is
   NOT used. These are published findings and one credential; presenting them
   as results delivered here is exactly what CAP 3.7 and the claims rules on
   this site forbid. */
.evidence {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-top: 2.5rem; border-top: 1px solid var(--line-2);
}
.ev-cell {
  padding: 1.9rem clamp(1.1rem, 2.2vw, 1.9rem) 1.9rem;
  border-left: 1px solid var(--line);
}
.ev-cell:first-child { border-left: 0; padding-left: 0; }
/* The lead column lifts by a single step, not to white.

   On the --paper-2 ground a white panel is a 0.07 luminance jump: it stopped
   reading as emphasis and started reading as a floating card that interrupted
   the rule across the top of the row. --paper is 8 points off the ground,
   which is enough to mark where to start and not enough to become an object.
   The rule across the top stays continuous, which is what makes the four
   columns read as one row. */
/* The lead cell needs the same inset as every other column or its letters sit
   flush against the edge of its own tint. `.ev-cell:first-child` sets
   padding-left: 0 so the row starts on the page margin, and that beat the
   single class here on specificity: the tint applied and the padding never
   did. Matched to two classes so it wins, and the box is pulled left by the
   same amount it is padded, so the tint bleeds into the gutter while the text
   still lines up with the heading above it. */
.ev-cell.ev-cell--lead {
  background: var(--paper);
  margin-left: calc(-1 * clamp(1.1rem, 2.2vw, 1.9rem));
  padding-left: clamp(1.1rem, 2.2vw, 1.9rem);
}
@media (max-width: 900px) {
  .ev-cell.ev-cell--lead { margin-left: 0; padding-left: 0; background: none; }
}

.ev-n {
  font-family: var(--display); font-weight: 500;
  font-size: clamp(2.3rem, 3.4vw, 3.1rem); line-height: 1;
  letter-spacing: -0.02em; color: var(--brass-2);
  margin: 0 0 0.85rem; font-variant-numeric: tabular-nums;
}
.ev-u { font-size: 0.42em; letter-spacing: 0; margin-left: 0.2em; }
.ev-k {
  margin: 0 0 1rem; font-size: 1rem; line-height: 1.35; color: var(--ink);
  position: relative; padding-bottom: 0.85rem;
  /* No min-height. Flooring this to two lines aligned the rules but left a
     hole between a one line label and its own rule, which looked worse than
     the raggedness it fixed. The labels are written to fit one line instead,
     so the rules align because the content agrees, not because a box was
     padded. Keep any new label under about 30 characters. */
}
/* the rule is the thing that stops the citation reading as more of the claim */
.ev-k::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 2.1rem; height: 2px; background: var(--brass);
}
.ev-s { margin: 0; font-size: 0.82rem; line-height: 1.5; color: var(--ink-3); }

@media (max-width: 900px) {
  .evidence { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ev-cell { border-left: 0; border-top: 1px solid var(--line); padding-inline: 0; }
  .ev-cell:nth-child(even) { padding-left: clamp(1.1rem, 3vw, 1.6rem); border-left: 1px solid var(--line); }
  .ev-cell--lead { background: none; padding-left: 0; }
}
@media (max-width: 560px) {
  .evidence { grid-template-columns: minmax(0, 1fr); }
  .ev-cell:nth-child(even) { padding-left: 0; border-left: 0; }
}

/* Published findings as a reference table, not as four stat cards.

   Four equal columns of big figure, label and citation is the single most
   recognisable template component on the web, and it was doing the page no
   favours: the eye reads four tiles rather than four findings. A ruled list
   reads as a source note, which is what this is. The figure keeps the display
   face and the accent, right aligned in its own column so the numbers line up
   as figures do in a report. */
.findings { margin: 2.25rem 0 0; border-top: 1px solid var(--line-2); }
.finding {
  display: grid; grid-template-columns: 9.5rem minmax(0, 1fr);
  gap: 0 clamp(1.25rem, 3vw, 2.75rem);
  padding: 1.1rem 0; border-bottom: 1px solid var(--line);
  align-items: baseline;
}
.find-n {
  font-family: var(--display); font-weight: 500; font-size: 1.95rem;
  line-height: 1.05; color: var(--brass-2); text-align: right;
  font-variant-numeric: tabular-nums; margin: 0;
}
.find-u {
  display: block; font-family: var(--mono); font-size: 0.62rem;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--ink-3);
  margin-top: 0.3rem;
}
.find-c {
  margin: 0; font-size: 1rem; line-height: 1.55; color: var(--ink);
  max-width: 46em;
}
.find-s {
  display: block; font-size: 0.84rem; line-height: 1.5;
  color: var(--ink-3); margin-top: 0.4rem;
}
@media (max-width: 680px) {
  .finding { grid-template-columns: minmax(0, 1fr); gap: 0.35rem; }
  .find-n { text-align: left; font-size: 1.7rem; }
  .find-u { display: inline; margin: 0 0 0 0.5rem; }
}

/* The same device under the section heading, which is what ties the two. */
.rule-under { position: relative; padding-bottom: 1.5rem; }
.rule-under::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 92px; height: 3px; background: var(--brass-2);
}

.stat--brass { border-color: var(--brass); }
.stat--info { border-color: var(--info); }
.stat--good { border-color: var(--good); }
/* One rule across the row. Per stat borders left a gap at every grid gutter,
   so the line read as broken rather than as three measures under one rule. */
.statrow { border-top: 2px solid var(--line-2); padding-top: 1.3rem; }
.statrow .stat { border-top: 0; padding-top: 0; }
.band--ink .statrow { border-top-color: var(--green-line); }
.statrow .stat .figure { color: var(--ink); }
/* The note runs under the full row rather than the first column, which is what
   left the lower right empty, and it no longer restates the provenance line
   above the figures. */
.statrow-note { margin-top: 1.6rem; max-width: 62ch; color: var(--on-green-2); }
.statrow .stat--good .figure { color: var(--good-2); }
.stat--brass .figure { color: var(--brass-2); }
.stat--info .figure { color: var(--info-2); }
/* the calculator's cash figure was the last --info-2 blue on the homepage,
   and blue is in no part of the documented palette */
.calc .readout .v { color: var(--ink); }
.calc #pd-cash { color: var(--brass-2); }
.stat--good .figure { color: var(--good-2); }
.band--ink .stat { border-color: var(--green-line); }
/* --ink-3 is unreadable on the dark band and --ink-4 measures 3.85:1 there,
   which fails 1.4.3. Both take the green ground's own secondary at 6.24:1. */
.band--ink .stat .label { color: var(--on-green-2); }
.band--ink .stat .unit { color: var(--on-green-2); }
.band--ink .statrow .stat .figure { color: var(--paper); }
.band--ink .stat--brass { border-color: var(--brass); }
.band--ink .stat--brass .figure { color: var(--brass); }
.band--ink .stat--info { border-color: var(--info); }
.band--ink .stat--info .figure { color: #8FAEE0; }
.band--ink .stat--good { border-color: var(--good); }
.band--ink .stat--good .figure { color: var(--good); }

/* Numbers strip */
.figures { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));   /* Grid items stretch by default, so each column's divider ran on past the
     shortest note and left a void at the lower right. Start alignment stops
     every rule with its own content. */
  align-items: start;
}
.figures > div { padding: 1.05rem 1.5rem 0 0; border-right: 1px solid var(--line); }
.figures > div:last-child { border-right: 0; padding-right: 0; }
.figures > div + div { padding-left: 1.5rem; }
@media (max-width: 940px) { .figures { grid-template-columns: repeat(2, minmax(0, 1fr)); } .figures > div:nth-child(2n) { border-right: 0; } }
@media (max-width: 520px) { .figures { grid-template-columns: minmax(0, 1fr); } .figures > div { border-right: 0; border-bottom: 1px solid var(--line); padding: 1.5rem 0; } }

/* ---------- Rule list ---------- */

.rulelist { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.rulelist > li {
  border-bottom: 1px solid var(--line); padding: 1.35rem 0;
  display: grid; grid-template-columns: 3.4rem 1fr; gap: 1.35rem; align-items: start;
  transition: background .2s ease;
}
.rulelist > li:hover { background: color-mix(in srgb, var(--brass-wash) 55%, transparent); }
.rulelist .n { font-family: var(--mono); font-size: 0.76rem; color: var(--info); padding-top: 0.25rem; }
.rulelist .h-sm { margin: 0 0 0.35rem; }
.rulelist p { margin: 0; font-size: 0.93rem; color: var(--ink-2); }

/* ---------- Callout ---------- */

/* Measured before this rewrite: a 922px box holding 517px of text, so 405px
   (44%) of every callout was empty wash. Two separate faults. The box is
   exempt from the prose cap so it filled the wrap, and the text was capped at
   34em of its OWN 0.95rem, which in a 20px article is 15.2px, so the
   highlighted box was set smaller and 34 characters narrower than the prose
   around it. A callout that shrinks the type reads as a downgrade.

   Both are fixed by sizing in em against the inherited context: the text now
   matches the article's own measure exactly, and the box is that measure plus
   its padding, so it tracks the column on a 20px guide and on a 17px service
   page without a breakpoint. */
.callout {
  --co-accent: var(--brass);
  --co-wash:   var(--brass-wash);
  max-width: 35.5em;
  border: 1px solid color-mix(in srgb, var(--co-accent) 20%, var(--line));
  border-left: 3px solid var(--co-accent);
  border-radius: var(--r);
  /* The flat pastel slab was the other half of why these read as a framework
     alert rather than an editorial aside. Pulling the wash towards white keeps
     the semantic colour legible at the border and the accent, where it does
     the work, without a block of mint filling the page. */
  background: color-mix(in srgb, var(--co-wash) 58%, var(--white));
  padding: 1.4rem 1.7rem 1.45rem;
  margin: 2.25rem 0;
}
.callout--info { --co-accent: var(--info); --co-wash: var(--info-wash); }
.callout--good { --co-accent: var(--good); --co-wash: var(--good-wash); }
/* Sentence case in the display face, not bold sans at body size: the site's
   own heading voice, and the thing that separates an aside from a UI alert. */
.callout .h-sm {
  font-family: var(--display); font-weight: 500;
  font-size: 1.06em; line-height: 1.3; letter-spacing: -0.008em;
  margin: 0 0 0.55rem;
}
.callout p { font-size: 0.95em; color: var(--ink-2); }
.callout p:last-child { margin-bottom: 0; }

/* Pull quote */
.pull {
  border-top: 2px solid var(--ink); border-bottom: 1px solid var(--line);
  padding: 1.6rem 0; margin: 2.5rem 0;
  font-family: var(--display); font-size: clamp(1.3rem, 2.4vw, 1.75rem); line-height: 1.24;
  letter-spacing: -0.015em;
}

/* ---------- Tables ---------- */

.table-scroll { overflow-x: auto; margin: 1.9rem 0; border: 1px solid var(--line); border-radius: var(--r); background: var(--paper); }
table { border-collapse: collapse; width: 100%; min-width: 540px; font-size: 0.9rem; }
th, td { text-align: left; padding: 0.82rem 1.05rem; border-bottom: 1px solid var(--line); vertical-align: top; }
thead th {
  background: var(--paper-2); font-family: var(--mono); font-size: 0.66rem;
  letter-spacing: 0.12em; text-transform: uppercase; font-weight: 500; color: var(--ink-2);
  position: sticky; top: 0;
}
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--paper-2); }
td.n, th.n { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* class chips inside tables */
.chip {
  font-family: var(--mono); font-size: 0.64rem; letter-spacing: 0.1em; text-transform: uppercase;
  padding: 0.16rem 0.5rem; border-radius: 100px; white-space: nowrap; display: inline-block;
}
.chip-star   { background: var(--good-wash);  color: var(--good-2);  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--good) 45%, transparent); }
.chip-plow   { background: var(--brass-wash);  color: var(--brass-2);  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brass) 45%, transparent); }
.chip-puzzle { background: var(--info-wash); color: var(--info-2); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--info) 40%, transparent); }
.chip-dog    { background: var(--paper-3);     color: var(--ink-3);    box-shadow: inset 0 0 0 1px var(--line-2); }

/* ---------- Page hero ---------- */

.page-hero { padding-block: clamp(3.25rem, 7vw, 6rem) clamp(2rem, 4vw, 3.25rem); border-bottom: 1px solid var(--line); }
.page-hero h1 { max-width: 17ch; }
.page-hero .lede { margin-top: 1.6rem; }

/* Breadcrumb: nav + ordered list, separators hidden from assistive tech and
   the current page marked, matching the BreadcrumbList schema on the page. */
.crumbs { margin-bottom: 1.8rem; }
.crumbs ol {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem;
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--ink-3);
}
.crumbs li { display: inline-flex; align-items: center; }
.crumbs a { text-decoration: none; color: var(--ink-3); border-bottom: 1px solid transparent; }
.crumbs a:hover { color: var(--brass-2); border-color: var(--brass); }
.crumbs [aria-current="page"] { color: var(--ink-2); }
.crumb-sep { color: var(--line-2); }

/* ---------- Home hero ---------- */

.hero { padding-block: clamp(3.5rem, 7vw, 6rem) clamp(3rem, 5vw, 4.5rem); }

/* Two paddings were stacking under the credential strip: the hero's own 72px
   bottom plus .section--air's 144px top on the problem section beneath it, so
   216px of nothing sat between the last credential and the first argument.

   Neither value was wrong on its own, and .section--air is a deliberate rhythm
   tier that the problem section is meant to have, so the fix is the join rather
   than either rule. The hero already closes itself: the strip carries a
   hairline above it and reads as a terminal qualifier, so it does not need to
   be followed by a full section's breath as well as its own.

   Scoped with :has so the /results/ hero, which has no strip, keeps the
   padding it was given. */
.hero:has(.hero-meta) { padding-bottom: clamp(1.25rem, 2.5vw, 2rem); }
.hero + .section--air { padding-top: clamp(3.5rem, 6vw, 4.5rem); }
.hero .hero-title { max-width: none; }
/* Hero credential strip.

   As a wrapping flex row the three items packed to the left and stopped: 613px
   of content under a 1092px rule, so 44% of the hairline crossed nothing and
   the strip read as an unfinished line rather than a set. Columns distribute
   that slack as rhythm instead of leaving it as a tail.

   Three explicit columns and one breakpoint, not auto-fit. auto-fit will
   always take the two-column state on the way down, and two columns strands
   the third credential alone on a second row with 362px of empty beside it,
   measured at 768px. There is no intermediate state worth having here, so the
   only transition is three to one.

   It keeps ONE rule across the top. `.levers` further down the page gives each
   column its own top hairline precisely so it does not read as the `Worked
   with` grid, and both are label-plus-grey-text rows; a third in that idiom
   would compound the collision. A single rule and a mark per item is what
   holds this one apart. */
.hero-meta {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  list-style: none;
  margin: 3rem 0 0; padding: 1.35rem 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3);
}
/* A bar, not a row of columns. Each claim takes its own cell with a hairline
   between, which is what separates a credential strip from a list that happens
   to sit in a line. The divider is dropped on whichever item begins a row, per
   breakpoint, so a wrapped row never opens with a rule hanging off its left. */
/* Mark above the claim, centred. Beside the text the marks read as punctuation
   on a line of type; stacked and centred they read as a set, and the strip
   stops being a sentence and becomes five things. */
.hero-meta li {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 0.7rem; padding: 0.3rem 1.1rem;
  border-left: 1px solid var(--line);
}
.hero-meta li:first-child { border-left: 0; }

/* Two tiers, and the split is the claim against its evidence rather than a
   typographic flourish: the bold line is what is being asserted, the quiet one
   underneath is what substantiates it. "3 AA Rosette trained" alone cannot be
   checked by anyone; "The Peacock at Rowsley" can be, against the AA's own
   guide, in about ten seconds. CAP rule 3.7 wants documentary evidence for an
   objective claim, and a named kitchen is the closest this strip can get to
   carrying its own. */
.cred-text { display: flex; flex-direction: column; gap: 0.3rem; line-height: 1.4; }
.hero-meta b { color: var(--ink); font-weight: 500; }

/* Five columns is the trust strip at full width. It is not five single line
   labels: the second tier is what makes each claim checkable, and dropping it
   to fit would trade the only verifiable thing in the strip for one more row
   of assertions. */
.hero-meta--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
/* Tuned against the longest second tier, "The Peacock at Rowsley" at 22
   characters. The cell padding the divider needs costs width the text was
   using, so the tier drops a step and loses some tracking to stay on one line
   at 1280px. Mono runs about 0.72em a character with 0.12em tracking. */
.hero-meta--5 .cred-text { font-size: 0.9em; }
/* The second tier drops out of mono small caps. "Performance measured against
   baseline" set in tracked capitals is a label pretending to be a sentence;
   the claim above it stays uppercase so the two tiers still read as claim and
   substantiation. */
.hero-meta--5 .cred-text span {
  font-family: var(--sans); text-transform: none; letter-spacing: 0;
  font-size: 0.82rem; line-height: 1.45; color: var(--ink-3);
}
.hero-meta--5 li { padding: 0.3rem 0.9rem; }
.cred-fill { fill: var(--ink-3); stroke: none; }

/* The heraldic rose on the Rosette claim, drawn rather than traced: five petals
   on a ring plus a seed, geometric so it still reads as a rose at 22px where a
   traced one collapses to a blob.

   ONE rose, not three. The count is already in the words beside it, and three
   of these at 22px are 7px each, which is below the size any of them reads at.

   Leigh asked for this twice after the objection, so it is a decision taken
   with the reason known, not an oversight: rosettes are awarded to restaurants
   and the Peacock holds these, not this practice. If the ASA ever asks, the
   words carry the qualifier and the mark is a rose, not the AA's device. */
/* Five interlaced loops, from the mark Leigh supplied. It carries more line
   length than any other mark in the set, so it takes a lighter weight to sit
   at the same optical density beside them. Round caps and joins because the
   loops are curves, where the rest of the set is straight-edged. */
.cred-mark--rose { stroke-width: 1.15; stroke-linecap: round; stroke-linejoin: round; }

/* The method's step verb. The four steps already existed, already worked, and
   .setup-step already numbered itself with a CSS counter, so adding a second
   number printed 01 twice. What the steps actually lacked was the verb: a name
   and an order a reader can repeat back, which is the difference between a
   described process and a method someone believes you own. */
/* The homepage case study.

   It deliberately does NOT repeat the three figures. They are already set large
   on the green proof band a few sections above, and the same numbers twice on
   one page reads as padding rather than evidence. This block carries what the
   band cannot: the dish, what actually changed, and the link to the worked
   detail.

   It is also not called a brief. The engagement was a head chef appointment,
   so there was no client and no brief, and framing it as one would be the
   single most misleading thing on the page. */
/* The measure step lost its diagram. It drew six dashed rectangles labelled
   BASELINE and WEEK 12 with nothing in any of them, because there are no client
   figures to put there: six empty boxes carrying zero information next to the
   densest copy on the page. The step reads better as the sentence it always
   was. */

/* One object on the ground rather than loose copy beside a photograph. The
   section sits on the plain paper, so a white panel with a hairline lifts the
   case off it the way a card does elsewhere, and the photograph runs flush to
   the panel edge instead of floating in its own bordered box. It is the only
   named piece of work on the page: it should read as a thing, not as a
   paragraph that happens to have an image next to it. */
.casecard {
  display: grid; grid-template-columns: minmax(0, 0.88fr) minmax(0, 1.12fr);
  gap: 0; align-items: stretch; margin-top: 1.75rem;
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r); overflow: hidden; box-shadow: var(--shadow-md);
}
.casecard-shot { margin: 0; }
/* fills its column, so the panel has no ragged edge whatever the copy does */
.casecard-shot img {
  width: 100%; height: 100%; display: block; min-height: 300px;
  object-fit: cover; object-position: center 50%;
  border: 0; border-radius: 0;
}
.casecard-body { padding: clamp(1.4rem, 2.6vw, 2.1rem); }
.casecard-body > p:first-child { margin-top: 0; }
.casecard-k {
  font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--green); margin: 1.2rem 0 0.6rem;
}
.casecard-list { margin: 0; padding-left: 1.1rem; }
.casecard-body .arrow-link { color: var(--ink); }
.casecard-body .arrow-link::after { color: var(--brass-2); }
.casecard-list li { font-size: 0.9rem; line-height: 1.5; color: var(--ink-2); margin-bottom: 0.4rem; }

/* The only named piece of work on the page had no outcome in it: the card
   opened on a photograph and four bullets, so a reader had to reach /results/
   before a number appeared. The move is stated once, at the top of the body,
   in the before-and-after idiom /results/ already uses. */
.case-result {
  display: grid; gap: 0.4rem; margin: 0 0 1.15rem;
  padding-bottom: 1.15rem; border-bottom: 1px solid var(--line);
}
.cr-k {
  font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-3);
}
.cr-v {
  display: flex; align-items: baseline; gap: 0.55rem;
  font-family: var(--display); font-variant-numeric: tabular-nums; line-height: 1;
}
.cr-was { font-size: clamp(1.3rem, 3vw, 1.6rem); color: var(--ink-3); }
.cr-arrow { font-size: 1rem; color: var(--brass-2); }
.cr-now { font-size: clamp(2.1rem, 5vw, 2.8rem); color: var(--ink); }

@media (max-width: 980px) {
  .casecard { grid-template-columns: minmax(0, 1fr); }
  /* 3:2 put 232px of photograph above the first word on a 664px viewport, and
     the body below it is 692px on its own. 16:9 buys back 36px without
     cropping the plate, so the figure lands on the first screen. */
  .casecard-shot img { min-height: 0; aspect-ratio: 1 / 1; object-position: center 40%; }
}

/* Results as before and after.

   A bare delta made the reader do the arithmetic and then trust it: "+3.6 pts"
   says nothing about where the site started. 69.8 to 73.4 shows the whole move,
   which is both more persuasive and more checkable, and it is the form the
   /results/ page already uses.

   The headline is a question because the section answers one. "The only measure
   that counts is what happens to the P&L" asserted a position; "What changed on
   the P&L?" sets up the three numbers underneath it. */
.ba-head { align-items: start; margin-bottom: 2.5rem; }
.ba-head h2 { margin: 0 0 0.9rem; }
.ba-head .lede { color: var(--on-green-2); max-width: 30em; }
.ba-method { border-left: 1px solid var(--green-line); padding-left: clamp(1.25rem, 3vw, 2.25rem); }
.ba-method p { color: var(--on-green-2); font-size: 0.95rem; line-height: 1.6; margin: 0 0 0.9rem; max-width: 34em; }
.ba-link { margin: 1.25rem 0 0 !important; }

.ba-card {
  border: 1px solid var(--green-line); border-radius: var(--r);
  padding: clamp(1.15rem, 2.4vw, 1.55rem);
  display: flex; flex-direction: column;
}
.ba-k {
  font-family: var(--mono); font-size: 0.64rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--on-green); margin: 0 0 0.9rem;
}
.ba-move { display: flex; align-items: flex-end; gap: clamp(0.7rem, 1.8vw, 1.1rem); }
.ba-pair { display: flex; flex-direction: column; }
.ba-v {
  font-family: var(--display); font-weight: 500; line-height: 1;
  font-size: clamp(1.75rem, 3.4vw, 2.5rem); color: var(--on-green);
  font-variant-numeric: tabular-nums;
}
.ba-t {
  font-family: var(--mono); font-size: 0.58rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--on-green-2); margin-top: 0.45rem;
}
/* The arrow is the only gold inside the move, so direction reads before value. */
.ba-arrow { color: var(--brass); font-size: 1.15rem; line-height: 1; padding-bottom: 1.15rem; }

/* The delta closes each card, so all three end on the number that matters. */
.ba-d {
  margin: 1rem 0 0; padding-top: 0.9rem;
  border-top: 1px solid var(--green-line);
  display: flex; align-items: baseline; gap: 0.55rem; flex-wrap: wrap;
}
.ba-dv {
  font-family: var(--display); font-weight: 500; line-height: 1;
  font-size: clamp(1.35rem, 2.4vw, 1.75rem); color: var(--brass);
  font-variant-numeric: tabular-nums;
}
.ba-dk {
  font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--on-green-2);
}

.ba-row {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(0.8rem, 1.8vw, 1.1rem);
}
.ba-foot { margin-top: 1.5rem; }
.ba-foot .provenance { margin-top: 0; }
.ba-foot .statrow-note { margin-top: 0.8rem; max-width: 70ch; }

@media (max-width: 900px) {
  .ba-row { grid-template-columns: minmax(0, 1fr); }
  .ba-method { border-left: 0; border-top: 1px solid var(--green-line); padding: 1.2rem 0 0; margin-top: 1.2rem; }
}

/* Provenance, and it sits ABOVE the figures on purpose.

   These are the strongest numbers on the site and they are employment history,
   not consultancy outcomes. The qualifier was below the row, which is where a
   reader scanning three large figures meets it last or not at all. Read before
   the numbers it costs nothing; read after them it is a correction. */
.provenance {
  margin: 2.5rem 0 0;
  font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--on-green-2);
  padding-left: 0.85rem; border-left: 2px solid var(--brass);
}
/* The light ground variant. It must follow the base rule: declared before it
   at equal specificity, source order gave it --on-green-2 on cream at 1.8:1. */
.provenance--light { color: var(--ink-3); margin-top: 1.2rem; }

/* A client lockup on a case study. It replaces the venue name rather than
   sitting beside it, which is what a logo is for, and the name survives in the
   alt text for anyone not seeing it. The artwork is supplied, so it is placed
   and never redrawn: the white ground was knocked out to alpha so it sits on
   any section, with the alpha taken from each pixel's darkness so the script's
   antialiased edges stay smooth. */
.venue-logo {
  display: block; width: 190px; height: auto;
  margin: 0 0 0.75rem;
}
@media (max-width: 620px) { .venue-logo { width: 150px; } }

/* The founder block.

   The quote is Ryan's own sentence, already published on /about/, not a line
   written for a hero. That matters more than it sounds: a founder quote is the
   one place a site is most tempted to invent voice, and an invented one reads
   as invented.

   It is the section's h2 because it is the section's statement. A separate
   heading above a pull quote would say the same thing twice. */
/* Portrait, argument, evidence. The three figures used to sit as cards inside
   the argument column, which made the block one long measure with a card grid
   dropped into the middle of it. Standing them in their own ruled column puts
   the person beside the claim beside the proof, and the portrait can be larger
   because it is no longer competing with the cards for the same row. */
.founder {
  display: grid; grid-template-columns: 360px minmax(0, 1fr) 272px;
  gap: clamp(1.75rem, 3.5vw, 3rem); align-items: center;
}
@media (max-width: 1120px) {
  .founder { grid-template-columns: 300px minmax(0, 1fr); }
  .founder-stats { grid-column: 1 / -1; }
}
.founder-face {
  width: 100%; height: auto; border-radius: var(--r);
  border: 1px solid var(--green-line);
}
.founder-quote {
  font-family: var(--display); font-weight: 500;
  font-size: clamp(1.25rem, 2.25vw, 1.75rem); line-height: 1.22;
  letter-spacing: -0.018em; text-wrap: balance;
  /* The measure and the size both track the sentence. It has grown twice now,
     97 to 142 characters, and this block was already the tallest in its
     section: holding the old 2.05rem over 30ch put it on five lines. */
  color: var(--on-green); margin: 0.25rem 0 0.9rem; max-width: 36ch;
}
/* The role line moved under the photograph, where it reads as a caption on the
   person rather than a floating credit, and the three figures it used to sit
   above are now cards. */
.founder-shot { margin: 0; }
.founder-shot figcaption {
  margin-top: 0.75rem; padding-top: 0.7rem;
  border-top: 1px solid var(--green-line);
  font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--on-green-2); line-height: 1.5;
}

/* One panel, hairline separated, rather than three bordered cards. A raised
   --green-2 surface lifts it off the ground just enough to read as a separate
   object without a second border. The number takes amber, which is 5.53:1
   here and is the one place a figure may be amber on this site. */
.founder-stats {
  background: var(--green-2); border: 1px solid var(--green-line);
  border-radius: var(--r); padding: 1.3rem 1.35rem 1.1rem; margin: 0;
  align-self: stretch;
}
.fs-head {
  font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--on-green); margin: 0 0 0.3rem;
  display: flex; align-items: center; gap: 0.6rem;
}
.fs-head::after {
  content: ""; flex: 1 1 auto; height: 1px; background: var(--brass);
  opacity: 0.55;
}
.fstat {
  display: flex; flex-direction: column;
  padding: 0.95rem 0 0.2rem; border-top: 1px solid var(--green-line);
}
.fstat:first-of-type { border-top: 0; padding-top: 0.75rem; }
.fs-n {
  font-family: var(--display); font-weight: 500; font-size: 1.9rem;
  line-height: 1; color: var(--brass); font-variant-numeric: tabular-nums;
}
.fs-k {
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--on-green); margin: 0.5rem 0 0.4rem;
}
.fs-d { font-size: 0.8rem; line-height: 1.45; color: var(--on-green-2); }

/* The provenance marker on a green ground. --ink-3 is 1.85:1 here. */
.provenance--onGreen { color: var(--on-green-2); margin: 1rem 0 0; }
.founder-cta { margin: 0; }

@media (max-width: 900px) {
  .fstat { flex-direction: row; align-items: baseline; gap: 0.8rem; flex-wrap: wrap; }
  .fs-n { font-size: 1.5rem; }
  .fs-k { margin: 0; }
  .fs-d { flex: 1 1 100%; margin-top: 0.3rem; }
}
/* The role sits a step quieter than the name, and --ink-3 is 1.85:1 here. */
.founder .lede { color: var(--on-green-2); max-width: 52ch;
  font-size: 0.95rem; line-height: 1.6; }

@media (max-width: 820px) {
  .founder { grid-template-columns: minmax(0, 1fr); gap: 1.75rem; }
  .founder-shot { max-width: 260px; }
}

/* The four leak headings. Mono and small caps rather than an h3, because these
   label a dimension rather than open a subsection, and four h3s here would put
   a heading level between the section's h2 and the ones further down the page
   for no structural reason. */
.leak-k {
  font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--green); margin: 0 0 0.6rem;
}

.step-id {
  margin: 0 0 0.3rem;
  font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--brass-2);
}


/* Below this the three columns cannot hold the longest credential without
   wrapping it, so they stack rather than wrap. 900px leaves 257px a column
   against 225px of content. */
/* Five items go 5 columns, then 3, then 1. Two columns is skipped on purpose:
   five items in two columns leaves the fifth alone on a third row with half
   the width empty beside it, which is the same orphan the three item strip was
   built to avoid. Three columns leaves one empty cell, which is a grid
   remainder rather than a stranded claim. */
@media (max-width: 1180px) {
  .hero-meta--5 { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 1.1rem; }
  .hero-meta--5 li:nth-child(3n+1) { border-left: 0; padding-left: 0; }
}
@media (max-width: 900px) {
  .hero-meta { grid-template-columns: 1fr; gap: 0.85rem; margin-top: 2.5rem; }
}
@media (max-width: 760px) {
  /* Stacked, the vertical rule has nothing to divide. The claims separate with
     their own spacing instead. */
  /* Stacked on a phone the vertical rule has nothing to divide, and a centred
     column of five is a lot of scrolling: back to mark beside claim. */
  .hero-meta--5 { grid-template-columns: 1fr; row-gap: 1rem; }
  .hero-meta--5 li { border-left: 0; padding: 0; flex-direction: row; text-align: left; gap: 0.8rem; }
  .hero-meta--5 .cred-mark { width: 28px; height: 28px; }
}

/* The credential marks.

   Drawn for these three facts rather than taken from a set, because generic
   stock icons are on the Prohibited list and a chef's hat, a star and a map
   pin are the three most generic marks in hospitality.

   Stacked plates and a cloche are kitchen objects, which is the point: the two
   credentials they sit beside are about Ryan's cooking, and the plates exist on
   this page at all because they carry the differentiator, that this is a chef
   rather than a spreadsheet consultancy. The third credential is logistics, not
   cooking, so it takes a geometric mark instead.

   Nothing here resembles a rosette, a laurel or a star, and the reason is
   stronger than licensing. Rosettes are awarded to restaurants, not to chefs,
   so the Peacock holds them and this practice does not. An emblem beside the
   credential would say Menu Engineering Co. holds three Rosettes, which is
   false, and AA authorisation could not make it true. A star is worse again: it
   reads as Michelin, a different awarding body and a far higher claim.

   Stroked in --ink-3, not --ink-4. Measured on the ivory canvas, --ink-4 is
   2.94:1 and fails the 3:1 that WCAG 1.4.11 asks of a meaningful graphic;
   --ink-3 is 5.36:1. They sit at the weight of the qualifier they accompany
   rather than competing with the lead term, which carries --ink. */
.cred-mark {
  /* 38px. Stacked above the text they carry the column, so they can be the
     size the reference uses rather than the size a line of type allows. */
  flex: none; width: 38px; height: 38px;
  fill: none; stroke: var(--ink-3); stroke-width: 1.25;
  stroke-linecap: square; stroke-linejoin: miter;
}

/* The Profit-focused mark is a supplied two tone artwork rather than a stroked
   outline like its neighbours, so it takes fills. All of it takes --ink-3,
   the colour of the other four marks, at 5.36:1. */
.cred-mark--chart { fill: none; stroke: none; }
.cred-mark--chart .cm-bar { fill: var(--ink-3); }
.cred-mark--chart .cm-arrow { stroke: var(--ink-3); }
.cred-mark--chart .cm-head { fill: var(--ink-3); }

.hero-panel {
  background: var(--white); color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--r); padding: clamp(1.5rem, 2.8vw, 2.1rem);
  box-shadow: var(--shadow-lg);
}
.hero-panel h2 { color: var(--ink); font-size: 1.02rem; font-family: var(--sans); font-weight: 600; letter-spacing: 0; margin-bottom: 0.3rem; }
.hero-panel .panel-note { font-family: var(--mono); font-size: 0.64rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); }

/* ---------- Margin comparison bars ---------- */

/* Text inside the SVG is set in viewBox units, so it shrinks with the
   container. Hold a floor width and scroll below it, the same way the tables
   and the matrix do, rather than letting the labels collapse. */
.marginbar { margin: 2.5rem 0 0; overflow-x: auto; }
.marginbar svg { width: 100%; height: auto; display: block; min-width: 460px; }

.mb-context {
  margin: 0 0 0.9rem; font-size: 0.9rem; color: var(--ink-2);
}
.mb-context strong { color: var(--ink); font-weight: 600; }

.mb-head {
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.14em;
  text-transform: uppercase; fill: var(--ink-3);
}
.mb-rule { stroke: var(--line-2); stroke-width: 1; }
.mb-name { font-family: var(--display); font-size: 19px; fill: var(--ink); }
.mb-meta { font-family: var(--sans); font-size: 11px; fill: var(--ink-3); }

/* Neutral for the dish that only looks better, positive for the one that
   actually pays. Amber is reserved for actions, so it is not used here. */
.mb-bar--plain { fill: var(--ink-4); }
.mb-bar--good  { fill: var(--good); }
/* The recovered margin, drawn as separate segments so the bar shows where the
   gain came from rather than only that it grew. */
.mb-bar--gain  { fill: var(--good); opacity: 0.42; }

/* Each row is one question, what it found, and what it was worth. These were
   three prose questions in the lede and three unlabelled fixes in a list, so
   the one to one mapping between them was invisible. */
.mb-lead {
  margin: 2rem 0 0.9rem; font-family: var(--mono); font-size: 0.68rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3);
  padding-bottom: 0.7rem; border-bottom: 1px solid var(--line);
}
.mb-changes { margin: 0; padding: 0; list-style: none; display: grid; }
.mb-changes li {
  display: grid; grid-template-columns: minmax(0, 1fr) 4.5rem;
  gap: 0.3rem 1rem; align-items: baseline;
  padding: 0.95rem 0; border-bottom: 1px solid var(--line);
}
.mb-q { font-size: 0.95rem; font-weight: 600; color: var(--ink); line-height: 1.4; }
.mb-found { grid-column: 1; font-size: 0.85rem; color: var(--ink-3); line-height: 1.5; }
.mb-amt {
  grid-row: 1 / span 2; grid-column: 2; justify-self: end; align-self: center;
  font-family: var(--display); font-size: 1.5rem; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--good-2);
}
@media (max-width: 520px) {
  .mb-changes li { grid-template-columns: minmax(0, 1fr) auto; }
  .mb-amt { font-size: 1.3rem; }
}

/* 180 plates a month was stated without saying where it came from, and it is
   someone else's volume. Three rates let the reader find their own. */
.mb-scale { margin-top: 2rem; border: 1px solid var(--line); border-radius: var(--r);
  padding: 1.25rem 1.4rem; background: var(--paper-2); }
.mb-scale-head { margin: 0 0 0.9rem; font-family: var(--sans); font-size: 0.88rem;
  font-weight: 600; color: var(--ink); }
.mb-scale ul { list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; }
.mb-scale li { display: flex; flex-direction: column; gap: 0.3rem; }
.mb-rate { font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-3); }
.mb-worth { font-family: var(--display); font-size: 1.35rem; line-height: 1; color: var(--ink);
  font-variant-numeric: tabular-nums; }
.mb-scale-note { margin: 1rem 0 0; font-size: 0.8rem; color: var(--ink-3); }
@media (max-width: 520px) { .mb-scale ul { grid-template-columns: minmax(0, 1fr); gap: 0.85rem; } }

.mb-val { font-family: var(--mono); font-size: 15px; fill: var(--ink-2);
          font-variant-numeric: tabular-nums; }
.mb-val--good { fill: var(--good-2); font-weight: 500; }

.mb-cap { font-size: 0.9rem; line-height: 1.55; color: var(--ink-2);
          margin-top: 1.1rem; max-width: 31em; }
.mb-cap strong { color: var(--ink); font-weight: 600; }

/* ---------- Plate photography ---------- */

/* Masonry would reflow on load; a plain grid with intrinsic image ratios keeps
   every card the same width and lets height follow the photograph. */
.plates {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.4vw, 2rem);
}
@media (max-width: 1000px) { .plates { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px)  { .plates { grid-template-columns: minmax(0, 1fr); } }

.plate { margin: 0; }
/* The source photographs are a mix of 3:4 and 1:1, which left caption
   baselines drifting across a row. A common crop makes the grid read as one
   designed set; the plates are centred in frame so nothing important is lost. */
.plate img {
  width: 100%; height: auto; display: block;
  aspect-ratio: 4 / 5; object-fit: cover;
  border-radius: var(--r);
  background: var(--paper-2);   /* holds the space while the file loads */
}
.plate figcaption { padding-top: 0.9rem; }
.plate figcaption b {
  display: block; font-weight: 600; font-size: 0.95rem; line-height: 1.35; color: var(--ink);
}
.plate-tag {
  display: inline-block; margin-top: 0.5rem;
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-3);
  border: 1px solid var(--line-2); border-radius: var(--r);
  padding: 0.2rem 0.5rem;
}
.plate-note {
  display: block; margin-top: 0.6rem;
  font-size: 0.845rem; line-height: 1.5; color: var(--ink-3);
}

/* A sector page shows a few plates as evidence, not a full portfolio. */
.plates--inline { grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 2.5rem 0; }
@media (max-width: 640px) { .plates--inline { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.plates--inline .plate-note { display: none; }

/* The lever label names the commercial mechanism before the dish name is read,
   so a row of photographs scans as a taxonomy rather than a portfolio. It is
   deliberately not a chip: a bordered box on every plate reads as decoration,
   and .plate-tag is already spoken for by the sector classification. */
.plate-lever {
  display: block; margin-bottom: 0.4rem;
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--brass-2);
}
.plates--inline .plate-lever { display: none; }

/* The five levers the plates below are examples of, read before the evidence
   so the lever label on each photograph has something to belong to. A card grid
   would be the fifth on this page and the homepage is already dense on a phone. */
.levers-block { margin-bottom: clamp(2.5rem, 5vw, 3.25rem); }
.levers {
  margin-top: 1rem;
  display: grid; gap: 1.5rem clamp(1.25rem, 2.4vw, 2rem);
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
@media (max-width: 1000px) { .levers { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 580px)  { .levers { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* A hairline per column rather than one rule across the whole row: five
   measurements standing side by side, and visibly not the same object as the
   Worked with row further down, which is a label-and-sentence list. */
.lever { border-top: 1px solid var(--line-2); padding-top: 0.85rem; }
.lever h3 {
  font-family: var(--display); font-weight: 500; letter-spacing: -0.005em;
  font-size: 1.02rem; line-height: 1.25; color: var(--ink); margin: 0 0 0.4rem;
}
.lever p { font-size: 0.845rem; line-height: 1.5; color: var(--ink-3); margin: 0; }

/* ---------- Menu engineering matrix chart ---------- */

.matrix { margin: 0; }
.matrix svg { width: 100%; height: auto; display: block; overflow: visible; }
.mx-caption { font-size: 0.8rem; color: var(--ink-3); line-height: 1.5; margin-top: 1rem; max-width: 31em; }
.matrix--ink .mx-caption { color: var(--ink-4); }

.mx-fill-star   { fill: var(--good-wash); }
.mx-fill-plow   { fill: var(--brass-wash); }
.mx-fill-puzzle { fill: var(--info-wash); }
.mx-fill-dog    { fill: var(--paper-2); }

.mx-axis  { stroke: var(--line-2); stroke-width: 1; }
.mx-thresh{ stroke: var(--ink-4); stroke-width: 1; stroke-dasharray: 3 4; }
.mx-label { font-family: var(--mono); font-size: 9px; letter-spacing: 0.14em; text-transform: uppercase; fill: var(--ink-3); }
.mx-quad  { font-family: var(--display); font-size: 15px; fill: var(--ink-2); }
.mx-axis-title { font-family: var(--mono); font-size: 8.5px; letter-spacing: 0.16em; text-transform: uppercase; fill: var(--ink-3); }

.mx-dot { stroke: var(--paper); stroke-width: 1.5; transition: r .2s ease; }
.mx-dot-star   { fill: var(--good-2); }
.mx-dot-plow   { fill: var(--brass-2); }
.mx-dot-puzzle { fill: var(--info); }
.mx-dot-dog    { fill: var(--ink-4); }
.mx-dot-label { font-family: var(--sans); font-size: 9px; fill: var(--ink-2); }

/* Halo so labels stay legible where they cross gridlines or fills */
.mx-dot-label, .mx-live-label, .mx-quad {
  paint-order: stroke;
  stroke: var(--paper);
  stroke-width: 3px;
  stroke-linejoin: round;
}
.matrix--ink .mx-dot-label, .matrix--ink .mx-quad { stroke: var(--ink); }

/* Chart given the same surface as a card when it stands on its own */
.matrix--panel {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: clamp(1.25rem, 2.4vw, 1.75rem);
  box-shadow: var(--shadow-sm);
}
.matrix--panel .mx-caption { margin-top: 1.25rem; padding-top: 1rem; border-top: 1px solid var(--line); }

/* The chart's text is set in viewBox units, so it shrinks with the container.
   Rather than scale type against an unpredictable container width, the chart
   holds a floor width and scrolls sideways below it, the same way the tables
   do. That keeps one predictable scale, so a single modest type bump covers
   every narrow case. */
.matrix { overflow-x: auto; }
.matrix svg { min-width: 460px; }

/* A chart carrying no dish labels stays legible at any size, so it should fit
   its container rather than scroll inside it. Kept separate from the colour
   variants below: fit and palette are independent choices. */
.matrix--fit { overflow-x: visible; }
.matrix--fit svg { min-width: 0; }

@media (max-width: 620px) {
  .mx-quad { font-size: 16.5px; }
  .mx-dot-label { font-size: 11px; }
  .mx-axis-title { font-size: 10px; letter-spacing: 0.1em; }
  .mx-live-label { font-size: 10px; }
}

/* live marker on the calculator */
.mx-live { transition: transform .5s cubic-bezier(.2,.7,.3,1), opacity .3s ease; }
.mx-live-ring { fill: none; stroke-width: 1.5; opacity: .55; }
.mx-live-dot { stroke: var(--paper); stroke-width: 2; }
.mx-stroke-star   { stroke: var(--good-2); }
.mx-stroke-plow   { stroke: var(--brass-2); }
.mx-stroke-puzzle { stroke: var(--info); }
.mx-stroke-dog    { stroke: var(--ink-4); }
.mx-live-label { font-family: var(--mono); font-size: 8.5px; letter-spacing: 0.12em; text-transform: uppercase; fill: var(--ink-3); }

@keyframes mx-pulse { 0%,100% { r: 13; opacity: .5; } 50% { r: 16; opacity: .22; } }
.mx-live-ring { animation: mx-pulse 2.6s ease-in-out infinite; }

/* dark variant for the ink panel */
.matrix--ink .mx-fill-star   { fill: rgba(16,148,104,.16); }
.matrix--ink .mx-fill-plow   { fill: rgba(245,158,11,.15); }
.matrix--ink .mx-fill-puzzle { fill: rgba(59,91,165,.17); }
.matrix--ink .mx-fill-dog    { fill: rgba(255,255,255,.04); }
.matrix--ink .mx-axis   { stroke: #4A4139; }
.matrix--ink .mx-thresh { stroke: #6E645B; }
.matrix--ink .mx-label, .matrix--ink .mx-axis-title { fill: var(--ink-4); }
.matrix--ink .mx-quad   { fill: #D8D0C7; }
.matrix--ink .mx-dot    { stroke: var(--ink); }
.matrix--ink .mx-dot-star { fill: var(--good); }
.matrix--ink .mx-dot-plow { fill: var(--brass); }
.matrix--ink .mx-dot-puzzle { fill: #7B9BD6; }
.matrix--ink .mx-dot-dog { fill: #7C736C; }
.matrix--ink .mx-dot-label { fill: var(--on-green-2); }

/* ---------- Quadrant cards ---------- */

.quadrant {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px;
  background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
}
.quadrant .q { background: var(--paper); padding: 1.35rem; min-height: 150px; transition: background .25s ease; position: relative; }
.quadrant .q .qname { font-family: var(--display); font-size: 1.4rem; display: block; margin-bottom: 0.3rem; }
.quadrant .q .qmeta { font-family: var(--mono); font-size: 0.63rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); display: block; margin-bottom: 0.7rem; }
.quadrant .q p { font-size: 0.87rem; color: var(--ink-2); margin: 0; }
.q-star   { box-shadow: inset 3px 0 0 var(--good); }
.q-plow   { box-shadow: inset 3px 0 0 var(--brass); }
.q-puzzle { box-shadow: inset 3px 0 0 var(--info); }
.q-dog    { box-shadow: inset 3px 0 0 var(--line-2); }
.q-star.is-active   { background: var(--good-wash); }
.q-plow.is-active   { background: var(--brass-wash); }
.q-puzzle.is-active { background: var(--info-wash); }
.q-dog.is-active    { background: var(--paper-2); }

/* ---------- Free tools: copy, dish card, matrix ---------- */
/* Three columns, because the argument needs all three to land: what the tools
   do, one dish costed, and where that dish ends up. The card and the matrix
   are tied by the amber on the Star, which is the only amber in the block. */
/* The card and the matrix are set to one height so their edges line up. The
   photograph takes whatever is left after the figures, which is what lets the
   two columns agree without either being padded to fake it. */
.tools-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) 260px minmax(0, 1.15fr);
  gap: clamp(2rem, 4vw, 3.5rem); align-items: start;
}
@media (max-width: 1080px) { .tools-grid { grid-template-columns: minmax(0, 1fr) 260px; } 
  .tools-grid .quad-matrix { grid-column: 1 / -1; } }
@media (max-width: 760px) { .tools-grid { grid-template-columns: minmax(0, 1fr); }
  .tools-grid .dish-card { max-width: 320px; } }
.tools-copy .lede { margin-bottom: 0.9rem; }
.tools-copy .btn-row { margin-top: 1.75rem; align-items: center; }

/* the dish card: a costed plate, which is the artefact the tools produce */
.dish-card {
  margin: 0; background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r); overflow: hidden; box-shadow: var(--shadow-md);
  display: flex; flex-direction: column;
}
/* Square. Judged against 4:5, 5:4 and 3:2 side by side rather than reasoned:
   the full 4:5 rendition carries a band of dark worktop across the top that is
   the dead space making the card look top heavy, and 1:1 removes it while
   keeping the whole plate and its rim. 5:4 starts cutting the rim, and 4:3,
   which this began as, took 40% of the height out of the middle. */
/* Square. The source is 4:5 and the plate fills it to the rim, so a 3:2 window
   cut the rim off top and bottom and the dish read as cropped. 1:1 keeps the
   plate whole.
   The card is then taller than the matrix's own content, so the quadrant takes
   a min-height to match rather than the photograph being squeezed to fit the
   text beside it. The picture is the thing a reader looks at; the quadrant is
   four short paragraphs and can afford the room. */
.dish-card img {
  display: block; width: 100%; aspect-ratio: 1 / 1;
  object-fit: cover; object-position: center 48%;
}
.dish-body { padding: 0.85rem 1.1rem 0.45rem; }
.dish-head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 0.7rem; padding-bottom: 0.7rem; border-bottom: 1px solid var(--line);
}
.dish-name { font-family: var(--display); font-size: 1.18rem; }
.dish-price { font-family: var(--mono); font-size: 1.02rem; font-variant-numeric: tabular-nums; }
.dish-rows { margin: 0; }
.dish-rows > div {
  display: flex; justify-content: space-between; gap: 0.7rem;
  padding: 0.42rem 0; border-bottom: 1px solid var(--line);
}
.dish-rows > div:last-child { border-bottom: 0; }
.dish-rows dt { font-size: 0.85rem; color: var(--ink-3); margin: 0; }
.dish-rows dd {
  margin: 0; font-family: var(--mono); font-size: 0.85rem;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.dish-verdict {
  background: var(--brass-wash); border-top: 1px solid var(--line);
  padding: 0.65rem 1.1rem 0.7rem;
}
.dish-cls {
  display: block; font-family: var(--display); font-size: 1.05rem; color: var(--brass-2);
}
.dish-meta {
  display: block; font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-3); padding-top: 0.15rem;
}

/* the matrix, with its axes named. Without them the four boxes are a 2x2 of
   adjectives; with them they are a chart someone can place a dish on. */
/* Named quad-matrix, not matrix: `.matrix` was already the SVG chart on
   /tools/food-cost-calculator/ and /menu-engineering/, and reusing the
   name gave that chart a three row grid it was never built for, which
   clipped 54px off it. Two different components cannot share a class. */
/* The axis labels sit in a band of a declared height, top and bottom, and the
   dish column takes the same band as padding. That is what makes the card and
   the quadrant agree: both are "the column height, less two bands". Letting
   the labels size themselves put the card 53px proud at each end. */
.quad-matrix {
  --qm-band: 1.6rem;
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: var(--qm-band) minmax(0, 1fr) var(--qm-band);
  align-items: center; gap: 0 0.6rem;
}
.qm-ax {
  font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--ink-3);
}
.qm-top   { grid-area: 1 / 2; text-align: center; }
.qm-bot   { grid-area: 3 / 2; text-align: center; }
.qm-left  { grid-area: 2 / 1; writing-mode: vertical-rl; transform: rotate(180deg); text-align: center; }
.qm-right { grid-area: 2 / 3; writing-mode: vertical-rl; text-align: center; }
.quad-matrix .quadrant { grid-area: 2 / 2; align-self: stretch; min-height: 37.5rem; }

/* the landed dish. The amber wash is the tie back to the card's verdict, and
   it is the only amber in this block, so it still means "this one". */
.quadrant .q.is-landed { background: var(--brass-wash); }
.quadrant .q.is-landed .qname { color: var(--brass-2); }
/* Inside the named matrix the four coloured bars come off. One of them was
   --info navy, which is in no part of the palette, and the amber on Plowhorse
   competed with the amber marking where the dish landed. The axes now carry
   what the colours were carrying, and amber means one thing again. */
.quad-matrix .q-star, .quad-matrix .q-plow,
.quad-matrix .q-puzzle, .quad-matrix .q-dog { box-shadow: none; }

/* the text link beside the button took --info-2, the default navy that is in
   no part of the documented palette. Ink with a brass underline instead. */
.tools-copy .arrow-link { color: var(--ink); }
.tools-copy .arrow-link::after { color: var(--brass-2); }

/* The annotation tying the costed dish to where it lands. Set in the display
   face in italic rather than a script: a handwriting font would be a fourth
   family on the site and reads as decoration. Desktop only, because once the
   grid stacks the card already sits directly above the matrix and the arrow
   would point at nothing. */
.dish-col { position: relative; display: flex; flex-direction: column;
  padding-block: 1.6rem; }
/* Under the card, not beside it. The gutter between the card and the matrix
   measures 51px, so an annotation placed there is clipped by the matrix the
   moment it carries any words. Below the card it reads in the same order the
   eye already travels: dish, verdict, then across. */
/* Hangs below the card so the card and the matrix still end on the same line.

   The arrow is horizontal and runs into the gutter. A curved arrow aimed at
   the matrix corner was tried twice and missed both times: its tip lands on a
   coordinate that moves with the column widths, so it pointed at empty space
   at any width other than the one it was tuned at. A straight rule pointing
   right cannot miss, because it points at a direction rather than a point. */
.lands {
  position: absolute; top: 100%; left: 0;
  /* exactly the grid gutter, so the tip meets the matrix column edge at any
     width rather than a value tuned at one */
  right: calc(-1 * clamp(2rem, 4vw, 3.5rem));
  display: none; margin: 0.55rem 0 0; color: var(--brass-2);
  align-items: center; gap: 0.75rem; pointer-events: none;
}
@media (min-width: 1081px) { .lands { display: flex; } }
.lands-t {
  font-family: var(--display); font-style: italic; font-size: 0.95rem;
  line-height: 1.3; color: var(--ink-3); white-space: nowrap;
}
.lands-a { display: block; flex: 1 1 auto; min-width: 54px; height: 8px; }

.tools-note {
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-3); margin-top: 1.6rem;
}
/* the annotation hangs out of the grid, so the note below has to clear it */
@media (min-width: 1081px) { .tools-note { margin-top: 2.6rem; } }

/* ---------- Calculator ---------- */

.calc {
  display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: 0;
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
  background: var(--paper); box-shadow: var(--shadow-md);
}
@media (max-width: 880px) { .calc { grid-template-columns: minmax(0, 1fr); } }
.calc-inputs { padding: clamp(1.5rem, 3vw, 2.1rem); border-right: 1px solid var(--line); background: var(--paper-2); }
@media (max-width: 880px) { .calc-inputs { border-right: 0; border-bottom: 1px solid var(--line); } }
.calc-out { padding: clamp(1.5rem, 3vw, 2.1rem); }

.field { margin-bottom: 1.3rem; }
.field label { display: block; font-size: 0.82rem; font-weight: 600; margin-bottom: 0.42rem; }
.field .hint { display: block; font-size: 0.84rem; color: var(--ink-3); margin-top: 0.4rem; line-height: 1.45; }

.input-money { position: relative; display: flex; align-items: center; }
.input-money .sym { position: absolute; left: 0.9rem; font-family: var(--mono); font-size: 0.9rem; color: var(--ink-3); pointer-events: none; }

/* Styled by exclusion rather than by listing types: adding a new field type
   should never silently produce an unstyled browser default, which is exactly
   what happened when the phone field moved from text to tel. */
input:where(:not([type="radio"]):not([type="checkbox"]):not([type="range"]):not([type="submit"]):not([type="button"]):not([type="hidden"]):not([type="file"])),
select, textarea {
  width: 100%; padding: 0.72rem 0.9rem;
  font-family: var(--sans); font-size: 0.95rem; font-variant-numeric: tabular-nums;
  color: var(--ink); background: var(--paper);
  border: 1px solid var(--line-2); border-radius: var(--r);
  transition: border-color .15s ease, box-shadow .15s ease;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--info);
  box-shadow: 0 0 0 3px var(--info-wash);
}
/* Numeric entry uses the mono face so digits align; everything else is body
   text and takes the sans. The exclusions above are wrapped in :where() so they
   contribute no specificity, otherwise this single-attribute rule could never
   win against a seven-:not() chain. */
input[type="number"] { font-family: var(--mono); }
textarea { min-height: 130px; resize: vertical; line-height: 1.55; }

/* Must follow the generic input rule so the currency symbol has room. */
.input-money input[type="number"] { padding-left: 2.05rem; }

.readout { border-top: 1px solid var(--line); padding-top: 1.15rem; margin-top: 1.15rem; }
.readout:first-child { border-top: 0; padding-top: 0; margin-top: 0; }
.readout .k { font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); display: block; margin-bottom: 0.35rem; }
.readout .v {
  font-family: var(--display); font-size: clamp(2.05rem, 4.5vw, 2.9rem); line-height: 1;
  font-variant-numeric: tabular-nums; display: block;
}
.readout .sub { font-size: 0.815rem; color: var(--ink-3); margin-top: 0.42rem; display: block; line-height: 1.45; }
.v--good { color: var(--good-2); }
.v--bad { color: var(--bad-2); }
.v--info { color: var(--info-2); }

/* A calculator's headline answer, with its workings beneath it at a smaller
   size. Without the step down every figure competes and the eye picks the
   first one it meets rather than the one that matters. */
.readout--lead .v { font-size: clamp(2.6rem, 6vw, 3.9rem); }
.readout--lead .k { color: var(--ink-2); }
.readout .v--sm { font-size: clamp(1.4rem, 2.6vw, 1.8rem); }
.readout-caption {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-3);
  margin: 1.6rem 0 1.15rem; padding-top: 1.15rem; border-top: 1px solid var(--line);
}

.readout-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.3rem; }
/* .readout carries a top hairline so stacked readouts separate. Side by
   side only the second one is :first-child-less, so the rule appeared over
   one column and not the other and read as a mistake. */
.readout-row > .readout { border-top: 0; padding-top: 0; margin-top: 0; }
@media (max-width: 460px) { .readout-row { grid-template-columns: minmax(0, 1fr); } }

.verdict {
  margin-top: 1.6rem; border: 1px solid var(--line); border-left-width: 3px;
  border-radius: 0 var(--r) var(--r) 0; padding: 1.2rem 1.4rem; background: var(--paper-2);
  transition: background .3s ease, border-color .3s ease;
}
.verdict .tag { font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.15em; text-transform: uppercase; display: inline-block; margin-bottom: 0.5rem; }
.verdict .h-sm { margin: 0 0 0.4rem; font-size: 1.06rem; }
.verdict p { margin: 0; font-size: 0.9rem; color: var(--ink-2); }
.verdict[data-class="star"]      { border-left-color: var(--good);  background: var(--good-wash); }
.verdict[data-class="star"] .tag { color: var(--good-2); }
.verdict[data-class="plowhorse"]      { border-left-color: var(--brass); background: var(--brass-wash); }
.verdict[data-class="plowhorse"] .tag { color: var(--brass-2); }
.verdict[data-class="puzzle"]      { border-left-color: var(--info); background: var(--info-wash); }
.verdict[data-class="puzzle"] .tag { color: var(--info-2); }
.verdict[data-class="dog"]      { border-left-color: var(--line-2); background: var(--paper-2); }
.verdict[data-class="dog"] .tag { color: var(--ink-3); }

.seg { display: flex; border: 1px solid var(--edge); border-radius: var(--r); overflow: hidden; }
.seg input { position: absolute; opacity: 0; pointer-events: none; }
.seg label {
  flex: 1; margin: 0; text-align: center; cursor: pointer; padding: 0.58rem 0.4rem;
  font-size: 0.8rem; font-weight: 500; background: var(--paper); color: var(--ink-2);
  border-right: 1px solid var(--edge); transition: background .15s ease, color .15s ease;
}
.seg label:last-of-type { border-right: 0; }
.seg label:hover { background: var(--paper-3); }
.seg input:checked + label { background: var(--ink); color: var(--paper); }
.seg input:focus-visible + label { box-shadow: inset 0 0 0 2px var(--info); }

.rows { width: 100%; }
.row-line { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr) 2.2rem; gap: 0.5rem; margin-bottom: 0.5rem; align-items: center; }
.row-line input { padding: 0.55rem 0.65rem; font-size: 0.86rem; }
.row-head { font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); }
.row-del {
  border: 1px solid var(--edge); background: var(--paper); border-radius: var(--r);
  cursor: pointer; height: 2.2rem; color: var(--ink-3); font-size: 1rem; line-height: 1; padding: 0;
  transition: border-color .15s ease, color .15s ease;
}
.row-del:hover { border-color: var(--brass); color: var(--brass-2); }
@media (max-width: 560px) { .row-line { grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,1fr) 2.2rem; } }

/* ---------- Case study ---------- */

.case { border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; background: var(--paper); box-shadow: var(--shadow-sm); }
.case-body { padding: clamp(1.5rem, 3vw, 2.1rem); }

/* The case header carries the venue, because the venue IS the identity here.
   Displaying a client's logo would need their written permission separately
   from the quote approvals we hold, so the name is set in type instead. */
.case-id { display: flex; align-items: flex-start; gap: clamp(0.9rem, 2vw, 1.4rem);
  padding: clamp(1.5rem, 3vw, 2.1rem); border-bottom: 1px solid var(--line); background: var(--paper-2); }
.case-id .num { font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--ink-3); border: 1px solid var(--line-2); border-radius: var(--r);
  padding: 0.45rem 0.6rem; line-height: 1; flex: 0 0 auto; margin-top: 0.35rem; }
.case-id .venue { font-family: var(--display); font-size: clamp(1.5rem, 2.6vw, 2rem); line-height: 1.05;
  margin: 0 0 0.45rem; letter-spacing: -0.01em; }
.case-id .tags { font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--ink-3); display: flex; flex-wrap: wrap; gap: 0.4rem 1.25rem; }

/* One figure per case leads. Three equally weighted metrics buried the number
   that actually sells the case: 300 to 650 read the same as 69.8% to 73.4%. */
.case-claim { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3rem); align-items: center;
  padding: clamp(1.5rem, 3vw, 2.1rem); border-bottom: 1px solid var(--line); }
.case-claim h3 { margin: 0 0 0.6rem; }
.case-claim .small { margin: 0; }
.hero-fig { border-left: 3px solid var(--good); padding-left: 1.15rem; }
.hero-fig .n { font-family: var(--display); font-size: clamp(2.6rem, 6vw, 3.6rem); line-height: 0.92;
  color: var(--good-2); font-variant-numeric: tabular-nums; display: block; }
.hero-fig .cap { font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.11em; text-transform: uppercase;
  color: var(--ink-3); display: block; margin-top: 0.55rem; line-height: 1.5; }

/* The movement is the story, so the delta is the large figure and the raw
   before/after sits under it. No bars: three metrics on three different
   scales side by side invite a comparison the units do not support. */
.movers { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; background: var(--white); }
.mover { padding: 1.25rem 1.3rem 1.15rem; border-right: 1px solid var(--line); }
.mover:last-child { border-right: 0; }
.mover .k { font-family: var(--sans); font-size: 0.82rem; font-weight: 600; color: var(--ink-2);
  display: block; margin-bottom: 0.9rem; line-height: 1.3; }
.mover .delta { font-family: var(--display); font-size: 1.9rem; line-height: 1; color: var(--good-2);
  font-variant-numeric: tabular-nums; display: block; }
.mover .ba-line { font-family: var(--mono); font-size: 0.74rem; color: var(--ink-3); margin-top: 0.7rem;
  display: flex; align-items: baseline; gap: 0.45rem; flex-wrap: wrap; }
.mover .ba-line .was { text-decoration: line-through; text-decoration-color: var(--ink-4); }
.mover .ba-line .now { color: var(--ink); font-weight: 500; }
@media (max-width: 760px) {
  .movers { grid-template-columns: minmax(0, 1fr); }
  .mover { border-right: 0; border-bottom: 1px solid var(--line); }
  .mover:last-child { border-bottom: 0; }
  .case-claim { grid-template-columns: minmax(0, 1fr); }
}

/* Plate groups: a heading per kitchen type so fifteen photographs read as
   three considered sets rather than one undifferentiated wall. */
.plate-group + .plate-group { margin-top: clamp(2.5rem, 5vw, 3.5rem); }
.plate-group > h3 { font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-3); font-weight: 500;
  padding-bottom: 0.75rem; border-bottom: 1px solid var(--line); margin: 0 0 clamp(1.25rem, 2.4vw, 2rem); }

.placeholder-note {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--info-2); background: var(--info-wash);
  border: 1px dashed color-mix(in srgb, var(--info) 55%, transparent);
  border-radius: var(--r); padding: 0.45rem 0.8rem; display: inline-block;
}

/* ---------- Article ---------- */

.article-meta {
  display: flex; flex-wrap: wrap; gap: 0.4rem 1.6rem;
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.13em; text-transform: uppercase; color: var(--ink-3);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding-block: 0.95rem; margin-block: 2.25rem;
}

/* The 60 second version. This page is 4,600 words over 21 sections, which is
   the right depth for search and far too much for someone deciding whether to
   read at all. The summary gives them the answer up front; the depth stays. */
.tldr {
  background: var(--white);
  border: 1px solid var(--line);
  border-left: 3px solid var(--brass);
  border-radius: var(--r);
  padding: clamp(1.4rem, 2.4vw, 1.9rem);
  margin-bottom: 2.5rem;
}
.tldr ol { margin: 0; padding-left: 1.25rem; }
.tldr li { margin-bottom: 0.75rem; font-size: 0.94rem; line-height: 1.55; color: var(--ink-2); }
.tldr li:last-child { margin-bottom: 0; }
.tldr li::marker { font-family: var(--mono); font-size: 0.8em; color: var(--brass-2); }
.tldr strong { color: var(--ink); font-weight: 600; }
.tldr-more {
  margin: 1.15rem 0 0; padding-top: 0.9rem; border-top: 1px solid var(--line);
  font-size: 0.85rem; color: var(--ink-3);
}

/* Sits inline at the top of a long article, not in a sticky rail. A 500px
   sidebar beside a 19,000px page left about twenty screens of dead column.
   Two columns so fourteen entries stay compact. */
.toc {
  background: var(--paper-2); border: 1px solid var(--line);
  border-radius: var(--r); padding: 1.45rem 1.7rem;
  margin-bottom: 3rem;
}
.toc ol { columns: 2; column-gap: 2.5rem; }
@media (max-width: 620px) { .toc ol { columns: 1; } }
.toc li { break-inside: avoid; }
.toc h2 { margin-bottom: 0.8rem; font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); font-weight: 500; }
.toc ol { margin: 0; padding-left: 1.15rem; }
.toc li { margin-bottom: 0.42rem; font-size: 0.89rem; }
.toc li::marker { font-family: var(--mono); font-size: 0.78em; color: var(--ink-4); }
.toc a { color: var(--ink-2); text-decoration: none; border-bottom: 1px solid transparent; }
.toc a:hover { color: var(--info-2); border-color: var(--info); }

/* The About page carries its identity block in the hero rather than as a
   byline mid-article, so it needs a rule above it and a little more room. */
.author--lead { margin-top: 2.25rem; padding-top: 1.75rem; border-top: 1px solid var(--line); }

.author--compact {
  margin-top: 2.5rem; padding-top: 1.4rem;
  border-top: 1px solid var(--line);
}
.author--compact .author-face { width: 48px; height: 48px; }
.author--compact .author-name { font-size: 0.92rem; }
.author--compact .author-bio { margin-bottom: 0; font-size: 0.85rem; }

/* An inline next step inside a long article. Deliberately quieter than a
   band: a rule, a line of copy and one action, so it reads as part of the
   argument rather than an advert dropped into it. */
.nextstep {
  margin: 3.25rem 0;
  padding: 1.4rem 0 0;
  border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0.5rem 1.5rem;
}
.nextstep p { margin: 0; font-size: 0.95rem; color: var(--ink-2); flex: 1 1 22ch; }
.nextstep .btn { flex: 0 0 auto; }

.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; padding: 1.2rem 0; font-weight: 600; font-size: 1rem;
  list-style: none; display: flex; justify-content: space-between; gap: 1.5rem; align-items: baseline;
  transition: color .15s ease;
}
.faq summary:hover { color: var(--brass-2); }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; font-family: var(--mono); color: var(--brass-2); font-size: 1.15rem; }
.faq details[open] summary::after { content: "\2212"; }
.faq .answer { padding-bottom: 1.35rem; font-size: 0.95rem; color: var(--ink-2); max-width: 31em; }
.faq .answer p:last-child { margin-bottom: 0; }

/* ---------- CTA ---------- */

.cta-block h2 { max-width: 20ch; }
.cta-block .lede { margin-bottom: 2.15rem; }

/* ---------- Footer ---------- */

/* The footer is white. It was green, and the brand mark in it is the REVERSED
   lockup, which is light artwork: swapping the ground without swapping the
   lockup would have left an invisible logo. Every hairline and every quiet grey
   in here was tuned for a dark ground and had to come back to the light set. */
.site-footer {
  background: var(--white); color: var(--ink-3);
  border-top: 1px solid var(--line-2);
  padding-block: clamp(3.25rem, 6vw, 5rem) 2rem; font-size: 0.9rem;
}
.site-footer a { color: var(--ink); text-decoration: none; transition: color .15s ease; }
.site-footer a:hover { color: var(--brass-2); }
.footer-grid { display: grid; grid-template-columns: minmax(0, 1.6fr) repeat(4, minmax(0, 1fr)); gap: 2.5rem; }
@media (max-width: 880px) { .footer-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
@media (max-width: 520px) { .footer-grid { grid-template-columns: minmax(0, 1fr); } }
.site-footer h2 { color: var(--ink-3); font-family: var(--mono); font-size: 0.64rem; letter-spacing: 0.16em; text-transform: uppercase; font-weight: 500; margin-bottom: 1.05rem; }
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: 0.58rem; font-size: 0.875rem; }
.site-footer .wordmark { margin-bottom: 1rem; }
.site-footer .wordmark b { color: var(--ink); }
.site-footer .wordmark span { color: var(--ink-3); }
.footer-base {
  margin-top: 3.25rem; padding-top: 1.6rem; border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem 1rem;
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
/* The legal links sit in small caps type; pad them out to a usable target. */
.footer-base a { display: inline-flex; align-items: center; min-height: 24px; }

/* The statutory disclosure. A sole trader has no separate legal personality,
   so the named human IS the legal person, and reg. 6 of the Electronic
   Commerce (EC Directive) Regulations 2002 wants that name and a geographic
   address easily and permanently accessible.

   It cannot be set in .footer-base's own type. That is 10.56px mono, uppercase
   and tracked 0.1em, which would put a person's name and a postal address in
   spaced capitals at a size nothing legal should be read at. So it takes a row
   of its own: width 100% claims a full line because the parent wraps, and the
   three inherited properties are reset rather than overridden piecemeal.

   --ink-4 is a hairline colour on light grounds and never text there, but on
   the footer ink it measures 5.68:1, so it clears 1.4.3 for normal text. */
.footer-legal {
  width: 100%;
  margin: 0 0 0.45rem;
  font-family: var(--sans);
  font-size: 0.8rem;
  letter-spacing: 0;
  text-transform: none;
  /* The statutory line follows the footer's ground: --ink-3 on white. */
  color: var(--ink-3);
}


/* Section rhythm is carried by layout, type scale and hairline rules, not by
   flipping the background every section. Across a page there should be at most
   one tinted band and one ink anchor. */
.section--rule { border-top: 1px solid var(--line); }
.section--flush { padding-top: 0; }

/* The brand line, set small and quiet under the mark. */
.brandline {
  font-family: var(--display); font-size: 1.02rem; line-height: 1.3;
  color: var(--ink); margin: 0.85rem 0 0.6rem;
}

/* ---------- Utility ---------- */

.skip { position: absolute; left: -9999px; top: 0; background: var(--ink); color: var(--paper); padding: 0.8rem 1.3rem; z-index: 100; border-radius: 0 0 var(--r) 0; }
.skip:focus { left: 0; }

hr { border: 0; border-top: 1px solid var(--line); margin-block: clamp(2.5rem, 5vw, 4rem); }

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

/* Scroll reveal */
.reveal { opacity: 0; transform: translateY(18px); transition: opacity .7s cubic-bezier(.2,.7,.3,1), transform .7s cubic-bezier(.2,.7,.3,1); }
.reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
  .reveal { opacity: 1; transform: none; }
}

/* ==========================================================================
   Print. Operators do print audit pages and guides to mark up, so the long
   form pages need to survive a printer: no interface furniture, no ink
   flooded backgrounds, and link destinations made visible.
   ========================================================================== */

@media print {
  :root {
    --ink: #000; --ink-2: #1a1a1a; --ink-3: #444;
    --paper: #fff; --paper-2: #fff; --paper-3: #fff;
    --line: #bbb; --line-2: #999;
  }
  body { font-size: 11pt; line-height: 1.45; background: #fff; }
  body::before { display: none; }

  .site-header, .site-footer, .nav, .nav-toggle, .btn, .btn-row,
  .skip, .cta-block, .mock-note, .toc { display: none !important; }

  main, section { padding-block: 0 !important; }
  section + section { margin-top: 1.5rem; }
  .wrap { max-width: none; padding-inline: 0; }
  .split, .grid, .g2, .g3, .g4, .calc { display: block !important; }

  .band, .band--ink, .hero-panel, .card, .callout, .case, .verdict {
    background: #fff !important; color: #000 !important;
    background-image: none !important; box-shadow: none !important;
    border: 1px solid #bbb;
  }
  .band--ink h1, .band--ink h2, .band--ink h3, .band--ink .lede { color: #000 !important; }

  h1 { font-size: 22pt; } h2 { font-size: 15pt; } h3, .h-sm { font-size: 12pt; }
  h1, h2, h3 { break-after: avoid; page-break-after: avoid; }
  .card, .case, .callout, .rulelist > li, tr, .matrix { break-inside: avoid; page-break-inside: avoid; }

  .table-scroll { overflow: visible !important; border: 0; }
  table { min-width: 0; font-size: 9.5pt; }
  thead { display: table-header-group; }

  /* Reveal animations must never leave printed content blank. */
  .reveal { opacity: 1 !important; transform: none !important; }

  /* A printed link is useless without its destination. */
  .prose a[href^="/"]::after  { content: " (ryanpurrington.co.uk" attr(href) ")"; font-size: 8.5pt; color: #555; }
  .prose a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 8.5pt; color: #555; }

  .faq details { break-inside: avoid; }
  .faq .answer { display: block !important; }
  .placeholder-note { border: 1px dashed #999; color: #333; background: #fff; }
}

.req { color: var(--bad-2); font-weight: 500; }

/* ---------- Printable dish sheet ---------- */
/* A branded one page PDF without shipping a PDF library. The browser's own
   print to PDF renders the real brand fonts and the real logo, which jsPDF
   would have to redraw, and it costs nothing on a page nobody prints. */
.sheet { display: none; }

@media print {
  /* When the sheet is being printed it IS the document. Everything else is a
     sibling of it under body, so one rule removes the whole site. */
  body.sheet-only > *:not(.sheet) { display: none !important; }
  body.sheet-only .sheet { display: block; }

  .sheet-head {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 2rem; border-bottom: 1.5pt solid #000; padding-bottom: 10pt;
  }
  .sheet-head img { height: 17pt; width: auto; }
  .sheet-date { font-family: var(--mono); font-size: 8.5pt; color: #444; margin: 0; }

  .sheet-title {
    font-family: var(--display); font-weight: 500; letter-spacing: -0.015em;
    font-size: 20pt; line-height: 1.1; margin: 22pt 0 2pt;
  }
  .sheet-dish { font-size: 12pt; color: #333; margin: 0 0 20pt; }

  .sheet-table { width: 100%; border-collapse: collapse; font-size: 11pt; }
  .sheet-table th, .sheet-table td { padding: 7pt 0; border-bottom: 0.5pt solid #ccc; text-align: left; }
  .sheet-table th { font-weight: 400; color: #333; width: 58%; }
  .sheet-table td {
    font-family: var(--mono); font-variant-numeric: tabular-nums;
    text-align: right; font-weight: 500;
  }
  .sheet-table tr.is-headline td, .sheet-table tr.is-headline th { font-size: 13pt; }
  .sheet-table tr:last-child th, .sheet-table tr:last-child td { border-bottom: 0; }

  .sheet-verdict { margin-top: 20pt; border: 1pt solid #000; padding: 12pt 14pt; }
  .sheet-k {
    font-family: var(--mono); font-size: 8pt; letter-spacing: 0.12em;
    text-transform: uppercase; color: #444; margin: 0 0 4pt;
  }
  .sheet-class { font-family: var(--display); font-size: 16pt; margin: 0 0 5pt; }
  .sheet-action { font-size: 10.5pt; margin: 0; }

  .sheet-foot { margin-top: 22pt; border-top: 0.5pt solid #ccc; padding-top: 9pt; }
  .sheet-foot p { font-size: 8.5pt; color: #444; margin: 0 0 5pt; line-height: 1.45; }
  .sheet-url { font-family: var(--mono); color: #000 !important; }

  @page { margin: 16mm; }
}

/* ---------- Analytics consent ---------- */
/* Restrained by design: a corner card rather than a full width slab, because
   a banner that covers the hero is the thing everyone hates about these. Both
   buttons carry equal visual weight, since a Decline that is harder to find
   than Allow is not freely given consent under UK GDPR Art. 4(11). */
.consent {
  position: fixed; z-index: 90;
  left: 1rem; right: 1rem; bottom: 1rem;
  max-width: 30em; margin-inline: auto;
  background: var(--white);
  border: 1px solid var(--line-2);
  border-left: 3px solid var(--brass);
  border-radius: var(--r);
  padding: 1.1rem 1.25rem;
  box-shadow: 0 2px 16px rgba(26, 22, 20, 0.1);
}
@media (min-width: 720px) { .consent { left: 1.5rem; right: auto; bottom: 1.5rem; margin-inline: 0; } }
.consent-copy { font-size: 0.86rem; line-height: 1.5; color: var(--ink-2); margin: 0 0 0.9rem; }
.consent-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; }
@media (prefers-reduced-motion: no-preference) {
  .consent { animation: consent-in 0.22s ease-out both; }
  @keyframes consent-in { from { opacity: 0; transform: translateY(8px); } }
}

/* ---------- Form validation and submission state ---------- */

.field--error input, .field--error select, .field--error textarea {
  border-color: var(--bad-2);
}
.field-error {
  display: block; margin-top: 0.4rem;
  font-size: 0.84rem; line-height: 1.45; color: var(--bad-2);
}
@media (pointer: coarse) {
  /* The nav toggle measured 32px and the small buttons 33px. These are
     standalone controls, so they take the 44px target rather than the 24px
     WCAG 2.5.8 floor that inline prose links sit on. */
  .nav-toggle, .btn--sm { min-height: 44px; }
  .nav-toggle { min-width: 44px; }
  .calc input[type="number"], .calc input[type="text"], .calc select,
  .seg label, .rcc-row input, .rcc-row select {
    min-height: 44px;
  }
  .seg label { display: flex; align-items: center; justify-content: center; }
  .calc input[type="range"] { height: 44px; }
}

.form-status { margin: 0 0 1rem; }
.form-status:empty { margin: 0; }
.form-status--ok, .form-status--manual {
  background: color-mix(in srgb, var(--good-wash) 58%, var(--white));
  border: 1px solid color-mix(in srgb, var(--good) 20%, var(--line));
  border-left: 3px solid var(--good);
  border-radius: var(--r); padding: 1rem 1.2rem;
}
/* The manual path is a fallback, not a failure, so it takes the brass family
   rather than the red one: there is an action to finish, nothing is broken. */
.form-status--manual {
  background: color-mix(in srgb, var(--brass-wash) 58%, var(--white));
  border-color: color-mix(in srgb, var(--brass) 20%, var(--line));
  border-left-color: var(--brass);
}
.form-status-head {
  font-family: var(--display); font-weight: 500; font-size: 1.04em;
  margin: 0 0 0.4rem; line-height: 1.3;
}
.form-status p:last-child { margin-bottom: 0; }
/* The composed enquiry, printed so it can be copied when no mail client picks
   up the mailto. Wraps rather than scrolls, because it has to be selectable. */
.form-dump {
  margin: 0.8rem 0 0; padding: 0.8rem 0.9rem;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r);
  font-family: var(--mono); font-size: 0.78rem; line-height: 1.55; color: var(--ink-2);
  white-space: pre-wrap; word-break: break-word;
}
/* Honeypot: removed from the visual and accessibility trees, still submitted. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ==========================================================================
   Evidence components. UK CAP Code rule 3.7 requires documentary evidence for
   objective claims, so every statistic on the site carries its source, and
   anything hypothetical is labelled as such rather than left to be read as a
   delivered result.
   ========================================================================== */

.cite {
  font-family: var(--sans); font-size: 0.82em; letter-spacing: 0;
  color: var(--ink-3);
  /* Must wrap: author lists are long enough to force page overflow otherwise. */
  white-space: normal; overflow-wrap: anywhere;
}
.cite a { color: var(--ink-3); text-decoration: underline; text-underline-offset: 2px; }
.cite a:hover { color: var(--brass-2); }

/* Source notes are sentences, not labels. They were set in uppercase mono at
   0.62rem (about 9.9px) with tracking, in --ink-4 at 2.94:1 on ivory: three
   compounding readability faults on strings of 140 characters and more.
   Uppercase strips word shapes, mono strips width variation and tracking pulls
   the letters apart, which is fine for a two word eyebrow and punishing for a
   sentence. Set as small sans text instead. */
.stat .source, .figures .source {
  display: block; margin-top: 0.6rem; padding-top: 0.55rem;
  border-top: 1px solid var(--line);
  font-family: var(--sans); font-size: 0.78rem; letter-spacing: 0;
  color: var(--ink-3); line-height: 1.5;
}
.band--ink .stat .source { border-top-color: var(--green-line); color: var(--on-green-2); }

/* Anything hypothetical is flagged before it is read, not after. */
.illustrative {
  display: flex; align-items: center; gap: 0.6rem;
  font-family: var(--mono); font-size: 0.73rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--info-2);
  background: var(--info-wash);
  border: 1px solid color-mix(in srgb, var(--info) 35%, transparent);
  border-radius: var(--r); padding: 0.6rem 0.9rem; margin-bottom: 1.25rem;
}
.illustrative::before {
  content: ""; width: 7px; height: 7px; flex: none;
  background: var(--info); transform: rotate(45deg);
}

/* The quiet variant. The boxed blue version was the last cool accent left on
   the page and it shouted louder than the demo it labels. The words stay: CAP
   3.7 and this site's own rule both want anything hypothetical labelled BEFORE
   it is read, and the price demo is hypothetical by construction. */
.illustrative--quiet {
  background: none; border: 0; border-radius: 0;
  padding: 0; margin-bottom: 1rem;
  color: var(--ink-3); letter-spacing: 0.14em;
}
.illustrative--quiet::before { background: var(--ink-4); width: 6px; height: 6px; }

.sources {
  border-top: 1px solid var(--line); margin-top: 2.5rem; padding-top: 1.5rem;
}
.sources h2, .sources .h-sm {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-3); font-weight: 500; margin-bottom: 0.9rem;
}
.sources ol { margin: 0; padding-left: 1.2rem; }
.sources li { font-size: 0.82rem; color: var(--ink-3); line-height: 1.55; margin-bottom: 0.5rem; }

/* ==========================================================================
   Author accountability. Google's quality rater guidelines put Trust at the
   centre of E-E-A-T, and a named, contactable, credentialled author with real
   dates is the largest single Trust signal a content page can carry.
   ========================================================================== */

.author {
  display: flex; gap: 1.15rem; align-items: flex-start;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding-block: 1.35rem; margin-block: 2rem;
}
.author-face {
  flex: none; width: 54px; height: 54px; border-radius: 50%;
  background: var(--ink); color: var(--paper);
  display: grid; place-items: center;
  font-family: var(--display); font-size: 1.15rem; letter-spacing: 0.02em;
  /* When it is a photograph rather than the monogram fallback */
  object-fit: cover; overflow: hidden;
}

/* The About page is the one making the authority claim, so the portrait earns
   more room there than it does on an article byline. */
.author--lead .author-face { width: 88px; height: 88px; }
@media (max-width: 520px) { .author--lead .author-face { width: 64px; height: 64px; } }
/* About hero: copy on the left, portrait on the right. Uses the full wrap
   rather than wrap--narrow, because a 340px portrait inside the narrow
   container left the lede running at about 40 characters. The text column is
   capped at the reading measure so the wider container does not stretch it. */
.hero-portrait {
  display: grid; grid-template-columns: minmax(0, 1fr) 32%;
  gap: clamp(2rem, 4vw, 4rem); align-items: start;
}
/* Proportional rather than a fixed 360px: a fixed portrait keeps its width as
   the viewport shrinks and eats the text column, which pushed the lede down to
   about 40 characters at tablet widths. */
.hero-portrait > div > .lede,
.hero-portrait > div > .author { max-width: 31em; }
@media (max-width: 900px) {
  /* Stacked, and the portrait leads: on a phone the face is the fastest way
     to establish who this page is about. */
  .hero-portrait { grid-template-columns: minmax(0, 1fr); }
  .hero-portrait > .portrait { order: -1; max-width: 260px; }
}

.portrait { margin: 0; }
.portrait img {
  width: 100%; height: auto; display: block;
  border-radius: var(--r);
  background: var(--paper-2);
}
.portrait figcaption {
  margin-top: 0.7rem;
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-3);
}

.author-body { min-width: 0; }
.author-name { margin: 0 0 0.3rem; font-weight: 600; font-size: 0.98rem; }
.author-name span {
  font-weight: 400; color: var(--ink-3);
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.12em;
  text-transform: uppercase; display: block; margin-top: 0.22rem;
}
.author-bio { margin: 0 0 0.55rem; font-size: 0.88rem; color: var(--ink-2); line-height: 1.55; max-width: 31em; }
.author-bio a { color: var(--brass-2); }
.author-dates {
  margin: 0; font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-3);
}
.author-dates span { color: var(--line-2); margin-inline: 0.4rem; }

@media (max-width: 520px) { .author { gap: 0.9rem; } .author-face { width: 44px; height: 44px; font-size: 0.95rem; } }

/* How a page's figures were arrived at, stated on the page that uses them. */
.method {
  max-width: 33em;
  background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--r);
  padding: 1.4rem 1.7rem 1.45rem; margin-top: 2.5rem;
}
.method .h-sm {
  font-family: var(--display); font-weight: 500;
  font-size: 1em; line-height: 1.3; letter-spacing: -0.008em; margin: 0 0 0.5rem;
}
.method p { font-size: 0.88em; color: var(--ink-2); }
.method p:last-child { margin-bottom: 0; }

/* ==========================================================================
   Mobile navigation, built on the sheet pattern: an overlay panel that traps
   focus, closes on Escape or an outside click, and locks background scroll.
   The previous dropdown did none of that, so a keyboard user tabbed straight
   out of the open menu into the page behind it.
   ========================================================================== */

.nav-overlay {
  position: fixed; inset: 0; z-index: 55;
  background: rgba(18, 16, 14, 0.5);
  opacity: 0; pointer-events: none;
  transition: opacity .22s ease;
}
.nav-overlay.is-open { opacity: 1; pointer-events: auto; }
body.nav-locked { overflow: hidden; }

@media (min-width: 1001px) { .nav-overlay { display: none; } }

/* ---------- Calculator: the headline pair ---------- */
/* The two figures that answer the question are a direct child of .calc, not
   part of .calc-out, so they can be placed independently at each breakpoint.

   On a phone the inputs alone run 496px inside a 664px viewport, so with the
   figures below them, dragging the price slider pushed the answer off screen
   and the control stopped feeling connected to the result. They sit first and
   stick to the top instead. This cannot be done with sticky alone while they
   sit after the inputs in the document: sticky pins an element on its way
   past, it cannot pull one up from below. */
.calc > .readout-row { grid-column: 2; grid-row: 1; }
.calc .calc-inputs { grid-column: 1; grid-row: 1 / span 2; }
.calc .calc-out { grid-column: 2; grid-row: 2; }
.calc > .readout-row {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 0 1.25rem; align-items: baseline;
  padding: clamp(1.5rem, 3vw, 2.1rem) clamp(1.5rem, 3vw, 2.1rem) 0;
}

@media (max-width: 880px) {
  /* Flex, not grid. A sticky grid item is confined to its own grid area, and
     that row is only as tall as the bar, so it had nowhere to travel and
     scrolled away like a static element. A column flex container gives it the
     whole calculator to stick within. */
  .calc { display: flex; flex-direction: column; }
  .calc > .readout-row,
  .calc .calc-inputs,
  .calc .calc-out { grid-column: auto; grid-row: auto; }
  /* `.calc` carries overflow:hidden for its corner radius, and an ancestor
     with overflow:hidden silently disables position:sticky in a descendant.
     Dropping it here is what makes the bar pin at all; the children keep
     their own corners. */
  .calc { overflow: visible; }
  .calc > .readout-row {
    /* the site header is sticky and 79px tall, so the bar parks under it
       rather than behind it */
    position: sticky; top: 79px; z-index: 3;
    padding: 0.8rem clamp(1.5rem, 3vw, 2.1rem) 0.75rem;
    background: var(--paper); border-bottom: 1px solid var(--line);
    border-radius: var(--r) var(--r) 0 0;
  }
  /* the sub lines are explanation, not result, and doubling the bar's height
     would eat the viewport it exists to preserve */
  .calc > .readout-row .sub { display: none; }
  .calc > .readout-row .k { font-size: 0.58rem; }
  .calc > .readout-row .v { font-size: 1.8rem; line-height: 1.1; }
}


/* ==========================================================================
   Range control. Native input[type=range] keeps keyboard, touch and screen
   reader support for free; this only restyles it to match the system.
   ========================================================================== */

.range-row { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: 0.45rem; }
.range-value {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 0.95rem; font-weight: 500; color: var(--ink);
  background: var(--paper-3); border-radius: var(--r); padding: 0.1rem 0.5rem;
}

input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; background: transparent; margin: 0.35rem 0 0; padding: 0;
  cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 6px; border-radius: 100px; background: var(--paper-3);
  border: 1px solid var(--line);
}
input[type="range"]::-moz-range-track {
  height: 6px; border-radius: 100px; background: var(--paper-3); border: 1px solid var(--line);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 20px; height: 20px; margin-top: -8px;
  border-radius: 50%; background: var(--paper);
  border: 2px solid var(--brass-2);
  box-shadow: 0 1px 3px rgba(18,16,14,.2);
  transition: box-shadow .15s ease;
}
input[type="range"]::-moz-range-thumb {
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--paper); border: 2px solid var(--brass-2);
  box-shadow: 0 1px 3px rgba(18,16,14,.2);
}
input[type="range"]:hover::-webkit-slider-thumb { box-shadow: 0 0 0 6px var(--brass-wash); }
input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px var(--info-wash); outline: 2px solid var(--info); }
input[type="range"]:focus-visible::-moz-range-thumb { outline: 2px solid var(--info); }
input[type="range"]:focus { outline: none; }

.range-scale {
  display: flex; justify-content: space-between;
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.08em;
  /* --ink-4 is a hairline and disabled colour and never text, which these are:
     at 10px on paper-2 it measured 2.74:1. These label the ends of a slider
     and a sighted user reads them to know its span. */
  color: var(--ink-3); margin-top: 0.35rem;
}

/* ==========================================================================
   Sticky result summary. On a phone the calculator inputs fill the screen and
   the outputs sit below the fold, so changing a number appears to do nothing.
   This pins the headline result to the bottom while the inputs are in view.
   ========================================================================== */

.sticky-result {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  background: var(--ink); color: var(--paper);
  border-top: 2px solid var(--brass);
  padding: 0.7rem var(--gut);
  display: none;
  transform: translateY(100%);
  transition: transform .25s cubic-bezier(.2,.7,.3,1);
  box-shadow: 0 -4px 20px rgba(18,16,14,.18);
}
.sticky-result.is-visible { transform: translateY(0); }
.sticky-result .sr-inner { display: flex; align-items: center; justify-content: space-between; gap: 1rem; max-width: var(--wrap); margin-inline: auto; }
.sticky-result .sr-k { font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-4); display: block; }
.sticky-result .sr-v { font-family: var(--display); font-size: 1.5rem; line-height: 1.1; font-variant-numeric: tabular-nums; }
.sticky-result .sr-tag {
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 0.28rem 0.65rem; border-radius: 100px; white-space: nowrap;
}
.sr-tag[data-class="star"] { background: var(--good); color: #04231A; }
.sr-tag[data-class="plowhorse"] { background: var(--brass); color: var(--on-accent); }
.sr-tag[data-class="puzzle"] { background: #7B9BD6; color: #0B1A31; }
.sr-tag[data-class="dog"] { background: #4A4139; color: var(--paper); }

@media (max-width: 880px) { .sticky-result { display: block; } }
@media print { .sticky-result, .nav-overlay { display: none !important; } }

/* Measurement protocol beside the caveats. A numbered list, not three stat
   cards: it is procedure, and it was taking a 498px band to say three short
   lines before the reader had seen any proof. */
.measure-steps { list-style: none; counter-reset: ms; padding: 0; margin: 1.75rem 0 0; }
.measure-steps li {
  counter-increment: ms; position: relative; padding-left: 2.4rem;
  font-size: 0.9rem; line-height: 1.55; color: var(--ink-2);
}
.measure-steps li + li { margin-top: 1rem; }
.measure-steps li::before {
  content: counter(ms); position: absolute; left: 0; top: -0.1rem;
  font-family: var(--mono); font-size: 0.72rem; color: var(--ink-3);
  border: 1px solid var(--line-2); border-radius: var(--r);
  width: 1.6rem; height: 1.6rem; display: grid; place-items: center;
}

/* Disclosure for the detail behind a note, so a page does not open with four
   paragraphs of qualification immediately after its strongest evidence. */
.note-more { margin-top: 1.5rem; border-top: 1px solid var(--line); padding-top: 1rem; }
.note-more > summary {
  cursor: pointer; font-family: var(--sans); font-size: 0.88rem; font-weight: 600;
  color: var(--ink-2); list-style: none; display: flex; align-items: center; gap: 0.5rem;
  min-height: 24px;
}
.note-more > summary::-webkit-details-marker { display: none; }
.note-more > summary::before {
  content: "+"; font-family: var(--mono); font-size: 0.9rem; color: var(--brass-2);
  width: 1rem; text-align: center;
}
.note-more[open] > summary::before { content: "\2212"; }
.note-more > summary:hover { color: var(--ink); }
.note-more > summary:focus-visible { outline: 2px solid var(--edge); outline-offset: 3px; }
.note-more > p { font-size: 0.9rem; margin-top: 1rem; }

/* ---------- Process steps ---------- */
/* Was .rulelist: four rows of full-container prose at 113 characters a line,
   nearly double the 60 to 75 target, with the step number set in --info blue
   at 12px. It also never said who does what, which is the buyer's actual
   question on a services page. Each step now carries its input and output. */
/* The career, as a ruled record rather than a bordered table.

   It was a three column <table> inside .table-scroll, which read as a data
   dump: the years, the role and the operation all at one weight, nothing
   marking which kitchens actually carried a rating. Same idiom as .findings
   and .exchange now, so the three evidence blocks on this site look like one
   another rather than like three different components. */
.cv { list-style: none; margin: 1.75rem 0 0; padding: 0; max-width: none; }
.cv > li { max-width: none; }
.cv-row {
  display: grid; grid-template-columns: 6.5rem minmax(0, 1fr);
  gap: 0 clamp(1rem, 2.5vw, 1.75rem);
  padding: 1.05rem 0; border-top: 1px solid var(--line);
  align-items: baseline;
}
.cv-row:first-child { border-top: 1px solid var(--ink); }
.cv-when {
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.06em;
  color: var(--ink-3); font-variant-numeric: tabular-nums; line-height: 1.45;
}
.cv-when b { display: block; font-weight: 500; color: var(--ink-2); }
.cv-when i { font-style: normal; }
.cv-when i::before { content: "to "; }
.cv-role {
  display: block; font-family: var(--display); font-weight: 500;
  font-size: 1.12rem; line-height: 1.25; color: var(--ink);
}
.cv-place { display: block; font-size: 0.9rem; color: var(--ink-3); margin-top: 0.15rem; }

/* The rating is the one thing in this list a reader can check, so it is the
   one thing marked. Same mark as the hero credential strip, which is what
   ties this page to the homepage. */
.cv-rose-k {
  display: inline-flex; align-items: center; gap: 0.4rem; margin-top: 0.45rem;
  font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--brass-2);
}
.cv-rose {
  width: 15px; height: 15px; flex: none;
  fill: none; stroke: var(--brass-2); stroke-width: 1.15;
  stroke-linecap: round; stroke-linejoin: round;
}

/* The current role. One row differs, so the eye lands on it first. */
.cv-row--now .cv-role { color: var(--green); }
.cv-row--now .cv-when b { color: var(--brass-2); }

.cv-note {
  font-size: 0.85rem; color: var(--ink-3); margin-top: 1.1rem;
  padding-top: 0.9rem; border-top: 1px solid var(--line);
}

@media (max-width: 560px) {
  .cv-row { grid-template-columns: minmax(0, 1fr); gap: 0.3rem; }
  .cv-when { display: flex; gap: 0.35rem; }
  .cv-when b { display: inline; }
}

/* How engagements run, as a schedule rather than a stepper.

   It was numbered circles joined by a vertical connector, which is the most
   recognisable process-timeline component on the web, and it repeated the
   YOU SEND / YOU GET labels eight times down the page while leaving the right
   half of the measure empty. This is a schedule of what changes hands, so it
   is set as one: ruled rows, column headings stated once, full measure used.
   Same idiom as .findings on the homepage. */
.exchange { list-style: none; margin: 2.75rem 0 0; padding: 0; max-width: none; }
/* The site caps list items at a reading measure, which is right for a prose
   list and wrong for a layout grid: it was squeezing these rows to 578px
   inside a 1092px container and wrapping every column to three lines. */
.exchange > li { max-width: none; }
.xhead, .xrow {
  display: grid;
  grid-template-columns: 2.75rem minmax(0, 1.15fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 0 clamp(1.25rem, 2.6vw, 2.25rem);
}
.xhead {
  font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-3);
  padding-bottom: 0.7rem; border-bottom: 1px solid var(--ink);
}
.xrow {
  padding: 1.35rem 0; border-bottom: 1px solid var(--line);
  align-items: baseline;
}
.x-n {
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.1em;
  color: var(--brass-2); font-variant-numeric: tabular-nums;
}
.x-title {
  font-family: var(--display); font-weight: 500; font-size: 1.3rem;
  line-height: 1.15; margin: 0 0 0.35rem;
}
.x-lede { margin: 0; font-size: 0.93rem; line-height: 1.55; color: var(--ink-2); }
.x-send, .x-get { font-size: 0.93rem; line-height: 1.55; color: var(--ink-2); }
/* The column headings carry the labels on desktop, so these are for the
   stacked layout only, where the columns no longer have headings above them. */
.x-k { display: none; }

@media (max-width: 900px) {
  .xhead { display: none; }
  .xrow {
    grid-template-columns: 3.25rem minmax(0, 1fr);
    gap: 0 1.1rem; padding: 1.5rem 0;
  }
  .x-send, .x-get { grid-column: 2; margin-top: 0.9rem; }
  .x-k {
    display: block; font-family: var(--mono); font-size: 0.58rem;
    letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3);
    margin-bottom: 0.25rem;
  }
}

.steps {
  list-style: none; margin: 3rem 0 0; padding: 0;
  counter-reset: none; position: relative;
}
.step {
  display: grid; grid-template-columns: 3.5rem minmax(0, 1fr);
  gap: 0 clamp(1.25rem, 2.5vw, 2rem);
  padding: 0 0 clamp(2.25rem, 4vw, 3rem);
  position: relative;
}
.step:last-child { padding-bottom: 0; }

/* The connector is what makes four items read as one sequence. It stops at
   the last number rather than running past it into empty space. */
.step:not(:last-child)::before {
  content: ""; position: absolute; left: 1.72rem; top: 2.6rem; bottom: 0;
  width: 1px; background: var(--line-2);
}
.step-n {
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.1em;
  color: var(--brass-2); background: var(--paper);
  border: 1px solid var(--line-2); border-radius: 50%;
  width: 3.5rem; height: 3.5rem; display: grid; place-items: center;
  position: relative; z-index: 1;
}
.step-title {
  font-family: var(--display); font-size: clamp(1.25rem, 2vw, 1.55rem);
  line-height: 1.15; margin: 0.55rem 0 0.6rem;
}
.step-lede { margin: 0; max-width: 31em; font-size: 1rem; line-height: 1.6; color: var(--ink-2); }

/* What you hand over, and what comes back. */
.step-meta {
  margin: 1.15rem 0 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.9rem clamp(1.5rem, 3vw, 2.5rem); max-width: 34em;
}
.step-meta > div { border-top: 1px solid var(--line); padding-top: 0.7rem; }
.step-meta dt {
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 0.4rem;
}
.step-meta dd { margin: 0; font-size: 0.875rem; line-height: 1.5; color: var(--ink-2); }

@media (max-width: 620px) {
  .step { grid-template-columns: 2.6rem minmax(0, 1fr); }
  .step-n { width: 2.6rem; height: 2.6rem; font-size: 0.66rem; }
  .step:not(:last-child)::before { left: 1.28rem; top: 2rem; }
  .step-title { margin-top: 0.2rem; }
  .step-meta { grid-template-columns: minmax(0, 1fr); gap: 0.75rem; }
}

/* Reading measure on the two places body text still ran unbounded: a quote
   inside a callout, and a bare <ul> of running prose. Both were unclassed, so
   neither .prose nor .small reached them. */
.callout > p, .callout > ul > li { max-width: 31em; }
.wrap > ul > li, .wrap--narrow > ul > li,
section .wrap > div > ul > li { max-width: 31em; }


/* A CTA block's four children were rendering at 1092 / 542 / 640 / 1092px:
   eyebrow and buttons spanning the container, heading and lede capped well
   inside it, so the group had no shared right edge and read as an accident
   rather than a column. One width for the whole block instead. */
/* Constrain the CHILDREN, not the wrap. .cta-block is the .wrap element, so
   capping it inherited .wrap's auto margins and centred the whole block,
   putting a third left edge on pages that already had two. */
.cta-block > :where(p, h2, h3) { max-width: 32em; }
.cta-block h2 { max-width: 20em; }


/* Containers exempted from the text cap fill the wider wrap, but the running
   text inside them still needs a measure. Sector FAQs use a bare
   <details><p>, so .faq .answer never reached them and they ran at 103
   characters once the wrap widened. */
.faq details > p,
.faq .answer > p,
.faq .answer > ul > li,
.callout > p,
.callout > ul > li,
.method > p,
.note-more > p,
.toc ~ ol > li,
main ol > li,
main ul > li { max-width: 34em; }

/* ---------- How it works ---------- */
/* This sat directly above "Four ways to bring me in", a four column grid of
   four numbered cards. Rendering the process as another four numbered cards
   made the page say the same shape twice in a row. A process is a sequence,
   not a set of parallel options, so it is built differently: three compact
   steps that set the work up, then the fourth given its own block, because
   the heading claims that one is the point and the layout should agree. */
.setup {
  list-style: none; margin: 3rem 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
  counter-reset: setup;
}
.setup-step {
  counter-increment: setup;
  display: flex; flex-direction: column; gap: 0.55rem;
  padding-top: 2.6rem; position: relative; max-width: none;
}
/* The numeral is the step marker. A "Step one" label above it as well was
   saying the same thing twice. */
.setup-step::before {
  content: counter(setup, decimal-leading-zero);
  position: absolute; top: 0; left: 0;
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.14em;
  color: var(--brass-2);
  padding-bottom: 0.7rem; border-bottom: 1px solid var(--line-2);
  width: 100%;
}
.setup-step h3 { font-size: 1.1rem; line-height: 1.22; margin: 0; }
.setup-step > p { font-size: 0.875rem; line-height: 1.55; color: var(--ink-2); margin: 0; max-width: none; }

.flowfig { margin: 0; }
.flowfig svg { width: 100%; height: auto; display: block; }
.flowfig--sm { margin-top: auto; padding-top: 1.2rem; }

/* The fourth step is the argument, so it gets the room the other three share. */
/* The measure step, as a strip.

   It used to be copy on the left and a diagram on the right. The diagram drew
   six empty dashed boxes and came out, which left the second column holding
   nothing and about 400px of dead space under the copy. Splitting the copy
   across both columns condenses the block and fills it: the heading states the
   step, the body argues it. */
.payoff {
  margin-top: clamp(2.5rem, 5vw, 3.75rem);
  border-top: 2px solid var(--ink); padding-top: clamp(1.75rem, 3vw, 2.4rem);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(1.5rem, 4vw, 3.5rem); align-items: start;
}
.payoff-head { display: flex; flex-direction: column; gap: 0.4rem; }
.payoff-body { display: flex; flex-direction: column; gap: 0.85rem; }
.payoff-n {
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--brass-2); margin: 0;
}
.payoff h3 { font-size: clamp(1.5rem, 2.6vw, 2rem); line-height: 1.12; margin: 0; }
.payoff-body > p { font-size: 1rem; line-height: 1.6; color: var(--ink-2); margin: 0; max-width: 31em; }
.payoff-note {
  font-size: 0.875rem; color: var(--ink-3);
  border-left: 2px solid var(--line-2); padding-left: 1rem; margin-top: 0.3rem;
}
/* The illustrative note belongs with the figure it describes. */
.flowfig-note { margin-top: 0.75rem; font-size: 0.8rem; }

@media (max-width: 860px) {
  .setup { grid-template-columns: minmax(0, 1fr); gap: 2.5rem; }
  .payoff { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
  .flowfig--lg { justify-self: start; max-width: 340px; }
}

/* Small text in these two containers had no cap and ran past 78 characters
   once Plex Sans narrowed the measure. Long lines hurt most at small sizes. */
.verdict p, .mx-note p, .mx-note li { max-width: 31em; }
/* .rulelist wraps each item's body in a div, so the generic list cap never
   reached the paragraphs inside it. */
.rulelist li > div > p { max-width: 31em; }

/* ---------- Hero grid ---------- */
/* The buttons used to sit inside the copy column, so when the split stacked on
   a phone the call to action landed above the photograph and the photograph
   was orphaned below it. A hero should close on the ask, not open with it.
   Three explicit grid children instead, placed per breakpoint. */
.hero-grid {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  gap: 0 clamp(2rem, 5vw, 5rem); align-items: start;
}
.hero-copy  { grid-column: 1; grid-row: 1; }
.hero-plate { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
.hero-cta   { grid-column: 1; grid-row: 2; margin-top: 2rem; align-self: start; }
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
  .hero-copy  { grid-row: 1; grid-column: 1; }
  /* Leigh's call: the photograph comes before the ask on a phone, so the hero
     closes on the button rather than opening with it.

     The cost is measured and was accepted. The CTA sat at 501px with the ask
     second and sits at 811px with it third, so on an 844px viewport its top
     is barely on screen, its bottom is not, and browser chrome takes another
     ~100px on top of that. Do not "restore" this to ask-then-photo
     on the grounds of the fold; that trade was made knowingly. */
  .hero-plate { grid-row: 2; grid-column: 1; margin-top: 0.5rem; }
  .hero-cta   { grid-row: 3; grid-column: 1; margin-top: 0.5rem; }
}

/* ---------- Hero plate ---------- */
/* The hero used to carry the matrix. That is the method, not the outcome, and
   an abstract chart made the site read as an analysis tool rather than a chef
   led consultancy. The matrix still runs in full on /menu-engineering/ and as
   a thumbnail in step two, so nothing is lost by handing the hero to the food.
   Caption sits below the image, not overlaid: an overlay needs a gradient to
   stay legible and flat colour is the rule here. */
.hero-plate { margin: 0; display: flex; flex-direction: column; }
.hero-plate img {
  width: 100%; height: auto; display: block;
  aspect-ratio: 4 / 5; object-fit: cover;
  border-radius: var(--r); background: var(--paper-2);
}
.hero-plate figcaption {
  margin-top: 0.85rem; font-size: 0.82rem; line-height: 1.5; color: var(--ink-3);
  max-width: 34em;
}
@media (max-width: 900px) {
  .hero-plate { max-width: 460px; }
  .hero-plate img { aspect-ratio: 3 / 2; }
}

/* ---------- Statement hero ---------- */
/* The three lines are the argument: two things held constant, one thing moved.
   The mockup had the payoff line in --ink-3, which de-emphasised the only line
   that matters. Inverted: the constants recede, the change carries full ink. */
/* The h1 names the thing the site is about; the statement underneath carries
   the argument. Small name over big line is the hero pattern that works when
   the name is a category term rather than a slogan, and it puts the exact
   phrase people search into the one heading that should hold it.

   The statement is no longer an h1, so it can no longer inherit the h1 type
   ramp and has to declare the whole thing. Keep these numbers identical to
   the h1 rule or the hero silently shrinks. */
.hero-title {
  font-size: clamp(1.25rem, 2.1vw, 1.55rem);
  line-height: 1.2; letter-spacing: -0.008em;
  color: var(--ink-2); margin: 0 0 0.7rem;
}
.statement {
  font-family: var(--display); font-weight: 500;
  font-size: clamp(2.4rem, 5.3vw, 4rem);
  line-height: 1.04; letter-spacing: -0.022em;
  text-wrap: balance;
  max-width: none; margin-bottom: 0;
}
.statement span { display: block; }
.statement .held { color: var(--ink-3); }
.statement .moved { color: var(--ink); }
.hero .statement + .lede { margin-top: 1.6rem; }

/* A statement hero with nothing beside it leaves half the viewport empty, which
   is the "large empty space with no purpose" the brand rules forbid. The space
   is paid for with the three figures the site can actually evidence.
   Named .proofrow, not .hp: that class is already the contact form's spam
   honeypot, absolutely positioned off screen at 1px, and the collision pushed
   every figure out of view while still reporting as visible. */
.hero-proof { display: flex; flex-direction: column; gap: 1.6rem; }
.proofrow { display: flex; flex-direction: column; gap: 0.4rem;
      border-top: 1px solid var(--line-2); padding-top: 0.9rem; }
.proofrow:first-child { border-top: 2px solid var(--ink); }
.proofrow .n {
  font-family: var(--display); font-weight: 500; font-size: clamp(1.9rem, 3vw, 2.4rem);
  line-height: 1; font-variant-numeric: tabular-nums; color: var(--ink);
  display: flex; align-items: baseline; gap: 0.26rem;
}
.proofrow:first-child .n { color: var(--good-2); }
.proofrow .n .u { font-family: var(--sans); font-size: 0.36em; font-weight: 600; color: var(--ink-3); }
.proofrow .l { font-size: 0.83rem; line-height: 1.5; color: var(--ink-3); max-width: 32em; }
.hero-proof-note { margin: 0.4rem 0 0; font-size: 0.76rem; line-height: 1.5; color: var(--ink-3); }

@media (max-width: 900px) {
  .hero-proof { gap: 1.25rem; }
  .proofrow .l { max-width: none; }
}

/* ---------- Phone: density ---------- */
/* The homepage ran 17.2 phone screens. Everything that sits 3 or 4 across on
   desktop stacks to one column, so height multiplies: the plate band alone was
   1,608px and the four steps 1,225px, before 1,144px of section padding across
   eleven sections. None of this shows at desktop width. */
@media (max-width: 640px) {
  section { padding-block: 2.6rem; }
  .section--tight { padding-block: 2rem; }

  /* Three 4:5 photographs stacked is nearly two screens of scrolling for one
     idea. A swipe strip shows them as one object and costs about a third of
     the height. The page body still never scrolls sideways. */
  .plates {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 72%;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    gap: 0.9rem;
    padding-bottom: 0.9rem;
    scrollbar-width: thin;
    overscroll-behavior-x: contain;
  }
  .plate { scroll-snap-align: start; }
  .plate figcaption { padding-top: 0.7rem; }

  /* The three setup diagrams restate what their own paragraph already says: a
     menu with prices, a scatter, four labelled actions. On a phone they cost
     about 700px to repeat the text. The fourth is kept, because the empty
     measurement grid shows something the words do not. */
  .flowfig--sm { display: none; }
  .flowfig--lg { max-width: 300px; }
  .setup { gap: 1.9rem; }
  .setup-step { padding-top: 2.2rem; }

  /* Source lines are required by CAP rule 3.7 and stay, but they do not need
     to be the same size as the claim they qualify. */
  .stat .source, .figures .source { font-size: 0.72rem; line-height: 1.45; }
  .figures { gap: 1.6rem; }
}

/* Guides index. Three full width cards with a left stripe on one of them used
   half of each card and marked a "featured" guide that was also last in the
   list, under a heading that called all three featured. It is a ruled index
   now, the same idiom as the other record blocks: topic stated once at the
   left, the title and standfirst in the measure, the action at the right edge.
   The amber stripe is gone; amber is for actions and nothing else. */
.guide-list { list-style: none; margin: 1.5rem 0 0; padding: 0; max-width: none; border-bottom: 1px solid var(--line); }
.wrap > .guide-list > li { max-width: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.guide-row {
  display: grid; grid-template-columns: minmax(0, 0.7fr) minmax(0, 2fr) auto;
  gap: clamp(1rem, 3vw, 3rem); align-items: start;
  padding: clamp(1.6rem, 3vw, 2.4rem) 0; text-decoration: none; color: var(--ink);
}
.gr-k {
  font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-3);
  padding-top: 0.55rem;
}
.gr-body { display: block; }
.gr-t {
  display: block; font-family: var(--display); font-weight: 500;
  font-size: clamp(1.35rem, 2.4vw, 1.75rem); line-height: 1.2;
  letter-spacing: -0.012em; text-wrap: balance; max-width: 24em;
  text-decoration: underline; text-decoration-color: transparent;
  text-decoration-thickness: 2px; text-underline-offset: 0.2em;
  transition: text-decoration-color .15s ease;
}
.gr-d { display: block; margin-top: 0.7rem; color: var(--ink-3); line-height: 1.6; max-width: 34em; }
.gr-go { align-self: center; color: var(--ink); white-space: nowrap; }
.guide-row:hover .gr-t, .guide-row:focus-visible .gr-t { text-decoration-color: var(--brass-2); }
@media (max-width: 820px) {
  .guide-row { grid-template-columns: minmax(0, 1fr); gap: 0.5rem; }
  .gr-k { padding-top: 0; }
  .gr-go { align-self: start; margin-top: 0.4rem; }
}
.gr-go::after { color: var(--brass-2); }

/* Guides: where to start, and per guide metadata. The start list answers the
   question a visitor arrives with, a problem rather than a topic, and sends
   them to one guide. It is a ruled list like the index below it, with the
   problem at the left and the guide at the right edge. */
.start-list { list-style: none; margin: 1.5rem 0 0; padding: 0; max-width: none; border-bottom: 1px solid var(--line); }
.wrap > .start-list > li {
  max-width: none; margin: 0; padding: 1.05rem 0; border-top: 1px solid var(--line);
  display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 1rem 2rem; align-items: baseline;
}
.sl-q { font-family: var(--display); font-weight: 500; font-size: clamp(1.05rem, 1.8vw, 1.3rem); line-height: 1.3; color: var(--ink); }
.sl-a { color: var(--ink); }
.sl-a::after { color: var(--brass-2); }
.gr-m {
  display: block; margin-top: 0.6rem; font-family: var(--sans); font-size: 0.8rem;
  letter-spacing: 0; text-transform: none; font-weight: 400; line-height: 1.5; color: var(--ink-3);
}
@media (max-width: 820px) {
  .wrap > .start-list > li { grid-template-columns: minmax(0, 1fr); gap: 0.4rem; }
}


/* Sample menu profitability analysis. Built on existing parts: the evidence row,
   the table-scroll wrapper and the homepage quadrant grid. Only what a financial
   table and a scatter chart need is new, and it is flat colour throughout.
   Strong and weak performers use --good-2 and --brass-2, the two text safe
   signal colours, and never red, so the table reads as a record, not an alert. */
.mp-note { max-width: 62em; color: var(--ink-3); font-size: 0.95rem; line-height: 1.6; margin: 0.75rem 0 1.5rem; }
.mp-table th.n, .mp-table td.n { text-align: right; }
.mp-table thead th { font-size: 0.7rem; white-space: normal; vertical-align: bottom; }
.mp-table tbody th, .mp-table tfoot th { font-weight: 500; white-space: nowrap; }
.mp-table td.hi { color: var(--good-2); font-weight: 600; }
.mp-table td.warn { color: var(--brass-2); font-weight: 600; }
.mp-table td.top { font-weight: 700; color: var(--ink); background: var(--paper-2); }
.mp-table tfoot td, .mp-table tfoot th { border-top: 1.5px solid var(--ink-3); border-bottom: 0; font-weight: 600; background: var(--white); }
.mp-table--small { min-width: 0; }
.mp-table--small tbody th { white-space: normal; }
.mp-table--levers td:last-child { max-width: 24em; }
.mp-table--levers { min-width: 760px; }
.mono-k { font-family: var(--mono); font-weight: 400; font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); }
.mp-split { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: clamp(1.5rem, 4vw, 3rem); align-items: start; margin: 1.5rem 0 2.5rem; }
.mp-figure { margin: 1.5rem 0 0; background: var(--white); border: 1px solid var(--line); border-radius: var(--r); padding: 1rem 1.25rem; }
.mp-chart { display: block; width: 100%; height: auto; }
.mp-plot { fill: none; stroke: var(--line-2); stroke-width: 1; }
.mp-grid { stroke: var(--line); stroke-width: 1; }
.mp-thr { stroke: var(--ink-3); stroke-width: 1.2; stroke-dasharray: 6 6; }
.mp-tick, .mp-axis-t { font-family: var(--mono); font-size: 12px; fill: var(--ink-3); }
.mp-axis-t { letter-spacing: 0.12em; text-transform: uppercase; }
.mp-quad { font-family: var(--mono); font-size: 12px; letter-spacing: 0.14em; fill: var(--ink-3); }
.mp-lbl { font-family: var(--sans); font-size: 13.5px; fill: var(--ink); }
.mp-pt--star { fill: var(--green); }
.mp-pt--plow { fill: var(--brass-2); }
.mp-pt--puzzle { fill: var(--white); stroke: var(--green); stroke-width: 2.5; }
.mp-pt--dog { fill: var(--ink-3); }
.mp-quad-matrix { margin-top: 2.5rem; }
.mp-quad-matrix .quadrant { min-height: 0; }
.mp-quad-matrix .quadrant .q { min-height: 9rem; }
.q-dishes { font-family: var(--display); font-size: 1.02rem; line-height: 1.45; font-weight: 500; color: var(--ink); margin: 0.6rem 0 0.7rem; }
@media (max-width: 900px) { .mp-figure { padding: 0.6rem; } }

/* A photograph inside a long guide. Guides were text only, so this is the first
   figure that is a picture rather than a table. It keeps the photograph's own
   ratio (the plate grid forces 4:5 and would crop a wide board), takes the 4px
   radius, and its caption is quiet and sits under the image, not over it. */
.photo-fig { margin: 2rem 0; }
.photo-fig img { display: block; width: 100%; height: auto; border-radius: var(--r); background: var(--paper-2); }
.photo-fig figcaption { margin-top: 0.7rem; font-size: 0.85rem; line-height: 1.5; color: var(--ink-3); max-width: 38em; }

/* ---------- Menu section tiles (homepage) ---------- */
.section--cats { padding: clamp(3rem, 6vw, 4.5rem) 0; }
.cat-tiles {
  list-style: none; padding: 0; margin: 2.25rem 0 0; max-width: none;
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(0.9rem, 1.6vw, 1.4rem);
}
.wrap > .cat-tiles > li { max-width: none; margin: 0; padding: 0; }
.cat-tile { display: block; color: var(--ink); text-decoration: none; }
.cat-img { display: block; overflow: hidden; border-radius: var(--r); background: var(--paper-2); }
.cat-img img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }
.cat-t {
  margin: 0.9rem 0 0; font-family: var(--display); font-weight: 500;
  font-size: 1.05rem; line-height: 1.25; letter-spacing: -0.008em; text-wrap: balance;
  text-decoration: underline; text-decoration-color: transparent;
  text-decoration-thickness: 2px; text-underline-offset: 0.2em;
}
.cat-d { display: block; margin-top: 0.4rem; font-size: 0.85rem; line-height: 1.5; color: var(--ink-3); }
.cat-tile:hover .cat-t, .cat-tile:focus-visible .cat-t { text-decoration-color: var(--brass-2); }
.cat-tile:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }
@media (prefers-reduced-motion: no-preference) {
  .cat-img img { transition: transform .5s ease; }
  .cat-tile:hover .cat-img img, .cat-tile:focus-visible .cat-img img { transform: scale(1.035); }
  .cat-t { transition: text-decoration-color .15s ease; }
}
@media (max-width: 1000px) { .cat-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 640px) {
  /* A scrolling row, with the next tile showing at the edge so it reads as one. */
  .cat-tiles {
    display: flex; gap: 0.9rem; overflow-x: auto; scroll-snap-type: x mandatory;
    margin-right: calc(-1 * var(--gut)); padding-right: var(--gut);
    padding-bottom: 0.5rem; -webkit-overflow-scrolling: touch;
  }
  .wrap > .cat-tiles > li { flex: 0 0 62vw; scroll-snap-align: start; }
}

/* ---------- Homepage: where is your menu leaking margin ---------- */
.leaks-head { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); gap: clamp(1.5rem, 4vw, 4rem); align-items: center; }
.leaks-photo { display: block; width: 100%; height: auto; aspect-ratio: 6 / 5; object-fit: cover; border-radius: var(--r); background: var(--paper-2); }
.leak-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(0.9rem, 1.6vw, 1.4rem); margin-top: clamp(2rem, 4vw, 3rem); }
.leak-card {
  position: relative; display: flex; flex-direction: column;
  background: var(--white); border: 1px solid var(--line-2); border-radius: var(--r);
  padding: clamp(1.4rem, 2vw, 1.9rem);
}
.leak-top { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 1.1rem; }
.leak-no { font-family: var(--display); font-size: 1.35rem; line-height: 1; letter-spacing: -0.01em; color: var(--brass-2); }
.leak-ico { display: block; color: var(--green); }
.leak-ico svg { display: block; width: 48px; height: 48px; }
.leak-ico .f { fill: color-mix(in srgb, var(--green) 12%, transparent); }
.leak-t { margin: 0 0 0.6rem; font-family: var(--display); font-weight: 500; font-size: 1.4rem; line-height: 1.2; letter-spacing: -0.012em; color: var(--ink); }
.leak-card .small { margin: 0; flex: 1; }
.leak-go { margin-top: 1.4rem; align-self: flex-start; font-weight: 600; font-size: 0.9rem; color: var(--ink); text-decoration: none; }
.leak-go::after { content: ""; position: absolute; inset: 0; border-radius: var(--r); }   /* whole card is the link */
.leak-arr { display: inline-block; margin-left: 0.4rem; color: var(--brass-2); }
.leak-card:hover, .leak-card:focus-within { border-color: var(--green); background: color-mix(in srgb, var(--green) 3%, var(--white)); }
.leak-go:focus-visible { outline: none; }
.leak-go:focus-visible::after { outline: 2px solid var(--ink); outline-offset: 3px; }
.leak-card:hover .leak-go, .leak-go:focus-visible { text-decoration: underline; text-decoration-color: var(--brass-2); text-decoration-thickness: 2px; text-underline-offset: 0.25em; }
@media (prefers-reduced-motion: no-preference) {
  .leak-card { transition: border-color .2s ease, background-color .2s ease, transform .25s ease; }
  .leak-card:hover { transform: translateY(-3px); }
  .leak-arr { transition: transform .2s ease; }
  .leak-card:hover .leak-arr, .leak-go:focus-visible .leak-arr { transform: translateX(4px); }
}
.leak-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem 2rem; flex-wrap: wrap;
  margin-top: clamp(1.25rem, 2.5vw, 1.75rem); padding: clamp(1.2rem, 2.4vw, 1.6rem) clamp(1.3rem, 3vw, 2.2rem);
  background: color-mix(in srgb, var(--green) 6%, var(--white)); border: 1px solid var(--line-2);
  border-left: 3px solid var(--green); border-radius: var(--r);
}
.leak-banner p { margin: 0; max-width: 34em; font-family: var(--display); font-size: clamp(1.05rem, 1.6vw, 1.25rem); line-height: 1.4; color: var(--ink); }
@media (max-width: 1100px) { .leak-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 800px) { .leaks-head { grid-template-columns: minmax(0, 1fr); } .leaks-photo { aspect-ratio: 3 / 2; } }
@media (max-width: 640px) { .leak-grid { grid-template-columns: minmax(0, 1fr); } .leak-banner .btn { width: 100%; text-align: center; } }

/* Homepage kitchen strip: the four labels are links to the sector pages. */
.kitchen-links h3 a { color: inherit; text-decoration: underline; text-decoration-color: var(--brass-2); text-decoration-thickness: 2px; text-underline-offset: 0.22em; }
.kitchen-links h3 a:hover, .kitchen-links h3 a:focus-visible { text-decoration-color: var(--ink); }

/* Menu profitability section pages: headline with a lead photograph. */
.pp-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 400px); gap: clamp(1.5rem, 4vw, 4rem); align-items: center; }
.pp-photo { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; border-radius: var(--r); background: var(--paper-2); }
@media (max-width: 800px) { .pp-head { grid-template-columns: minmax(0, 1fr); } .pp-photo { aspect-ratio: 3 / 2; } }
@media (prefers-reduced-motion: no-preference) {
  .leak-ico { transition: transform .25s ease; }
  .leak-card:hover .leak-ico { transform: translateY(-2px); }
}

/* Homepage plate band: what each dish is tested on, as plain labels (no figures exist to show). */
.plate-tests { display: block; margin-top: 0.85rem; padding-top: 0.7rem; border-top: 1px solid var(--line-2); font-size: 0.8rem; line-height: 1.45; color: var(--ink); }
.plate-tests span { display: block; margin-bottom: 0.15rem; font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); }
.plates--inline .plate-tests { display: none; }
.plate:has(.plate-tests) { display: flex; flex-direction: column; }
.plate:has(.plate-tests) figcaption { flex: 1; display: flex; flex-direction: column; }
.plate:has(.plate-tests) .plate-note { margin-bottom: 0.9rem; }
.plate:has(.plate-tests) .plate-tests { margin-top: auto; }

/* Section hero: white ground, larger lead photograph. */
.pp-hero { padding-block: clamp(2.75rem, 6vw, 5rem); }
@media (max-width: 800px) { .pp-hero .pp-photo { aspect-ratio: 5 / 4; } }

/* Leaks heading without a photograph: one column, intro held to a reading measure. */
.leaks-head--text { display: block; }
.leaks-head--text .lede { max-width: 34em; }

/* Five plates: three over two, the second row centred, so no empty cell. */
.plates--five { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.plates--five .plate { grid-column: span 2; }
.plates--five .plate:nth-child(4) { grid-column: 2 / span 2; }
.plates--five .plate:nth-child(5) { grid-column: 4 / span 2; }
@media (max-width: 640px) {
  .plates--five { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .plates--five .plate, .plates--five .plate:nth-child(4), .plates--five .plate:nth-child(5) { grid-column: auto; }
}

/* ---------- Guides index: grouped, one list, the problem stated on each guide ---------- */
.gi-count { margin-top: 1rem; font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); }
.gi-group {
  display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 2fr);
  gap: clamp(1.25rem, 4vw, 4rem); padding: clamp(2rem, 4vw, 3rem) 0; border-top: 1px solid var(--line);
}
.gi-group:last-child { border-bottom: 1px solid var(--line); }
.gi-head h2 { font-size: clamp(1.4rem, 2.4vw, 1.8rem); margin: 0; }
.gi-head .small { margin-top: 0.6rem; max-width: 22em; color: var(--ink-3); }
.gi-list, .wrap .gi-list > li { list-style: none; margin: 0; padding: 0; max-width: none; }
.gi-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1.5rem, 3vw, 2.5rem); }
.gi-start { display: block; margin-bottom: 0.45rem; font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brass-2); }
.gi-t { margin: 0; font-family: var(--display); font-weight: 500; font-size: clamp(1.15rem, 1.7vw, 1.35rem); line-height: 1.25; letter-spacing: -0.01em; text-wrap: balance; }
.gi-t a { color: var(--ink); text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: 2px; text-underline-offset: 0.18em; transition: text-decoration-color .15s ease; }
.gi-t a:hover, .gi-t a:focus-visible { text-decoration-color: var(--brass-2); }
.gi-when { margin: 0.7rem 0 0; font-size: 0.9rem; line-height: 1.5; color: var(--ink); }
.gi-when span { font-weight: 600; }
.gi-d { margin: 0.45rem 0 0; font-size: 0.875rem; line-height: 1.55; color: var(--ink-3); }
.gi-meta { margin: 0.7rem 0 0; font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); }
.gi-also { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1.25rem, 3vw, 2.5rem); margin-top: 1.75rem; }
.gi-links, .wrap .gi-links > li { list-style: none; margin: 0; padding: 0; max-width: none; }
.gi-links li { padding: 0.45rem 0; border-top: 1px solid var(--line); font-size: 0.92rem; }
.gi-links a { color: var(--ink); text-decoration-color: var(--brass-2); }
.gi-next { margin-top: 2rem; max-width: 46em; color: var(--ink-3); }
@media (max-width: 900px) { .gi-group { grid-template-columns: minmax(0, 1fr); } .gi-also { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 640px) { .gi-list { grid-template-columns: minmax(0, 1fr); } }

/* ---------- Results case studies: one panel each, results row, then ruled story rows ---------- */
.cs { background: var(--white); border: 1px solid var(--line); border-radius: var(--r); padding: clamp(1.5rem, 3.5vw, 3rem); }
.cs + .cs { margin-top: clamp(2.5rem, 5vw, 4rem); }
.cs-head { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(1.5rem, 4vw, 3.5rem); align-items: start; }
.cs--aside .cs-head { grid-template-columns: minmax(0, 1fr) minmax(0, 280px); }
.cs-num { margin: 0 0 0.9rem; font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brass-2); }
.cs-venue { margin: 0; font-family: var(--display); font-size: clamp(1.3rem, 2.2vw, 1.6rem); line-height: 1.1; color: var(--ink); }
.cs .venue-logo { display: block; width: 170px; height: auto; }
.cs-tags { margin: 0.6rem 0 0; font-family: var(--mono); font-size: 0.64rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); }
.cs-title { margin: 1.5rem 0 0; font-size: clamp(1.6rem, 3vw, 2.25rem); line-height: 1.15; max-width: 22ch; text-wrap: balance; }
.cs-intro { margin: 1rem 0 0; max-width: 36em; color: var(--ink-2); line-height: 1.6; }
.cs-photo { margin: 0; }
.cs-photo img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; border-radius: var(--r); background: var(--paper-2); }
.cs-photo figcaption { margin-top: 0.6rem; font-size: 0.8rem; color: var(--ink-3); }
.cs-results { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin: clamp(1.75rem, 3.5vw, 2.5rem) 0 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.cs-results > div { padding: 1.25rem clamp(0.75rem, 2vw, 1.5rem) 1.25rem 0; }
.cs-results > div + div { padding-left: clamp(0.75rem, 2vw, 1.5rem); border-left: 1px solid var(--line); }
.cs-results dt { font-family: var(--mono); font-size: 0.64rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); }
.cs-results dd { margin: 0; }
.cs-fig { margin-top: 0.5rem !important; font-family: var(--display); font-weight: 500; font-size: clamp(1.8rem, 3.4vw, 2.6rem); line-height: 1; color: var(--good); letter-spacing: -0.015em; }
.cs-ba { margin-top: 0.55rem !important; font-family: var(--mono); font-size: 0.78rem; color: var(--ink); }
.cs-ba .was { color: var(--ink-3); text-decoration: line-through; }
.cs-quote { margin: clamp(1.75rem, 3.5vw, 2.5rem) 0 0; padding: 0 0 0 clamp(1rem, 2.5vw, 1.75rem); border-left: 3px solid var(--good); max-width: 40em; }
.cs-quote p { margin: 0; font-family: var(--display); font-size: clamp(1.15rem, 2vw, 1.4rem); line-height: 1.45; color: var(--ink); }
.cs-quote footer { margin-top: 0.75rem; font-size: 0.85rem; color: var(--ink-3); }
.cs-story { margin-top: clamp(1.75rem, 3.5vw, 2.5rem); }
.cs-row { display: grid; grid-template-columns: minmax(0, 12em) minmax(0, 1fr); gap: clamp(1rem, 3vw, 2.5rem); padding: 1.25rem 0; border-top: 1px solid var(--line); }
.cs-row h4 { margin: 0; font-family: var(--display); font-weight: 500; font-size: 1.1rem; line-height: 1.3; }
.cs-row p, .cs-row li { margin: 0; max-width: 40em; font-size: 0.95rem; line-height: 1.6; color: var(--ink-2); }
.cs-row ul { margin: 0; padding-left: 1.1rem; }
.cs-row li + li { margin-top: 0.5rem; }
.wrap .cs-row ul > li { max-width: 40em; }
@media (max-width: 820px) {
  .cs--aside .cs-head { grid-template-columns: minmax(0, 1fr); }
  .cs-glance { max-width: 32em; }
  .cs-photo { max-width: 320px; }
  .cs-row { grid-template-columns: minmax(0, 1fr); gap: 0.5rem; }
}
@media (max-width: 560px) {
  .cs-results { grid-template-columns: minmax(0, 1fr); }
  .cs-results > div + div { padding-left: 0; border-left: 0; border-top: 1px solid var(--line); }
}
.cs-results + .cs-story .cs-row:first-child { border-top: 0; padding-top: 0.5rem; }
.cs-glance { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r); padding: 1.25rem 1.35rem; }
.cs-glance-k { margin: 0 0 0.75rem; font-family: var(--mono); font-size: 0.64rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brass-2); }
.cs-glance dl { margin: 0; }
.cs-glance dl > div { padding: 0.7rem 0; border-top: 1px solid var(--line); }
.cs-glance dt { font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); }
.cs-glance dd { margin: 0.25rem 0 0; font-size: 0.92rem; line-height: 1.45; color: var(--ink); }

/* ---------- Menu profitability pages: shared category hero ---------- */
.pp-hero { padding-block: clamp(2.25rem, 5vw, 4rem) clamp(2rem, 4vw, 3rem); }
.ph-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(1.75rem, 4vw, 3.5rem); align-items: center; }
.ph-copy h1 { max-width: none; font-size: clamp(2.3rem, 4.6vw, 3.6rem); line-height: 1.04; }
.ph-sub { margin: 1.5rem 0 0; font-family: var(--display); font-weight: 500; font-size: clamp(1.35rem, 2.4vw, 1.75rem); line-height: 1.25; color: var(--ink); letter-spacing: -0.01em; }
.ph-sub::after { content: ""; display: block; width: 3.2rem; height: 2px; margin-top: 0.8rem; background: var(--brass); }
.ph-intro { margin: 1.25rem 0 0; max-width: 33em; font-size: 1.02rem; line-height: 1.6; color: var(--ink-2); }
.ph-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 1.1rem; margin-top: 1.75rem; }
.ph-link { font-size: 0.92rem; color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--line-2); }
.ph-link:hover, .ph-link:focus-visible { border-color: var(--brass-2); }
.ph-photo { display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; border-radius: var(--r); background: var(--paper-2); }
.ph-strip { list-style: none; margin: clamp(1.75rem, 3.5vw, 2.75rem) 0 0; padding: 0; max-width: none; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); background: var(--white); border: 1px solid var(--line); border-radius: var(--r); }
.wrap > .ph-strip > li { max-width: none; margin: 0; }
.ph-item { display: flex; gap: 1rem; align-items: flex-start; padding: 1.35rem clamp(1rem, 2vw, 1.6rem); }
.ph-item + .ph-item { border-left: 1px solid var(--line); }
.ph-ico { flex: none; color: var(--brass-2); }
.ph-pt { margin: 0; font-family: var(--display); font-weight: 500; font-size: 1.08rem; line-height: 1.25; color: var(--ink); }
.ph-pd { margin: 0.3rem 0 0; font-size: 0.86rem; line-height: 1.5; color: var(--ink-3); }
@media (max-width: 860px) {
  .ph-grid { grid-template-columns: minmax(0, 1fr); }
  .ph-copy h1 { max-width: none; }
  .ph-photo { order: -0; }
  .ph-strip { grid-template-columns: minmax(0, 1fr); }
  .ph-item + .ph-item { border-left: 0; border-top: 1px solid var(--line); }
}
@media (max-width: 560px) { .ph-actions .btn { width: 100%; text-align: center; } }

.pp-gallery-cta { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.75rem; margin: 0.5rem 0 2.5rem; }
@media (max-width: 560px) { .pp-gallery-cta .btn { width: 100%; text-align: center; } }

/* Menu profitability pages: calmer vertical rhythm from the hero down. */
.pp-hero { padding-bottom: clamp(1.75rem, 3vw, 2.5rem); }
.pp-hero + .section--tight { padding-top: clamp(1.75rem, 3vw, 2.5rem); }
.pp-prose h2 { margin-top: 1.9em; }
.pp-prose h2:first-child { margin-top: 0; }
.pp-prose .pp-gallery-cta { margin: 0.25rem 0 0; }
.pp-prose .callout + h2, .pp-prose .method { margin-top: 2.5em; }

/* One plate on a section page: photo and caption in a row, not a lone card in a grid */
.plates--solo { grid-template-columns: 1fr; }
.plates--solo .plate { display: grid; grid-template-columns: minmax(0, 18rem) minmax(0, 1fr); gap: 1.5rem 2rem; align-items: center; }
.plates--solo .plate-note { display: block; margin: 0.5rem 0 0; font-size: 0.95em; color: var(--ink-3); }
@media (max-width: 640px) { .plates--solo .plate { grid-template-columns: 1fr; } }
.photo-fig--narrow { max-width: 22rem; }





/* ==========================================================================
   Homepage "what a menu audit examines". An editorial two column spread: the
   argument on the left, four numbered ruled entries on the right, set like
   the contents of a financial report. No cards, no icons, no figures.
   ========================================================================== */
.scope-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(2rem, 6vw, 5.5rem); align-items: start; }
.scope-intro .lede { margin-top: 1.25rem; max-width: 24em; }
.scope-cta { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.75rem; margin-top: 2rem; }
.scope-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--ink); }
.scope-item { display: grid; grid-template-columns: 3.25rem minmax(0, 1fr); column-gap: 1rem; padding: clamp(1.4rem, 2.5vw, 2rem) 0; border-bottom: 1px solid var(--line-2); }
.scope-n { grid-row: 1 / span 2; padding-top: 0.45rem; font-family: var(--mono); font-size: 0.8rem; letter-spacing: 0.1em; color: var(--brass-2); }
.scope-t { margin: 0; font-family: var(--display); font-weight: 500; font-size: clamp(1.5rem, 2.6vw, 2rem); line-height: 1.15; letter-spacing: -0.01em; color: var(--ink); }
.scope-item p { margin: 0.6rem 0 0; max-width: 32em; font-size: 1.02rem; line-height: 1.6; color: var(--ink-2); }
@media (max-width: 900px) { .scope-grid { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 520px) { .scope-item { grid-template-columns: 2.5rem minmax(0, 1fr); column-gap: 0.75rem; } }


/* ==========================================================================
   Results band refinement. Labels were 9 to 10px; they are now legible. The
   arrow is centred on the figures rather than on the card, so it never drifts
   toward the Before and After captions, and every card ends on its delta at
   the same height whatever the label wraps to.
   ========================================================================== */
.ba-card { --ba-fs: clamp(2rem, 3.4vw, 2.5rem); }
.ba-k { font-size: 0.72rem; letter-spacing: 0.14em; min-height: 2.6em; line-height: 1.3; }
.ba-move { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: start; gap: clamp(0.6rem, 1.6vw, 1rem); }
.ba-v { font-size: var(--ba-fs); white-space: nowrap; }
.ba-t { font-size: 0.68rem; }
.ba-arrow { display: flex; align-items: center; justify-content: center; height: var(--ba-fs); padding: 0; font-size: 1.25rem; }
.ba-d { margin-top: auto; }
.ba-move { margin-bottom: 1.1rem; }
.ba-dv { font-size: clamp(1.5rem, 2.6vw, 1.9rem); white-space: nowrap; }
.ba-dk { font-size: 0.68rem; }
.ba-link { margin-top: 1.25rem !important; }
.ba-link .arrow-link { display: inline-flex; align-items: center; min-height: 44px; font-size: 1rem; font-weight: 600; }

.ba-foot { margin-top: 2rem; padding: 1.25rem 0 0 1.25rem; border-top: 1px solid var(--green-line); border-left: 2px solid var(--brass); }
.ba-foot-t { margin: 0; font-family: var(--display); font-weight: 500; font-size: clamp(1.2rem, 2.2vw, 1.5rem); line-height: 1.3; color: var(--on-green); max-width: 34em; }
.ba-foot-p { margin: 0.75rem 0 0; font-size: 0.98rem; line-height: 1.6; color: var(--on-green-2); max-width: 46em; }
@media (max-width: 900px) {
  .ba-k { min-height: 0; }
}
@media (max-width: 520px) {
  .ba-card { padding: 1.1rem; }
  .ba-foot { padding-left: 1rem; margin-top: 1.5rem; }
}


/* ==========================================================================
   Plate band, rewritten as a story: the opening, five numbered tests, one
   editorial statement, then three dishes each told as a short commercial
   argument. Numerals take the text safe amber, rules are hairlines, and there
   are no cards, chips or icons.
   ========================================================================== */
.craft-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2rem 3rem; align-items: end; margin-bottom: clamp(2.25rem, 5vw, 3.5rem); }
.craft-lede { margin: 1.1rem 0 0; max-width: 34em; font-size: 1.12rem; line-height: 1.55; color: var(--ink-2); }
.craft-line { margin: 0.8rem 0 0; font-family: var(--display); font-size: 1.2rem; line-height: 1.35; color: var(--ink); max-width: 30em; }
.craft-more { margin: 0; }
.craft-eye { margin: 0 0 0.9rem; }
.craft-tests { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0 clamp(1rem, 2vw, 1.75rem); border-top: 1px solid var(--ink); }
.craft-test { padding: 1.1rem 0 1.4rem; border-bottom: 1px solid var(--line-2); display: flex; flex-direction: column; }
.craft-n { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.12em; color: var(--brass-2); }
.craft-t { margin: 0.6rem 0 0; font-family: var(--display); font-weight: 500; font-size: 1.25rem; line-height: 1.2; color: var(--ink); }
.craft-d { margin: 0.6rem 0 0; font-size: 0.92rem; line-height: 1.5; color: var(--ink-2); }
.craft-b { margin: 0.7rem 0 0; padding-top: 0.6rem; border-top: 1px solid var(--line); font-size: 0.85rem; line-height: 1.45; color: var(--ink-3); margin-top: auto; }

.craft-phil { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 1.5rem clamp(2rem, 5vw, 4rem); align-items: start; margin: clamp(2.5rem, 5vw, 3.75rem) 0; padding: clamp(1.5rem, 3vw, 2.25rem) 0; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--line-2); }
.craft-phil-t { margin: 0; font-family: var(--display); font-weight: 500; font-size: clamp(1.6rem, 3vw, 2.25rem); line-height: 1.15; letter-spacing: -0.015em; color: var(--ink); max-width: 14em; }
.craft-phil-l { margin: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.25rem 1.5rem; }
.craft-phil-l dt { font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brass-2); }
.craft-phil-l dd { margin: 0.5rem 0 0; font-size: 0.98rem; line-height: 1.5; color: var(--ink-2); }

.plates--craft .plate-lever { display: block; }
.plate-why-k { display: block; margin-top: 0.7rem; font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); }
.plate-why { list-style: none; margin: 0.45rem 0 0; padding: 0; }
.plate-why li, .wrap .plate-why > li { max-width: none; position: relative; padding-left: 1rem; margin: 0 0 0.35rem; font-size: 0.9rem; line-height: 1.45; color: var(--ink-2); }
.plate-why li::before { content: ""; position: absolute; left: 0; top: 0.65em; width: 0.5rem; height: 1px; background: var(--brass-2); }
.craft-prov { margin: 1.5rem 0 0; padding-left: 0.85rem; border-left: 2px solid var(--brass); font-size: 0.9rem; color: var(--ink-3); }

@media (max-width: 1100px) { .craft-tests { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 900px) {
  .craft-head { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .craft-phil { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 700px) {
  .craft-tests { grid-template-columns: minmax(0, 1fr); }
  .craft-test { display: grid; grid-template-columns: 2.5rem minmax(0, 1fr); column-gap: 0.5rem; padding: 1.1rem 0; }
  .craft-n { grid-row: 1 / span 3; padding-top: 0.35rem; }
  .craft-b { margin-top: 0.6rem; }
  .craft-phil-l { grid-template-columns: minmax(0, 1fr); }
}

/* Founder section, slimmed. The portrait and the sentence sit side by side, and
   the three proof points run as one icon row beneath them instead of a tall
   panel. Icons are drawn for these facts (bars, seven sites, a cloche) and
   deliberately avoid a rosette, laurel or star. */
.founder { grid-template-columns: 300px minmax(0, 1fr); align-items: center; }
.founder-quote { font-size: clamp(1.35rem, 2.6vw, 2rem); max-width: 30ch; }
.founder-facts { grid-column: 1 / -1; list-style: none; margin: 0; padding: clamp(1.25rem, 2.5vw, 1.75rem) 0 0; border-top: 1px solid var(--green-line); display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.25rem clamp(1.25rem, 3vw, 2.5rem); max-width: none; }
.founder-facts > li, .wrap .founder-facts > li { max-width: none; }
.ff { display: grid; grid-template-columns: 3.25rem minmax(0, 1fr); column-gap: 1.1rem; align-items: start; }
.ff .fi { grid-row: 1 / span 2; color: var(--brass); width: 3.25rem; height: 3.25rem; }
.ff-h { margin: 0; font-size: 1.02rem; line-height: 1.3; color: var(--on-green); }
.ff-h b { font-family: var(--display); font-weight: 500; font-size: 1.6rem; line-height: 1; color: var(--brass); margin-right: 0.25rem; font-variant-numeric: tabular-nums; }
.ff-d { margin: 0.35rem 0 0; font-size: 0.88rem; line-height: 1.45; color: var(--on-green-2); }
@media (max-width: 820px) {
  .founder { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
  .founder-facts { grid-template-columns: minmax(0, 1fr); }
}

/* The phone swipe strip suits bare photographs. These plates carry their
   argument, so on a phone they stack and nothing is hidden off screen. */
@media (max-width: 640px) {
  .plates--craft { display: grid; grid-template-columns: minmax(0, 1fr); grid-auto-flow: row; grid-auto-columns: auto; overflow: visible; scroll-snap-type: none; gap: 2rem; padding-bottom: 0; }
  .plates--craft .plate img { aspect-ratio: 5 / 4; object-position: center 40%; }
}

.craft-sample { margin: 1rem 0 0; }

/* ==========================================================================
   Guide pages. The answer used to start about 1,200px down, behind a meta
   strip and a full author block. A one line byline and a collapsed contents
   list take their place, and the full author box now closes the article.
   ========================================================================== */
.byline { display: grid; grid-template-columns: 40px minmax(0, 1fr); column-gap: 0.85rem; align-items: center; margin: 0.25rem 0 1.5rem; }
.byline-face { grid-row: 1 / span 2; width: 40px; height: 40px; border-radius: 50%; object-fit: cover; background: var(--ink); }
.byline-t { margin: 0; font-size: 0.95rem; line-height: 1.3; color: var(--ink); }
.byline-t span { color: var(--ink-3); margin-left: 0.4rem; font-size: 0.85rem; }
.byline-m { margin: 0.15rem 0 0; font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); }
@media (max-width: 520px) { .byline-t span { display: block; margin: 0; } }

.toc-mini { margin: 0 0 2.25rem; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.toc-mini summary { display: flex; align-items: center; justify-content: space-between; min-height: 48px; cursor: pointer; list-style: none; font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink); }
.toc-mini summary::-webkit-details-marker { display: none; }
.toc-mini summary span { color: var(--ink-3); }
.toc-mini summary::after { content: "+"; font-size: 1.2rem; line-height: 1; color: var(--brass-2); margin-left: 0.75rem; }
.toc-mini details[open] summary::after { content: "\2212"; }
.toc-mini summary:focus-visible { outline: 2px solid var(--info); outline-offset: 2px; }
.toc-mini ol { margin: 0; padding: 0.25rem 0 1.1rem 1.25rem; columns: 2; column-gap: 2.5rem; }
.toc-mini li { break-inside: avoid; margin: 0; padding: 0.3rem 0; max-width: none; font-size: 0.95rem; line-height: 1.4; }
.toc-mini a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--line-2); }
.toc-mini a:hover { border-bottom-color: var(--brass-2); }
@media (max-width: 620px) { .toc-mini ol { columns: 1; } .toc-mini li { padding: 0.5rem 0; } }

.author-end { margin-top: 3rem; }
.author-end-k { margin: 0; font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); }
.author-end .author { margin-block: 0.75rem 0; }
