/* Modernist — the VesselSuite design system, recovered verbatim from the
   published artifact bundle (claude.ai/artifact/9PZEkDs6fci6R6pcvBzD6X), which
   carried the _ds/modernist-* assets the .dc.html exports referenced but never
   shipped. Archivo is self-hosted from assets/fonts/, so the site still makes
   zero external requests. Site-level overrides are at the end of this file and
   are the only departures from the system as authored. */
/* Modernist — design-system tokens and component classes. This file is the source of truth for the system's look; retune it here and see readme.md. */
/* vietnamese */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-vietnamese.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-vietnamese.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-vietnamese.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


:root {
  --color-bg: #f3f2f2;
  --color-surface: #eae9e9;
  --color-text: #201e1d;
  --color-accent: #ec3013;
  --color-accent-2: #e15b47;
  --color-divider: color-mix(in srgb, #201e1d 40%, transparent);

  /* Tonal ramps — generated in OKLCH on one shared lightness scale, so the
     same step of any role matches the others in visual value. */
  --color-neutral-100: #f8f4f4;
  --color-neutral-200: #eae7e7;
  --color-neutral-300: #d7d3d3;
  --color-neutral-400: #bab6b6;
  --color-neutral-500: #9b9797;
  --color-neutral-600: #7d7979;
  --color-neutral-700: #605d5d;
  --color-neutral-800: #444141;
  --color-neutral-900: #2d2b2b;

  --color-accent-100: #fff2ef;
  --color-accent-200: #ffe0d9;
  --color-accent-300: #ffc4b8;
  --color-accent-400: #ff9783;
  --color-accent-500: #ff563c;
  --color-accent-600: #dd2b0f;
  --color-accent-700: #ae1800;
  --color-accent-800: #7c1405;
  --color-accent-900: #4d170e;

  --color-accent-2-100: #fff2ef;
  --color-accent-2-200: #ffe0da;
  --color-accent-2-300: #ffc4b9;
  --color-accent-2-400: #ff9784;
  --color-accent-2-500: #ef6853;
  --color-accent-2-600: #c94b39;
  --color-accent-2-700: #9e3526;
  --color-accent-2-800: #71261b;
  --color-accent-2-900: #471d16;

  --font-heading: "Archivo", system-ui, sans-serif;
  --font-heading-weight: 800;
  --font-body: "Archivo", system-ui, sans-serif;

  --space-1: 4.0px;
  --space-2: 8.0px;
  --space-3: 12.0px;
  --space-4: 16.0px;
  --space-6: 24.0px;
  --space-8: 32.0px;

  --radius-sm: 0px;
  --radius-md: 0px;
  --radius-lg: 0px;

  /* Elevation — derived from the ground: soft ink-tinted shadows on a
     light theme, a hairline edge + ambient darkness on a dark one. */
  --shadow-sm: 0 1px 2px color-mix(in srgb, #2d2b2b 14%, transparent);
  --shadow-md: 0 3px 10px color-mix(in srgb, #2d2b2b 16%, transparent);
  --shadow-lg: 0 12px 32px color-mix(in srgb, #2d2b2b 22%, transparent);
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
}
h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); }

.grayscale{filter:grayscale(1) contrast(1.08)}

/* ══════════════════════════════════════════════════════════════════════════
   Components — built with the tokens above. Plain CSS
   on plain HTML: no JavaScript, no build step. Each class is documented in
   readme.md and demonstrated in foundations/ and components/.
   ══════════════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-size: 15px; line-height: 1.55; font-weight: 400; }
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  line-height: 1.12; letter-spacing: -0.015em; margin: 0 0 var(--space-2);
}
h1 { font-size: 42px; }
h2 { font-size: 32px; }
h3 { font-size: 25px; }
h4 { font-size: 20px; }
h5 { font-size: 16px; }
h6 { font-size: 13px; }
h6 { letter-spacing: 0.08em; text-transform: uppercase; }
p { margin: 0 0 var(--space-3); }
a { color: var(--color-accent); text-underline-offset: 3px; }
img { display: block; max-width: 100%; }
figure { margin: 0; }
figcaption {
  font-size: 11px; margin-top: var(--space-1);
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.text-muted { color: color-mix(in srgb, var(--color-text) 55%, transparent); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* — rules — */
.hr {
  height: 2px; border: 0; margin: var(--space-4) 0;
  background: var(--color-divider);
}

/* — buttons — */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; line-height: 1.2; color: var(--color-text); /* matches the .input's 14px —
     the pair sits side by side in sign-up rows */
  background: transparent; border: 1px solid transparent;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  border-radius: var(--radius-md);
}
.btn svg { display: block; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-primary { background: var(--color-accent); color: var(--color-bg); }
.btn-primary:hover { background: var(--color-accent-600); }
.btn-primary:active { background: var(--color-accent-700); }
.btn-secondary { border-color: var(--color-divider); }
.btn-secondary:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.btn-secondary:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
.btn-ghost { color: var(--color-accent); padding-inline: var(--space-1); }
.btn-ghost:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.btn-ghost:active { background: color-mix(in srgb, var(--color-accent) 18%, transparent); }
.btn-icon { width: 36px; height: 36px; padding: 0; }
.btn-block { width: 100%; margin-top: var(--space-2); justify-content: flex-start; text-align: left; }

/* — forms — */
.field > label {
  display: block; font-size: 12px; margin-bottom: 5px;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}
.input {
  width: 100%; min-height: 36px; padding: 6px 10px; font: inherit;
  font-size: 14px; color: var(--color-text); caret-color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.input:focus-visible { border-color: var(--color-accent); outline-offset: 0; }
textarea.input { min-height: 90px; resize: vertical; }
.radio { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 14px; }
.radio input, .seg-opt input {
  position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
.radio .dot {
  width: 16px; height: 16px; flex: none; border-radius: 50%;
  border: 1.5px solid var(--color-divider);
}
.radio:hover .dot { border-color: var(--color-accent); }
.radio input:checked + .dot {
  border-color: var(--color-accent); background: var(--color-accent);
  box-shadow: inset 0 0 0 4px var(--color-bg);
}
.radio input:focus-visible + .dot { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.seg {
  display: inline-flex; overflow: hidden;
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.seg-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; font-size: 13px; cursor: pointer;
}
.seg-opt + .seg-opt { border-left: 1px solid var(--color-divider); }
.seg-opt:has(input:checked) { background: var(--color-accent); color: var(--color-bg); }
.seg-opt:not(:has(input:checked)):hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.seg-opt:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: -2px; }

/* — cards — */
.card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); border-radius: var(--radius-md); background: var(--color-surface);
}
.card-kicker { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-accent); }
.card-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 17px; line-height: 1.2;
}
.card-body { margin: 0; font-size: 13px; opacity: 0.8; flex: 1; }
.card-meta {
  display: flex; align-items: center; gap: 6px; font-size: 11px;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}
.elev-sm { box-shadow: var(--shadow-sm); }
.elev-md { box-shadow: var(--shadow-md); }
.elev-lg { box-shadow: var(--shadow-lg); }

/* — tags — */
.tag {
  display: inline-flex; align-items: center; font-size: 11px;
  letter-spacing: 0.02em; padding: 3px 10px;
  border-radius: calc(var(--radius-md) * 0.75);
}
.tag-accent { background: var(--color-accent-100); color: var(--color-accent-800); }
.tag-accent-2 { background: var(--color-accent-2-100); color: var(--color-accent-2-800); }
.tag-neutral { background: var(--color-neutral-100); color: var(--color-neutral-800); }
.tag-outline { border: 1px solid var(--color-accent); color: var(--color-accent); }

/* — navigation — */
.nav {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: 2px solid var(--color-divider);
}
.nav-brand {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 18px; margin-right: auto;
}
.nav a { color: inherit; text-decoration: none; font-size: 14px; }
.nav a:hover { color: var(--color-accent); }

/* — tables — */
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th {
  text-align: left; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
  padding: var(--space-2); border-bottom: 2px solid var(--color-divider);
}
.table td {
  padding: var(--space-2);
  border-bottom: 1px solid var(--color-divider);
}
.table tbody tr:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }

/* — dialog — */
.dialog-backdrop {
  position: fixed; inset: 0; display: grid; place-items: center;
  padding: var(--space-4);
  background: color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
}
.dialog {
  width: min(440px, 100%); display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4); border-radius: var(--radius-lg);
  background: var(--color-surface); box-shadow: var(--shadow-lg);
}
.dialog-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 20px;
}
.dialog-body { font-size: 14px; opacity: 0.85; }
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-2); }

/* ── site overrides ─────────────────────────────────────────────────────────
   The blocks below, in order, and only the first two are about contrast: the
   nav colour pair, the .btn-primary fill, scroll-behavior, .skip, @media print,
   the 2.5.8 tap targets, the focus ring restated, anchor clearance, the
   current page, the sticky nav, the legal pages' contents, the grids that ran
   off a phone, and the product screenshots. No count is kept here;
   the list is the record. Everything ABOVE this line is the system as
   authored — change a block here rather than a token up there.

   Every ratio below is computed from the tokens in this file, WCAG 2.x
   relative luminance. They read 3.4, 4.0 and 6.5, none of which was a
   measurement, and the first described a defect these two lines already fix. */

/* `.nav a` (0,1,1) outranks `.btn-primary` (0,1,0), so WITHOUT the two lines
   below a button in the nav inherits the body colour — #201e1d on the accent,
   3.95:1, under the 4.5:1 an unbolded 14px label needs. With them it is
   --color-bg on accent-700: 6.41:1. */
.nav a:not(.btn) { color: inherit; }
.nav a.btn-primary { color: var(--color-bg); }
.nav a.btn-ghost:hover { color: var(--color-accent-800); }

/* accent-700 rather than accent: --color-bg on #ec3013 is 3.76:1 and fails AA
   for the .btn's 14px label. accent-700 is 6.41:1 and stays on-palette. */
.btn-primary { background: var(--color-accent-700); }
.btn-primary:hover { background: var(--color-accent-800); color: var(--color-bg); }
.btn-primary:active { background: var(--color-accent-800); }
.btn-ghost, .btn-ghost:hover { color: var(--color-accent-700); }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 30; /* above the sticky nav's 20, or it focuses behind the bar */
  padding: 10px 16px;
  background: var(--color-text);
  color: var(--color-bg);
  font-family: var(--font-body);
  font-size: 14px;
}
.skip:focus { left: 0; color: var(--color-bg); }

/* the legal pages get printed; the navigation and the calls to action do not */
@media print {
  :root { --color-divider: #ddd; }
  .nav, .skip, .btn { display: none !important; }
  body { color: #000; font-size: 11pt; }
  a { color: #000; text-decoration: underline; }
  main a[href^="http"]::after,
  main a[href^="mailto"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
  h1, h2, h3 { break-after: avoid; }
  section, footer { break-inside: avoid; }
}

/* WCAG 2.5.8 wants a standalone target to be at least 24px. The pages set every
   type size inline, so growing the box would move the layout; this grows the
   HIT AREA instead and nothing shifts. It is applied to the nav and to links
   marked .tap — not to links inside a sentence, which the rule exempts and
   whose neighbours are a line-height apart. */
.nav a,
a.tap { position: relative; }
.nav a::after,
a.tap::after {
  content: "";
  position: absolute;
  /* 3px, not more: the nav's own row-gap is 8px, so a 22px link wrapped onto a
     second line sits 30px below the one above it. Expanding by 5 made adjacent
     rows' hit areas overlap on a phone, which puts the wrong link under a
     thumb. 3px gives 28px — over the 24px floor, with 2px still between. */
  inset: -3px -6px;
}

/* The authored system says `:focus { outline: none }` and, on the very next
   line, `:focus-visible { outline: … }`. The first is safe only while the
   second stands; delete it, or reorder them, and every keyboard user loses the
   only mark of where they are, with nothing failing. So the ring is restated
   here, where the site owns it — a guard, not a note beside the risk.
   #ec3013 on --color-bg is 3.76:1, over the 3:1 a focus indicator needs. */
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* Where a fragment jump stops: clear of the pinned nav, plus a breath. The
   nav's height differs by page and by width — measured 61px on one row, 100px
   on two, 134px on three — so app.js sets --nav-clearance from the bar's real
   height whenever it changes. These are the values without a script: a breath
   where the nav scrolls away, and the tallest pinned bar (100px) plus the
   breath where it stays. */
:root { --nav-clearance: 16px; }
@media (min-width: 1024px) { :root { --nav-clearance: 116px; } }
[id] { scroll-margin-top: var(--nav-clearance); }

/* The nav stays put while the page scrolls — the same bar as at the top, not a
   smaller one — wherever it fits. Measured in serve.py: at 1024px and up it is
   one row (61px) or at most two (100px, WasteBook at 1024). Narrower it
   is three to six rows (134px at 860, 193px on a phone), and pinning that would
   cover up to a quarter of the screen, so there it scrolls away as it always
   did.

   The authored .nav has no position, background or z-index — right for a bar
   in flow, wrong for one the page scrolls underneath. */
@media (min-width: 1024px) {
  .nav { position: sticky; top: 0; z-index: 20; background: var(--color-bg); }
}

/* Keep the homepage's first action within reach on a phone. */
.p-index .home-hero h1 { max-width: 18ch; }
.p-index .nav-brand { font-size: 18px; }
body .cost-label { font-size: clamp(28px, 4vw, 44px); line-height: 1.15; }
@media (max-width: 600px) {
  body .s-9d2a3792 { grid-template-columns: minmax(0, 1fr); }
  body .s-059fa833 { grid-template-columns: minmax(0, 1fr); row-gap: 12px; }
  .s-059fa833 > .s-ecbd410c:not(:first-child) { margin-top: var(--leading); }
  .s-059fa833 > span:empty { display: none; }
  .nav { gap: 12px; }
  .nav [data-nav-sections] { flex-basis: 100%; gap: 8px 16px; }
  .nav > .btn { margin-left: 0; }
  .p-index .home-hero { padding: 40px 0 48px; }
  .p-index .home-hero h1 { font-size: clamp(36px, 10.8vw, 42px); line-height: 1.08; }
  .p-index .home-hero .s-7bade8ff { font-size: 16px; line-height: 25px; }
}

/* Where you are, in bold and underlined. aria-current="page" is written into
   pages/ on each self-link; data-current is set by app.js on the section
   being read. Separate attributes, because the page is a fact about the
   document and the section a fact about one reader's viewport — but the same
   mark, because to the reader they answer the same question. (0,2,1) beats
   `.nav a` and the per-page `a { text-decoration: none }` rules.

   600, not 800. Measured on the WasteBook nav at 1280px: reserving 800's
   width for its seven links wrapped the bar onto a second row (61px -> 100px),
   so the pinned bar would no longer have been the bar at the top. 600 is a
   real face this file already loads, and keeps it one row. */
.nav a[aria-current="page"],
.nav a[data-current] {
  font-weight: 600;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 6px;
}

/* Bold is wider than regular, so a mark moving down the nav would shove every
   link after it sideways as you scroll. app.js copies each spied link's text
   into data-label, and this reserves that text's bold width in advance, as an
   invisible zero-height line: the link is always as wide as its bold self.
   It costs about 20px of nav width, and the WasteBook bar had none to
   spare: its content box is 1072px at 1280 but only 1056px from about 1440 up
   (the side margin grows with the window until it caps), and with the
   reservation it needed 1063 — so it wrapped onto two rows on every screen
   1440px and wider while looking fine at 1280. The gap between section links
   drops from 20px to 16px to pay for it, measured to fit at every width from
   1024 to 1920. */
.nav [data-nav-sections], .nav .nav-products { column-gap: 16px; }
.nav a[data-label] { display: inline-block; }
.nav a[data-label]::before {
  content: attr(data-label);
  display: block; height: 0; overflow: hidden; visibility: hidden;
  font-weight: 600;
}

/* The legal pages' table of contents. Hand-written in pages/, not generated:
   build.py deleted anchor_sections() so that markup like this lives where it
   can be read, and check_links already refuses an entry whose section is gone,
   which was the only thing generating it would have bought. An <ol>, so its
   numbers are the pages' own section numbers. Two columns where they fit, one
   on a phone. Its links keep the legal pages' accent-700, 6.41:1. */
.toc { margin: calc(1.5 * var(--leading)) 0; }
.toc-title {
  display: block; margin: 0 0 12px;
  font-size: 13px; line-height: 14px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--color-accent-700);
}
.toc ol {
  margin: 0; padding-left: 1.8em;
  columns: 2 16em; column-gap: 48px;
  font-size: 15px; line-height: var(--leading);
}
.toc li { break-inside: avoid; }
.toc a { display: block; min-height: 28px; }

/* Grids that ran off a phone. At 375px three pages scrolled sideways — the
   front page by 63px, WasteBook by 77, OneBook by 114 — measured in
   serve.py, and live since before this stylesheet was extracted.

   The label | heading | paragraph rows (.s-da52f7c8, .s-7540e55d) are
   minmax(64px,120px) minmax(0,380px) 1fr: the middle track takes its 380px
   first, so the paragraph's column is what gives way. Measured: 0px at 375,
   115px at 768, 223px at 900, 325px at 1024. At 0 the paragraph's words spill
   past the edge. Below 860px, where that column falls under ~190px, the row
   stacks instead.

   Four-item sequences use four, two or one columns, keeping tablet rows
   balanced. Other card groups fit as many 220px columns as their box allows.

   Two grids already auto-fit and still overflowed at 320px: .s-4db17b91 has a
   320px minimum, wider than a 320px phone's 280px of content, so its single
   column cannot fit; .s-81ef9f36 does the same at 240px inside a narrower box.
   min(N, 100%) lets the minimum give way to the container.

   `body` in front of each: the generated .s- rules come later in this file
   and would win a tie at equal specificity. */
@media (max-width: 860px) {
  body .s-da52f7c8, body .s-7540e55d {
    grid-template-columns: 2ch minmax(0, 1fr);
    gap: 12px 20px;
    padding: var(--leading) 0;
  }
  .s-da52f7c8 > p:last-child, .s-7540e55d > p:last-child { grid-column: 2; }
}
body .s-3e3bd7f2, body .s-74b397cf, body .s-88d1eacf, body .s-e54efa66 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 1000px) {
  body .s-3e3bd7f2, body .s-74b397cf, body .s-88d1eacf, body .s-e54efa66 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 600px) {
  body .s-3e3bd7f2, body .s-74b397cf, body .s-88d1eacf, body .s-e54efa66 {
    grid-template-columns: minmax(0, 1fr);
  }
}
body .s-5ec55f7c { grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); }
body .s-4db17b91 { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
body .s-81ef9f36 { grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
body .s-ea80e839 { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }

/* Shared closing panels need readable text in every link state. */
body .s-5a3b080b, body .s-f117d0b0 { background: var(--color-accent-700); }
body .s-dc5881ec:hover { color: var(--color-bg); background: var(--color-accent-800); }
.s-5a3b080b :focus-visible, .s-f117d0b0 :focus-visible { outline-color: var(--color-bg); }
body .s-286140fa { align-items: center; }

/* Keep actions aligned when adjacent descriptions have different lengths. */
.s-8ff4dac6 > div { display: flex; flex-direction: column; }
.s-8ff4dac6 > div > p:last-child { margin-top: auto; padding-top: var(--leading); }

/* Legal prose, tables and shared navigation use the same reading rhythm. */
.p-privacy .nav-brand, .p-terms .nav-brand, .p-security .nav-brand, .p-404 .nav-brand { font-size: 18px; }
.p-privacy main p a, .p-terms main p a, .p-security main p a { text-decoration: underline; }
.faq h3 { margin-top: calc(1.75 * var(--leading) - 1cap); }
.limits li a { text-decoration: underline; }
.p-privacy .table { max-width: 70ch; margin-top: var(--leading); font-size: 15.5px; }
.p-privacy .table th, .p-privacy .table td { vertical-align: top; }
.p-privacy .table th { color: var(--color-text); }
body .s-ecbd410c { color: var(--color-accent-700); }
body footer a { text-decoration: none; }
body footer a:hover { text-decoration: underline; }
.recovery-links { display: flex; flex-wrap: wrap; gap: 12px 24px; }

@media (max-width: 600px) {
  body .s-e9dde8b3, body .s-06dba253, body .s-02a1c88b {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 20px;
  }
  .p-onebook .s-2be23b82, .p-safebook .s-2be23b82, .p-wastebook .s-b5aa93a4 { padding: 40px 0 48px; }
  .p-onebook .s-2be23b82 h1, .p-safebook .s-2be23b82 h1, .p-wastebook .s-b5aa93a4 h1 {
    font-size: clamp(36px, 10.8vw, 42px);
    line-height: 1.08;
  }
  .p-onebook .s-5784f326, .p-safebook .s-5784f326, .p-wastebook .s-7bade8ff { font-size: 16px; line-height: 25px; }
}

/* Product screenshots on the WasteBook page, from the ship application's
   own demonstration register. Two across where there is room and stacked on a
   phone, by the same auto-fit rule the grids above use; .shot-wide spans the
   row. The img carries width and height, so the page does not jump as each one
   loads. The authored `figcaption` is 11px at 55% — too faint to read a
   sentence in — so these captions are 14px at 70%. */
.shots {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr));
  gap: calc(1.5 * var(--leading)) clamp(24px, 4vw, 48px);
  margin-top: calc(2 * var(--leading));
}
.shot { margin: 0; }
.shot-wide { grid-column: 1 / -1; }
/* Two across, a 1440px screen is shown at about 500px and its words are too
   small to read, so each image links to its full-size file. */
.shot-link { display: block; cursor: zoom-in; }
.shot-link:hover img { box-shadow: var(--shadow-lg); }
.shot img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--color-divider);
  box-shadow: var(--shadow-md);
  background: var(--color-surface);
}
.shot figcaption {
  margin-top: 12px; max-width: 64ch;
  font-size: 14px; line-height: 1.5;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}

/* ══════════════════════════════════════════════════════════════════════════
   PER-PAGE HEAD STYLES, lifted from the five exports' helmets on
   22 September 2026 — APPENDED, and the position is the whole point.

   Each export carried one <style> block, emitted into <head> AFTER the ds.css
   <link>, so at equal specificity those rules beat this file's. Moving them
   here without moving them to the END would silently hand every tie back to
   ds.css: `a` would go back to --color-accent, and the four pages that turn
   link underlines off would get them back.

   Four of the five blocks were byte-identical; OneBook's differed and
   still does, which is what `.p-onebook` is for. The 404's block is here
   too, and it is the one page whose rendering this CHANGES rather than
   preserves: it used var(--leading) and var(--edge) while defining neither,
   so its gap fell back to `normal` and its padding to `0`. Both are declared
   on :root now — where the four other pages had them on a wrapper div and
   OneBook had them in its own :root — so the 404 finally lays out the way
   it always read as though it would.
   ══════════════════════════════════════════════════════════════════════ */

:root { --leading: 28px; --edge: clamp(20px, 5vw, 72px); }

/* The body rule is reproduced WHOLE, including the three declarations this file
   already makes further up, and that is not redundancy. @media print above sets
   `body { color: #000 }` and `a { color: #000 }`; the helmet used to sit AFTER
   this whole file in the document and quietly beat it. Declaring only
   text-wrap here handed print back to the print block and turned every page
   black — measured, 10,240 property differences on the front page alone.

   Worth writing down: it means the print block's colour rules have never
   applied to these five pages. They applied to the 404, which carried no
   helmet. Whether print SHOULD be black is a real question and a separate
   one; this move is not the place to answer it. */
body { margin: 0; text-wrap: pretty; background: var(--color-bg); color: var(--color-text); font-family: var(--font-body); }
a { color: var(--color-accent-700); }
a:hover { color: var(--color-accent-800); }

/* The four that suppress underlines. OneBook deliberately does not: its
   helmet carried no text-decoration rule, so its links are underlined, and
   reproducing that is a migration rather than a redesign. Whether the five
   should agree is a question for a person, and it is not this file's to take. */
.p-index a, .p-wastebook a, .p-safebook a, .p-privacy a, .p-terms a, .p-security a { text-decoration: none; }
.p-index a:hover, .p-wastebook a:hover, .p-safebook a:hover,
.p-privacy a:hover, .p-terms a:hover, .p-security a:hover { text-decoration: underline; }

/* OneBook's own. The height rules and the `body > div` reset came from the
   artifact runtime that used to wrap these pages; they match nothing now, and
   they are carried verbatim rather than dropped so that this move changes
   nothing it did not set out to change. Deleting them is a one-line follow-up
   once the computed-style comparison has been read. */
/* Scoped, because only OneBook's helmet carried it. Applied to every page
   it changes html's computed background from transparent on the other five —
   invisible, since body paints the same colour over it, and still a change
   this move did not set out to make. */
html:has(.p-onebook) { background: var(--color-bg); }
.p-onebook, html:has(.p-onebook) { height: auto; min-height: 100%; }

/* OneBook's helmet set these two on body and they look redundant, because
   the same values are declared on `body` at the top of this file. They are not:
   @media print above sets `body { font-size: 11pt }`, and the helmet used to sit
   after the whole stylesheet and beat it. Dropping them as duplicates reprinted
   the entire page at 11pt — measured, 2,154 property differences, all of them
   `font-size` and `line-height` in print media and none of them on screen. A
   class beats the print block's element selector whatever the order, so this is
   the form that survives somebody reordering the file. */
.p-onebook { font-size: 15px; line-height: 1.55; }
.p-onebook > div { min-height: 0; height: auto; }

/* The 404: its own layout, and the only page that has one. It sits between the
   site's nav and footer now, so it fills most of the screen rather than all of
   it — at 100svh the footer landed below the fold on every viewport. Block
   padding only: the container around it already pads the sides by --edge. */
.p-404 main {
  display: grid; place-content: center; gap: var(--leading);
  min-height: 60svh; padding: var(--edge) 0;
}
.p-404 h1 {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: clamp(28px, 3.4vw, 42px); letter-spacing: -0.02em; margin: 0;
}
.p-404 p { margin: 0; font-size: 15.5px; line-height: var(--leading); }

/*══════════════════════════════════════════════════════════════════════════
   EXTRACTED INLINE STYLES — 22 September 2026.

   The pages carried every typographic decision as a style="" attribute: 675
   attributes over 138 distinct declaration strings. That is why style-src had
   to carry 'unsafe-inline', and it is the only reason it did.

   The `/* ×N */` after each rule is how many elements wore it AT THAT
   MIGRATION. It is a record, not a count: it is not maintained, and new markup
   reusing these classes — which is the right way to write markup here — makes
   it stale on purpose. Measure uses in pages/ if you need them.

   These are APPENDED, for the same reason the helmet block above is: an inline
   attribute beat every rule in this file, so a class carrying the same
   declarations has to come last to keep winning the ties it used to win.

   The names are sha256 of the declaration string. They are meaningless on
   purpose — a name like .card-title would be a claim about what the rule is
   for, and nobody has checked that claim for 128 rules. Identical strings
   share a class; nothing was merged or rewritten. Equivalence was proved by
   rendering every page before and after at three widths in screen and print
   media and comparing every computed property of every element.
   ════════════════════════════════════════════════════════════════════════*/

.s-078b0ea1 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 17px; line-height: var(--leading); margin: 0; text-box: trim-both cap alphabetic; }   /* ×52 */
.s-aaefc22e { font-size: 15.5px; line-height: var(--leading); margin: calc(var(--leading) - 1cap) 0 0; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×51 */
.s-9797af67 { border-top: 2px solid var(--color-divider); padding-top: calc(var(--leading) - 1cap); }   /* ×46 */
.s-8677af2f { font-size: 15.5px; line-height: var(--leading); max-width: 70ch; margin: calc(var(--leading) - 1cap) 0 0; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×34 */
.s-98d0fc7d { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 22px; line-height: calc(1.15 * var(--leading)); letter-spacing: -0.015em; margin: 0; text-box: trim-both cap alphabetic; }   /* ×22 */
.s-ecbd410c { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 15px; line-height: var(--leading); color: var(--color-accent); }   /* ×22 */
.s-74fc43e7 { white-space: nowrap; }   /* ×20 */
.s-d2234468 { display: block; font-size: 13px; line-height: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent-700); margin: 0 0 14px; }   /* ×18 */
.s-47a4bbbe { padding: calc(3 * var(--leading)) 0 calc(2.5 * var(--leading)); }   /* ×17 */
.s-169d0ef3 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); }   /* ×16 */
.s-555d8a06 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 15px; line-height: var(--leading); font-feature-settings: 'tnum' 1; margin: 0; text-box: trim-both cap alphabetic; }   /* ×16 */
.s-94f73611 { font-size: 15.5px; line-height: var(--leading); margin: 0; max-width: 52ch; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×16 */
.s-b57725a7 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 24px; line-height: var(--leading); letter-spacing: -0.01em; margin: 0; text-box: trim-both cap alphabetic; }   /* ×16 */
.s-7217a965 { display: flex; flex-direction: column; gap: 10px; }   /* ×15 */
.s-a85133f2 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 15px; line-height: 20px; letter-spacing: -0.01em; color: var(--color-text); text-transform: uppercase; }   /* ×15 */
.s-bb44a95e { font-size: 13px; line-height: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent-700); margin: 0 0 16px; font-feature-settings: 'tnum' 1; }   /* ×13 */
.s-58746642 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 32px; line-height: calc(1.5 * var(--leading)); letter-spacing: -0.015em; margin: 0; text-box: trim-both cap alphabetic; }   /* ×12 */
.s-da52f7c8 { border-top: 2px solid var(--color-divider); display: grid; grid-template-columns: minmax(64px, 120px) minmax(0, 380px) minmax(0, 1fr); gap: var(--leading) clamp(24px, 4vw, 72px); align-items: baseline; padding: calc(1.5 * var(--leading)) 0; }   /* ×12 */
.s-89b11661 { display: block; flex: none; }   /* ×9 */
.s-a206a59b { max-width: 1200px; margin: 0 auto; padding: 0 var(--edge); }   /* ×8 */
.s-bd877e16 { display: block; }   /* ×7 */
.s-2bb48ce4 { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 24px; border-top: 2px solid var(--color-divider); margin-top: calc(2 * var(--leading)); padding: calc(1.25 * var(--leading)) 0 calc(2 * var(--leading)); }   /* ×5 */
.s-4ca4f1c6 { margin-left: auto; white-space: nowrap; }   /* ×5 */
.s-649f9eeb { flex: 1; }   /* ×5 */
.s-6c188296 { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--leading) clamp(24px, 4vw, 64px); }   /* ×5 */
.s-8ad6029e { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 20px; }   /* ×5 */
.s-98434415 { border-top: 2px solid var(--color-divider); padding-top: calc(1.25 * var(--leading)); }   /* ×5 */
.s-9a35e894 { font-size: 17px; line-height: var(--leading); max-width: 58ch; margin: calc(var(--leading) - 1cap) 0 0; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×5 */
.s-c1da43c9 { font-size: 13px; line-height: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent-700); margin: 0 0 16px; }   /* ×5 */
.s-dc5881ec { color: var(--color-bg); border-color: var(--color-bg); }   /* ×5 */
.s-ed07d383 { flex-wrap: wrap; row-gap: 12px; padding-inline: max(var(--edge), calc((100% - 1200px) / 2 + var(--edge))); }   /* ×5 */
.s-31e67c8c { font-size: 13px; line-height: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent-700); margin: 0 0 12px; }   /* ×4 */
.s-5ec55f7c { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--leading) clamp(24px, 4vw, 72px); margin-top: calc(2 * var(--leading)); }   /* ×4 */
.s-7540e55d { display: grid; grid-template-columns: minmax(64px, 120px) minmax(0, 380px) minmax(0, 1fr); gap: var(--leading) clamp(24px, 4vw, 72px); align-items: baseline; padding: calc(1.5 * var(--leading)) 0; }   /* ×4 */
.s-8558ca92 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 27px; line-height: calc(1.25 * var(--leading)); letter-spacing: -0.015em; margin: 0; text-box: trim-both cap alphabetic; }   /* ×4 */
.s-9a1d5659 { display: block; font-size: 13px; line-height: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: color-mix(in srgb, var(--color-text) 62%, transparent); margin: 0 0 8px; }   /* ×4 */
.s-9ac7c9ea { --leading: 28px; --edge: clamp(20px, 5vw, 72px); }   /* ×4 */
.s-cac5cf77 { font-size: 13px; line-height: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: color-mix(in srgb, var(--color-text) 70%, transparent); margin: 14px 0 0; }   /* ×4 */
.s-fb1ab7bd { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: clamp(34px, 3.4vw, 48px); line-height: calc(2 * var(--leading)); color: var(--color-accent); margin: 0 0 0 -0.045em; text-box: trim-both cap alphabetic; }   /* ×4 */
.s-2457feb6 { font-family: var(--font-body); font-size: 15.5px; line-height: var(--leading); color: var(--color-text); background: var(--color-bg); border: 2px solid var(--color-divider); border-radius: 0; padding: 8px 12px; width: 100%; box-sizing: border-box; }   /* ×3 */
.s-475c9658 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 32px; line-height: calc(1.5 * var(--leading)); letter-spacing: -0.015em; margin: 0; max-width: 30ch; text-box: trim-both cap alphabetic; }   /* ×3 */
.s-523ba2d2 { padding: calc(2.5 * var(--leading)) 0 0; font-size: 13px; line-height: 28px; color: color-mix(in srgb, var(--color-text) 70%, transparent); }   /* ×3 */
.s-5a3b080b { background: var(--color-accent); color: var(--color-bg); }   /* ×3 */
.s-5a4e38d6 { margin-top: calc(2 * var(--leading)); }   /* ×3 */
.s-6a983fea { width: 34px; height: 34px; color: var(--color-accent-700); display: block; margin-bottom: calc(0.75 * var(--leading)); }   /* ×3 */
.s-98cf0af0 { display: flex; align-items: center; gap: 12px; flex: none; white-space: nowrap; }   /* ×3 */
.s-b7f21fa6 { font-size: 15.5px; line-height: var(--leading); max-width: 60ch; margin: calc(1.25 * var(--leading) - 1cap) 0 0; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×3 */
.s-d0339cd2 { max-width: 1200px; margin: 0 auto; padding: calc(3 * var(--leading)) var(--edge); }   /* ×3 */
.s-dfa152ff { font-size: 15.5px; letter-spacing: 0; padding: 2px 10px; }   /* ×3 */
.s-f0b51600 { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--leading); }   /* ×3 */
.s-f7f61163 { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; margin-top: calc(1.25 * var(--leading)); }   /* ×3 */
.s-059fa833 { display: grid; grid-template-columns: 56px minmax(0, 1fr); column-gap: clamp(20px, 3vw, 32px); row-gap: calc(1.75 * var(--leading)); }   /* ×2 */
.s-0b1e0001 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: clamp(34px, 4.2vw, 56px); line-height: clamp(36px, 4.45vw, 59.4px); letter-spacing: -0.015em; margin: 0 0 0 -0.058em; max-width: 32ch; text-box: trim-both cap alphabetic; }   /* ×2 */
.s-0d4184ad { padding: calc(2.5 * var(--leading)) 0 calc(2 * var(--leading)); }   /* ×2 */
.s-0f0e5dfe { display: flex; align-items: center; gap: 12px; flex: none; white-space: nowrap; color: var(--color-text); }   /* ×2 */
.s-11f9b2f7 { border-top: 2px solid var(--color-accent); padding-top: calc(var(--leading) - 1cap); }   /* ×2 */
.s-25c017f6 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 24px; line-height: var(--leading); letter-spacing: -0.01em; margin: 0 0 calc(var(--leading) - 1cap) 0; padding-bottom: calc(var(--leading) - 1cap); border-bottom: 2px solid var(--color-divider); text-box: trim-both cap alphabetic; }   /* ×2 */
.s-286140fa { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: calc(1.5 * var(--leading)); }   /* ×2 */
.s-3c115869 { margin-top: 8px; }   /* ×2 */
.s-3f34c14d { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: clamp(42px, 6.2vw, 84px); line-height: clamp(44.5px, 6.57vw, 89px); letter-spacing: -0.02em; margin: 0 0 0 -0.058em; text-box: trim-both cap alphabetic; }   /* ×2 */
.s-58bf47c8 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: clamp(40px, 5.2vw, 66px); line-height: calc(2.5 * var(--leading)); letter-spacing: -0.03em; color: var(--color-accent); margin: 0 0 0 -0.05em; text-box: trim-both cap alphabetic; }   /* ×2 */
.s-6d40cb68 { display: flex; flex-direction: column; gap: 4px; white-space: nowrap; }   /* ×2 */
.s-6e7eace4 { display: flex; flex-wrap: wrap; gap: 8px 32px; font-size: 13px; line-height: 28px; color: color-mix(in srgb, var(--color-text) 62%, transparent); margin-top: calc(1.5 * var(--leading)); }   /* ×2 */
.s-7bade8ff { font-size: 17px; line-height: var(--leading); max-width: 58ch; margin: calc(1.5 * var(--leading) - 1cap) 0 0; text-box: trim-both cap alphabetic; }   /* ×2 */
.s-7ce46e9c { font-size: 17px; line-height: var(--leading); max-width: 62ch; margin: calc(1.5 * var(--leading) - 1cap) 0 0; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×2 */
.s-7ddef2cf { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: clamp(34px, 4.2vw, 56px); line-height: clamp(36px, 4.45vw, 59.4px); letter-spacing: -0.015em; margin: 0 0 0 -0.058em; text-box: trim-both cap alphabetic; }   /* ×2 */
.s-81ef9f36 { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--leading) clamp(24px, 4vw, 72px); margin-top: calc(1.5 * var(--leading)); }   /* ×2 */
.s-8ff4dac6 { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--leading) clamp(24px, 4vw, 72px); margin-top: calc(1.5 * var(--leading)); }   /* ×2 */
.s-99c7df4e { border-top: 2px solid var(--color-divider); padding: calc(2.5 * var(--leading)) 0 0; font-size: 13px; line-height: 28px; color: color-mix(in srgb, var(--color-text) 70%, transparent); }   /* ×2 */
.s-a1547dba { padding: calc(3.5 * var(--leading)) 0 calc(2 * var(--leading)); }   /* ×2 */
.s-a88a1a24 { fill: var(--color-text); opacity: 0.55; font-feature-settings: 'tnum' 1; }   /* ×2 */
.s-a96134ca { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: clamp(38px, 5vw, 64px); line-height: clamp(40px, 5.3vw, 68px); letter-spacing: -0.02em; margin: 0 0 0 -0.05em; text-box: trim-both cap alphabetic; }   /* ×2 */
.s-ad835167 { font-size: 15px; line-height: var(--leading); max-width: 74ch; margin: calc(1.5 * var(--leading) - 1cap) 0 0; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×2 */
.s-ada1302e { font-size: 15.5px; line-height: var(--leading); max-width: 74ch; margin: calc(1.5 * var(--leading) - 1cap) 0 0; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×2 */
.s-b10fe3f3 { white-space: nowrap; color: var(--color-text); }   /* ×2 */
.s-b5aa93a4 { padding: calc(4 * var(--leading)) 0 calc(3 * var(--leading)); }   /* ×2 */
.s-c9bc1432 { font-size: 15.5px; line-height: var(--leading); max-width: 60ch; margin: calc(var(--leading) - 1cap) 0 0; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×2 */
.s-de022c2f { line-height: 1; white-space: nowrap; }   /* ×2 */
.s-e73174ab { font-size: 13px; line-height: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: color-mix(in srgb, var(--color-text) 62%, transparent); margin: calc(2.5 * var(--leading)) 0 0; }   /* ×2 */
.s-f117d0b0 { background: var(--color-accent); color: var(--color-bg); padding: calc(3 * var(--leading)) clamp(24px, 4vw, 56px); margin-bottom: calc(2 * var(--leading)); }   /* ×2 */
.s-f122a859 { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: calc(1.75 * var(--leading)); }   /* ×2 */
.s-f4ead190 { padding: calc(2.5 * var(--leading)) 0; }   /* ×2 */
.s-fd066bbd { font-family: var(--font-body); font-size: 9.5px; font-weight: 400; letter-spacing: 0.06em; text-transform: uppercase; line-height: 1; white-space: nowrap; color: color-mix(in srgb, var(--color-text) 62%, transparent); }   /* ×2 */
.s-ff99c9cc { display: block; font-size: 13px; line-height: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent-700); margin: 0 0 18px; }   /* ×2 */
.s-02a1c88b { display: grid; grid-template-columns: 72px minmax(0, 1fr); column-gap: clamp(20px, 3vw, 32px); }   /* ×1 */
.s-06dba253 { border-top: 2px solid var(--color-divider); display: grid; grid-template-columns: 72px minmax(0, 1fr); column-gap: clamp(20px, 3vw, 32px); padding: calc(1.5 * var(--leading)) 0; }   /* ×1 */
.s-074ace16 { font-size: 17px; line-height: var(--leading); max-width: 52ch; margin: calc(1.5 * var(--leading) - 1cap) 0 0; }   /* ×1 */
.s-0c474fd7 { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-3) var(--leading); }   /* ×1 */
.s-0e3648af { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: clamp(40px, 5.8vw, 78px); line-height: 1.0; letter-spacing: -0.03em; margin: 0 0 0 -0.058em; max-width: 22ch; text-box: trim-both cap alphabetic; }   /* ×1 */
.s-10a543bc { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: clamp(19px, 2.1vw, 27px); line-height: calc(1.5 * var(--leading)); letter-spacing: -0.01em; color: var(--color-accent-700); margin: calc(1.5 * var(--leading) - 1cap) 0 0 -0.02em; text-box: trim-both cap alphabetic; }   /* ×1 */
.s-12f14d3f { fill: var(--color-text); font-family: var(--font-heading); font-weight: 600; font-feature-settings: 'tnum' 1; }   /* ×1 */
.s-155aee05 { border-top: 2px solid var(--color-divider); display: grid; grid-template-columns: 72px minmax(0, 1fr); column-gap: clamp(20px, 3vw, 32px); padding: calc(1.5 * var(--leading)) 0; margin-top: calc(var(--leading) - 1cap); }   /* ×1 */
.s-2153bff4 { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: calc(2 * var(--leading)); }   /* ×1 */
.s-25e51b25 { font-size: 15.5px; line-height: var(--leading); }   /* ×1 */
.s-2b4ad1ba { text-transform: none; letter-spacing: 0; }   /* ×1 */
.s-2be23b82 { padding: calc(3.5 * var(--leading)) 0 calc(2.5 * var(--leading)); }   /* ×1 */
.s-3070f194 { font-size: 15.5px; line-height: var(--leading); margin: calc(var(--leading) - 1cap) 0 var(--leading); color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×1 */
.s-359b8bb8 { font-size: 15.5px; line-height: var(--leading); max-width: 70ch; margin: calc(var(--leading) - 1cap) 0 0; padding-left: 20px; color: color-mix(in srgb, var(--color-text) 78%, transparent); }   /* ×1 */
.s-3e3bd7f2 { display: grid; grid-template-columns: repeat(4, 1fr); gap: calc(1.5 * var(--leading)) clamp(24px, 4vw, 72px); margin-top: calc(2 * var(--leading)); }   /* ×1 */
.s-41a1a18c { font-size: 15.5px; line-height: var(--leading); margin: var(--leading) 0 0; max-width: 52ch; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×1 */
.s-495765a2 { border-top: 2px solid var(--color-accent); padding-top: calc(1.25 * var(--leading)); }   /* ×1 */
.s-4a923ac9 { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: calc(1.5 * var(--leading)) var(--leading); }   /* ×1 */
.s-4db17b91 { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: calc(2 * var(--leading)) clamp(32px, 5vw, 88px); margin-top: calc(2.5 * var(--leading)); }   /* ×1 */
.s-508c263c { font-size: 15.5px; line-height: var(--leading); max-width: 62ch; margin: calc(1.25 * var(--leading) - 1cap) 0 0; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×1 */
.s-5129dc23 { margin-top: calc(2.5 * var(--leading)); }   /* ×1 */
.s-554d2457 { fill: var(--color-accent-200); }   /* ×1 */
.s-5784f326 { font-size: 17px; line-height: var(--leading); max-width: 62ch; margin: calc(1.5 * var(--leading) - 1cap) 0 0; text-box: trim-both cap alphabetic; }   /* ×1 */
.s-5c16532e { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 32px; line-height: calc(1.5 * var(--leading)); letter-spacing: -0.015em; margin: 0; max-width: 24ch; text-box: trim-both cap alphabetic; }   /* ×1 */
.s-64fcfa1a { font-size: 17px; line-height: var(--leading); max-width: 58ch; margin: calc(1.5 * var(--leading) - 1cap) 0 0; }   /* ×1 */
.s-65d8693e { border-top: 2px solid var(--color-accent); margin: calc(2.5 * var(--leading)) 0 0; padding: calc(1.5 * var(--leading) - 1cap) 0 0; }   /* ×1 */
.s-7123e1ea { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--leading) clamp(24px, 4vw, 72px); margin-top: calc(2.5 * var(--leading)); }   /* ×1 */
.s-74b397cf { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--leading) clamp(24px, 4vw, 72px); margin-top: calc(2 * var(--leading)); }   /* ×1 */
.s-76532ef5 { display: block; width: 100%; height: auto; overflow: visible; font-family: var(--font-body); }   /* ×1 */
.s-7c3d853c { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: clamp(22px, 2.4vw, 30px); line-height: calc(1.5 * var(--leading)); letter-spacing: -0.01em; margin: 0; max-width: 42ch; text-box: trim-both cap alphabetic; }   /* ×1 */
.s-7d5d1b82 { fill: var(--color-accent-700); font-family: var(--font-heading); font-weight: 600; letter-spacing: 0.06em; font-feature-settings: 'tnum' 1; }   /* ×1 */
.s-7de60eaa { position: absolute; left: -9999px; }   /* ×1 */
.s-8780d7e4 { font-size: 15.5px; line-height: var(--leading); margin: calc(var(--leading) - 1cap) 0 0; max-width: 58ch; color: color-mix(in srgb, var(--color-text) 78%, transparent); text-box: trim-both cap alphabetic; }   /* ×1 */
.s-879cf576 { fill: none; stroke: var(--color-accent); stroke-width: 4; }   /* ×1 */
.s-88d1eacf { display: grid; grid-template-columns: repeat(4, 1fr); gap: calc(1.5 * var(--leading)) clamp(24px, 4vw, 72px); }   /* ×1 */
.s-8916ee81 { border-top: 2px solid var(--color-accent); margin-top: calc(2.5 * var(--leading)); padding-top: calc(1.5 * var(--leading)); }   /* ×1 */
.s-8b240398 { margin: calc(2.5 * var(--leading)) 0 0; }   /* ×1 */
.s-9c195c5a { font-size: 15px; line-height: var(--leading); max-width: 78ch; margin: calc(1.5 * var(--leading) - 1cap) 0 0; color: color-mix(in srgb, var(--color-text) 72%, transparent); text-box: trim-both cap alphabetic; }   /* ×1 */
.s-9d2a3792 { display: grid; grid-template-columns: repeat(2, 1fr); gap: calc(1.5 * var(--leading)) clamp(24px, 4vw, 72px); margin-top: calc(2 * var(--leading)); }   /* ×1 */
.s-9f9a1067 { display: block; font-size: 13px; line-height: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent-700); }   /* ×1 */
.s-a056831b { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: clamp(28px, 3.4vw, 42px); line-height: 1.12; letter-spacing: -0.02em; margin: 0 0 0 -0.03em; max-width: 30ch; text-box: trim-both cap alphabetic; }   /* ×1 */
.s-ac175920 { border-top: 2px solid var(--color-accent); margin-top: calc(2 * var(--leading)); padding-top: calc(1.5 * var(--leading) - 1cap); }   /* ×1 */
.s-afe6d805 { fill: var(--color-accent-700); font-family: var(--font-heading); font-weight: 600; font-feature-settings: 'tnum' 1; }   /* ×1 */
.s-b279f52b { fill: none; stroke: var(--color-neutral-800); stroke-width: 4; }   /* ×1 */
.s-b830c149 { font-family: var(--font-body); font-size: 15.5px; line-height: var(--leading); color: var(--color-text); background: var(--color-bg); border: 2px solid var(--color-divider); border-radius: 0; padding: 8px 12px; width: 100%; box-sizing: border-box; resize: vertical; }   /* ×1 */
.s-bdf8422b { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: clamp(34px, 4.2vw, 56px); line-height: clamp(36px, 4.45vw, 59.4px); letter-spacing: -0.015em; margin: 0 0 0 -0.058em; max-width: 22ch; text-box: trim-both cap alphabetic; }   /* ×1 */
.s-c315df0c { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--leading) clamp(24px, 4vw, 72px); margin-top: calc(2.5 * var(--leading)); }   /* ×1 */
.s-cbe083ec { display: grid; gap: var(--leading); }   /* ×1 */
.s-d6437160 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 27px; line-height: calc(1.25 * var(--leading)); letter-spacing: -0.015em; margin: 0; max-width: 34ch; text-box: trim-both cap alphabetic; }   /* ×1 */
.s-e54efa66 { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--leading) clamp(24px, 4vw, 72px); margin-top: calc(1.5 * var(--leading)); }   /* ×1 */
.s-e5f6dbfa { border-top: 2px solid var(--color-divider); margin-top: calc(2 * var(--leading)); padding-top: calc(1.5 * var(--leading)); max-width: 640px; }   /* ×1 */
.s-e9dde8b3 { border-top: 2px solid var(--color-accent); display: grid; grid-template-columns: 72px minmax(0, 1fr); column-gap: clamp(20px, 3vw, 32px); padding: calc(1.5 * var(--leading)) 0; margin-top: calc(var(--leading) - 1cap); }   /* ×1 */
.s-ea80e839 { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: calc(2 * var(--leading)) clamp(32px, 5vw, 88px); margin-top: calc(2 * var(--leading)); }   /* ×1 */
.s-ff791649 { position:absolute; }   /* ×1 */

/* the one-line hint under the enquiry form's file input; same 70% mix as the footer's 13px text */
.enq-hint { font-size: 13px; line-height: 20px; margin: 8px 0 0; color: color-mix(in srgb, var(--color-text) 70%, transparent); }

/* ── Photos ───────────────────────────────────────────────────────────────
   Added with the website photo set (2026-10-12). Files live in
   site/assets/photos/; sources and credits are in the photo package's
   manifest.json and CREDITS.md. Appended at the END of ds.css on purpose:
   later rules win ties, as the generated s-* classes do.
   Square corners and no shadow, to match the Modernist system (radius 0). */
.photo { margin: calc(1.5 * var(--leading)) 0 0; }
.photo picture,
.photo img { display: block; width: 100%; }
.photo img { height: auto; background: var(--color-neutral-200); }

/* Home and product-page headers: the photo closes the section, under the buttons. */
.photo-hero { margin-top: calc(2 * var(--leading)); }

/* In-section photos: a letterbox crop on wide screens, so a photo supports the
   section instead of filling the screen. Full 3:2 on narrow screens. */
@media (min-width: 861px) {
  .photo-wide img { aspect-ratio: 2 / 1; object-fit: cover; }
}

/* Inside an audience card: above the heading, so the card's top rule stays on top. */
.photo-card { margin: 0 0 var(--space-3); }

/* Credit line under each photo. Small and quiet; it is attribution, not a caption. */
.photo-credit { margin-top: var(--space-2); font-size: 12px; line-height: 1.4; color: var(--color-neutral-600); }
.photo-credit a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.photo-credit a:hover { color: var(--color-text); }

@media (max-width: 600px) {
  .photo, .photo-hero { margin-top: var(--leading); }
}
@media print {
  .photo { break-inside: avoid; }
  .photo-credit a { text-decoration: none; }
}

/* Photo credits, listed once per page at the foot of the footer. */
.photo-credits { margin: var(--space-3) 0 0; font-size: 11px; line-height: 1.5; color: var(--color-neutral-600); }
.photo-credits a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.photo-credits a:hover { color: var(--color-text); }
