/* Roizin Refinery — mail-in site.
   Colour, type and spacing come from brand.css. Nothing here retypes a token:
   a second copy of a hex value is how two surfaces silently drift apart. */

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

:root {
  /* Layout only. Every colour and face is inherited from brand.css. */
  --gut: clamp(20px, 5vw, 56px);
  --measure: 62ch;
  --wrap: 1180px;
  --rule: 1px solid var(--rz-aluminium-light);
  --ease: cubic-bezier(.16, 1, .3, 1);

  /* The house curve. The same cubic-bezier drives every entrance on the other
     Roizin-adjacent sites, so motion here reads as the same hand. Interactive
     state changes keep --ease; entrances use this. */
  --ease-house: cubic-bezier(0.22, 1, 0.36, 1);

  /* Two tints derived for surfaces that must sit *on* paper without becoming
     a second ground. Both are the token colours at low alpha, never new hues. */
  --tint-ink: rgba(26, 20, 19, .045);
  --tint-ox:  rgba(150, 25, 28, .07);
}

/* ---------- Web-only token overrides ----------

   These override --rz-size-* and --rz-aluminium, and add the three material
   colours, for this site and ONLY this site.

   They are deliberately NOT edited in css/brand.css, because that file is the
   shared token sheet: Marketing/design/brand/templates/invoice.html,
   letterhead.html and business-card.html import the same values. Those are
   print surfaces at a fixed physical size — an invoice is read at 300mm, a
   business card at 85mm, and neither wants a 19px body. Raising the token
   would silently resize every printed invoice and every card in the next
   order. A screen read at arm's length wants more; paper does not. So the
   scale forks here, downstream of the tokens, where only the web can see it.

   The same logic now applies to colour. --rz-aluminium at #8C8F92 measures
   2.94:1 against --rz-paper — well under the 4.5:1 AA floor for normal text —
   and it is what .benefit p, .flow p, .steps p, .deflist dd, .muted, .label,
   the footer links and .field__hint (css/quote.css, which loads this sheet
   too) all render with. Darkening the token in brand.css would darken every
   printed invoice and business card along with it, which is not the print
   surfaces' problem to inherit. #66696C keeps the aluminium hue and forks it
   here instead: 5.00:1 on bare paper, an 11% margin over the 4.5:1 floor, and
   still clearly lighter than --rz-ink (16.5:1) so the secondary/primary text
   hierarchy holds.

   There were nine --rz-web-<metal>-<stop> material colours here too, read by
   js/backdrop.js. The backdrop was removed 2026-08-31 and they went with it;
   nothing else on the site ever used them. If a surface needs gold, silver or
   platinum again, it forks here for the same reason the sizes do, and not in
   brand.css, which invoice.html, letterhead.html and business-card.html share.

   Keep this block the single place the web deviates. A one-off font-size or
   colour on a component is how the two scales drift back apart. */
:root {
  --rz-size-body: 19px;      /* was 16px */
  --rz-size-heading: 30px;   /* h3 — was 26px */
  --rz-size-subhead: 21px;   /* h4, .steps h3 — was 18px */
  --rz-size-label: 12px;     /* .label — was 11px */
  --rz-size-data: 17px;      /* was 15px */
  --rz-aluminium: #66696C;   /* was #8C8F92 — 2.94:1 on paper, now 5.00:1 */
}

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

/* The paper ground lives on html, not body, and body is transparent below.
   That split was originally what let a z-index:-1 canvas sit between the two;
   the canvas is gone, but the arrangement is harmless and moving the ground
   back onto body would change what a full-height page paints when content is
   shorter than the viewport. Left as it is deliberately. */
html { background: var(--rz-paper); }

body {
  margin: 0;
  background: transparent;
  color: var(--rz-ink);
  font-family: var(--rz-font-text);
  font-size: var(--rz-size-body);
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---------- Rhythm ---------- */

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gut); }
.wrap-narrow { max-width: 760px; }
section { padding-block: clamp(56px, 9vw, 112px); }
.rule-top { border-top: var(--rule); }

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

h1, h2, h3, h4 {
  font-family: var(--rz-font-display);
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: -.015em;
  margin: 0 0 var(--rz-space-md);
  text-wrap: balance;
}
h1 { font-size: clamp(46px, 32.10px + 3.564vw, 82px); letter-spacing: -.025em; }
h2 { font-size: clamp(32px, 25.05px + 1.782vw, 50px); }
h3 { font-size: var(--rz-size-heading); }
h4 { font-size: var(--rz-size-subhead); }

p { margin: 0 0 var(--rz-space-md); max-width: var(--measure); }
.lede { font-size: clamp(21px, 19.07px + 0.495vw, 26px); line-height: 1.55; color: var(--rz-ink); }
.muted { color: var(--rz-aluminium); }
.small { font-size: 17px; line-height: 1.55; }

/* The one small-caps label style. Mono, tracked, aluminium — it marks a section
   without spending the accent colour on it. */
.label {
  font-family: var(--rz-font-data);
  font-size: var(--rz-size-label);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--rz-aluminium);
  margin: 0 0 var(--rz-space-sm);
  display: block;
}

/* Figures must line up in a column or they get misread. brand.css defines
   .rz-data / .rz-money / .rz-weight; this is the display-size variant. */
.figure {
  font-family: var(--rz-font-data);
  font-variant-numeric: tabular-nums;
  font-size: clamp(34px, 27.82px + 1.584vw, 50px);
  letter-spacing: -.02em;
  line-height: 1;
}

a { color: inherit; }
a:not([class]) {
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
  text-decoration-color: var(--rz-aluminium-light);
  transition: text-decoration-color .25s var(--ease);
}
a:not([class]):hover { text-decoration-color: var(--rz-oxblood); }

/* Focus is never removed, only restyled. Keyboard is the whole funnel's
   fallback and it has to stay visible on every ground. */
:focus-visible {
  outline: 2px solid var(--rz-oxblood);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---------- Skip link ---------- */

.skip {
  position: absolute; left: -9999px;
  background: var(--rz-oxblood); color: #fff;
  padding: 10px 18px; border-radius: var(--rz-radius-pill);
  z-index: 200; font-size: 16px;
}
.skip:focus { left: var(--gut); top: 12px; }

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

.masthead {
  position: sticky; top: 0; z-index: 60;
  background: color-mix(in srgb, var(--rz-paper) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(14px);
  border-bottom: var(--rule);
}
.masthead .wrap { display: flex; align-items: center; justify-content: space-between; gap: var(--rz-space-md); min-height: 70px; }
.masthead__logo { display: flex; align-items: center; }
/* Brand minimum is 140px for the lockup — below that use the symbol. */
.masthead__logo img { height: 30px; width: auto; display: block; }

.nav { display: flex; align-items: center; gap: clamp(14px, 2.2vw, 30px); }
.nav a {
  font-size: 16px; text-decoration: none; color: var(--rz-ink);
  position: relative; padding-block: 4px;
}
.nav a::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 1px; width: 0;
  background: var(--rz-oxblood); transition: width .32s var(--ease);
}
.nav a:hover::after, .nav a[aria-current="page"]::after { width: 100%; }
.nav a[aria-current="page"] { color: var(--rz-oxblood); }
@media (max-width: 780px) { .nav .nav__hide { display: none; } }

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

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  font-family: var(--rz-font-text); font-size: 17px; font-weight: 500;
  padding: 13px 26px; border-radius: var(--rz-radius-pill);
  border: 1px solid transparent; cursor: pointer; text-decoration: none;
  transition: background-color .25s var(--ease), color .25s var(--ease),
              border-color .25s var(--ease), transform .25s var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--rz-oxblood); color: #fff; }
.btn--primary:hover { background: color-mix(in srgb, var(--rz-oxblood) 86%, #000); }
.btn--ghost { border-color: var(--rz-aluminium-light); color: var(--rz-ink); background: transparent; }
.btn--ghost:hover { border-color: var(--rz-ink); }
.btn[disabled], .btn[aria-disabled="true"] {
  background: var(--rz-aluminium-light); color: color-mix(in srgb, var(--rz-ink) 45%, transparent);
  border-color: transparent; cursor: not-allowed; pointer-events: none;
}
.btn--lg { padding: 17px 34px; font-size: 18px; }
/* The two hero buttons sit in one <p>, separated by an inline margin in the
   markup. At the new type scale the pair no longer fitted a 390px line, and a
   wrapped second button inherited that margin as a stray 10px indent under the
   first. Trimming the large button on a phone keeps them on one line, which is
   also the better mobile layout. */
@media (max-width: 460px) { .btn--lg { padding: 15px 24px; font-size: 17px; } }

/* A row of secondary links that has to wrap. The two hero buttons above sit in
   one <p> separated by a hardcoded margin-left, which is fine for two and falls
   apart at four — the comment above records that even two --lg buttons stopped
   fitting a 390px line. So this is a real flex row with a gap instead of an
   inline margin, and the buttons in it are deliberately NOT --lg: they are
   places to go and verify us, not the thing the page is asking you to do. */
.linkrow {
  display: flex; flex-wrap: wrap; gap: var(--rz-space-sm);
  margin-top: var(--rz-space-md);
}
.linkrow .btn { font-size: 16px; padding: 10px 20px; }

/* ---------- The bar scrub ---------- */

/* Frames carry alpha (tools/key-frames.mjs), so the bar composites straight
   onto the paper ground. It has to be alpha rather than a matching stage
   colour: the generated backgrounds differ per metal and platinum's drifts
   218–229 across the rotation, which would show as a pulsing rectangle. */
.scrub {
  position: relative;
  /* Opaque, and still load-bearing after the backdrop was removed: the frames
     carry alpha, so the bar composites onto whatever is behind it and this is
     what that is. It has to be the paper token exactly — see the note above
     about platinum's generated background drifting 218–229 across the
     rotation. */
  background: var(--rz-paper);
}
.scrub__sticky {
  position: sticky; top: 0; height: 100vh;
  display: grid; place-items: center; overflow: hidden;
}
.scrub__canvas { width: min(52vw, 460px); height: min(52vw, 460px); display: block; }
/* An author `display` on the canvas/img outranks the UA's [hidden] rule, so the
   static fallback rendered *underneath* the live canvas — two bars, stacked.
   Author-level and !important, or `hidden` silently does nothing. */
[hidden] { display: none !important; }
.scrub__glow {
  position: absolute; inset: 0; margin: auto;
  width: 46%; height: 46%; border-radius: 50%;
  background: radial-gradient(closest-side, var(--tint-ox), transparent 70%);
  filter: blur(26px); z-index: 0; pointer-events: none;
}
.scrub__panel {
  position: absolute; top: 50%; transform: translateY(-50%) translateX(-22px);
  width: min(34vw, 380px); opacity: 0; z-index: 2;
  transition: opacity .55s var(--ease), transform .6s var(--ease);
}
.scrub__panel.is-on { opacity: 1; transform: translateY(-50%) translateX(0); }
.scrub__panel--left  { left: max(20px, 4vw); }
.scrub__panel--right { right: max(20px, 4vw); transform: translateY(-50%) translateX(22px); }
.scrub__panel--right.is-on { transform: translateY(-50%) translateX(0); }

.scrub__ticks { position: absolute; left: 50%; bottom: max(22px, 4vh); transform: translateX(-50%); z-index: 3; display: flex; gap: 7px; }
.scrub__ticks span { width: 26px; height: 3px; border-radius: 2px; background: var(--rz-aluminium-light); overflow: hidden; }
.scrub__ticks span::after { content: ""; display: block; height: 100%; width: 0; background: var(--rz-oxblood); transition: width .4s ease; }
.scrub__ticks span.is-done::after { width: 100%; }
.scrub__ticks span.is-active::after { width: 50%; }

/* Stacked fallback: reduced motion, no canvas, low-power, or narrow. The layout
   has to be complete without a single frame having loaded. */
.scrub.is-static .scrub__sticky { position: relative; height: auto; padding-block: var(--rz-space-xl); }
.scrub.is-static .scrub__panel {
  position: relative; top: auto; left: auto; right: auto;
  transform: none; opacity: 1; width: 100%; max-width: 560px;
  margin: var(--rz-space-lg) auto 0;
}
.scrub.is-static .scrub__ticks { display: none; }

@media (max-width: 900px) {
  .scrub__panel { position: relative; top: auto; left: auto; right: auto; transform: none; width: min(92vw, 460px); margin-inline: auto; }
  .scrub__panel.is-on { transform: none; }
}

/* ---------- Cards, rails, tables ---------- */

.card {
  background: #fff; border: var(--rule); border-radius: var(--rz-radius-md);
  padding: clamp(20px, 3vw, 30px);
}
.card--flush { background: transparent; border: 0; padding: 0; }

.grid { display: grid; gap: var(--rz-space-lg); }
@media (min-width: 720px) { .grid--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .grid--3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 900px) { .grid--4 { grid-template-columns: repeat(4, 1fr); } }
.grid--split { gap: clamp(30px, 5vw, 72px); }
@media (min-width: 900px) { .grid--split { grid-template-columns: 1fr 1fr; align-items: center; } }

/* Numbered steps. The numeral is mono and oxblood — the accent for this
   surface, spent once. */
.steps { list-style: none; margin: 0; padding: 0; counter-reset: step; }
.steps > li { counter-increment: step; padding: var(--rz-space-md) 0; border-top: var(--rule); display: grid; grid-template-columns: 2.8rem 1fr; gap: var(--rz-space-md); }
.steps > li::before {
  content: counter(step, upper-roman);
  font-family: var(--rz-font-data); font-size: 14px; letter-spacing: .08em;
  color: var(--rz-oxblood); padding-top: .35em;
}
.steps h3 { margin-bottom: 6px; font-size: var(--rz-size-subhead); font-family: var(--rz-font-text); font-weight: 600; letter-spacing: 0; }
.steps p { margin: 0; font-size: 17px; color: var(--rz-aluminium); }

/* Grade chips — what we accept. Not prices. */
.grades { display: flex; flex-wrap: wrap; gap: 8px; padding: 0; margin: 0; list-style: none; }
.grades li {
  font-family: var(--rz-font-data); font-size: 15px; letter-spacing: .04em;
  border: var(--rule); border-radius: var(--rz-radius-sm);
  padding: 8px 14px; background: #fff;
}

.deflist { margin: 0; }
.deflist > div { display: grid; gap: 4px; padding: var(--rz-space-md) 0; border-top: var(--rule); }
@media (min-width: 700px) { .deflist > div { grid-template-columns: 17rem 1fr; gap: var(--rz-space-lg); } }
.deflist dt { font-weight: 600; font-size: 17px; }
.deflist dd { margin: 0; color: var(--rz-aluminium); font-size: 17px; }

/* ---------- Notices ---------- */

.notice {
  border-left: 2px solid var(--rz-oxblood);
  background: var(--tint-ox);
  padding: var(--rz-space-md) var(--rz-space-lg);
  border-radius: 0 var(--rz-radius-sm) var(--rz-radius-sm) 0;
  font-size: 17px;
}
.notice p:last-child { margin-bottom: 0; }
.notice--quiet { border-left-color: var(--rz-aluminium); background: var(--tint-ink); }

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

.footer { border-top: var(--rule); padding-block: var(--rz-space-xl) var(--rz-space-lg); font-size: 16px; }
.footer__cols { display: grid; gap: var(--rz-space-lg); }
@media (min-width: 760px) { .footer__cols { grid-template-columns: 1.6fr 1fr 1fr; } }
.footer a { text-decoration: none; color: var(--rz-aluminium); }
.footer a:hover { color: var(--rz-ink); }
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.footer__base { margin-top: var(--rz-space-xl); padding-top: var(--rz-space-md); border-top: var(--rule); color: var(--rz-aluminium); display: flex; flex-wrap: wrap; gap: var(--rz-space-md); justify-content: space-between; }
.footer__logo img { height: 26px; width: auto; margin-bottom: var(--rz-space-sm); }

/* ---------- Reveal ----------

   Entrances are opt-IN, not opt-out. Nothing below applies until two things
   are true at once:

     1. `html.rz-ready` is present — js/reveal.js adds it once document.fonts
        has settled (or after a 1200ms timeout, whichever comes first). Before
        that class lands every element is at its normal, visible, final state.
        No script, no class, no rule, and the page is simply complete. A
        webfont swapping in mid-transition is what makes an entrance read as a
        flash of the wrong typeface, so the gate is on fonts, not on load.

     2. The user has not asked for less motion. The whole system is nested in
        `prefers-reduced-motion: no-preference`, so under `reduce` these rules
        do not exist at all — there is no `animation: none` override to lose a
        specificity fight with, because there is nothing to override.

   Only three properties transition — opacity, transform, clip-path — all of
   them compositor-friendly. No layout property is ever animated. */

@media (prefers-reduced-motion: no-preference) {
  html.rz-ready [data-reveal] > *,
  html.rz-ready .reveal {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity .62s var(--ease-house),
                transform .62s var(--ease-house),
                clip-path .62s var(--ease-house);
  }

  /* Five variants. A long page that repeats one effect reads as a single
     tic; giving each kind of block its own direction keeps the scroll alive
     without any of them being loud. */
  html.rz-ready [data-reveal="up"]    > * { transform: translateY(22px); }
  html.rz-ready [data-reveal="left"]  > * { transform: translateX(-26px); }
  html.rz-ready [data-reveal="right"] > * { transform: translateX(26px); }

  /* The horizontal pair has to clip its own overflow, and this is not
     cosmetic. A full-width block offset 26px to the right widens the document
     by 26px, and a phone at 320px gets a horizontal scrollbar for as long as
     the block has not yet been revealed. `clip`, not `hidden`: hidden would
     make these scroll containers and break `position: sticky` on the masthead
     from anywhere inside them. `clip` on one axis leaves the other visible,
     which `hidden` does not. The clip margin is there so a focus ring on a
     control at the container's edge is not shaved off. */
  html.rz-ready [data-reveal="left"],
  html.rz-ready [data-reveal="right"] {
    overflow-x: clip;
    overflow-clip-margin: 8px;
  }
  html.rz-ready [data-reveal="scale"] > * { transform: scale(.975); transform-origin: left center; }
  html.rz-ready [data-reveal="clip"]  > * { transform: none; clip-path: inset(0 100% 0 0); }

  html.rz-ready [data-reveal].in > *,
  html.rz-ready .reveal.in,
  html.rz-ready .reveal.is-in {
    opacity: 1; transform: none; clip-path: inset(0 0 0 0);
  }

  /* 90ms apart, capped at six. Past the sixth child the eye has stopped
     counting and a linear ramp only delays the tail — everything from the
     seventh on lands together at half a second. */
  html.rz-ready [data-reveal].in > *:nth-child(1) { transition-delay: 0s; }
  html.rz-ready [data-reveal].in > *:nth-child(2) { transition-delay: .09s; }
  html.rz-ready [data-reveal].in > *:nth-child(3) { transition-delay: .18s; }
  html.rz-ready [data-reveal].in > *:nth-child(4) { transition-delay: .27s; }
  html.rz-ready [data-reveal].in > *:nth-child(5) { transition-delay: .36s; }
  html.rz-ready [data-reveal].in > *:nth-child(6) { transition-delay: .45s; }
  html.rz-ready [data-reveal].in > *:nth-child(n+7) { transition-delay: .5s; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; scroll-behavior: auto !important; }
}

/* ---------- The paper ground on text blocks ----------

   These blocks take var(--rz-paper) explicitly rather than inheriting it.

   The reason was the falling-grain backdrop: small --rz-aluminium secondary
   text clears 4.5:1 on bare paper with little to spare, and could not be
   relied on to clear it over a grain that happened to land behind a word, so
   every block carrying such text was given an opaque ground and the field was
   seen around them. The backdrop was removed 2026-08-31 and that job is gone.

   The declarations stay, because one of them is quietly doing a second job:
   .card sets `background: #fff` up in "Cards, rails, tables", and this later
   rule of equal specificity overrides it to paper. Every card on the site is
   paper-coloured because of this line, not white. Deleting the rule as dead
   backdrop scaffolding would repaint them, which is a design change and not a
   cleanup. If cards should be white, change them there and drop this rule in
   the same commit, deliberately.

   The list is the nine it always was. .label, .muted, figcaption and .diagram
   were added while the backdrop existed and are removed with it. */
.card,
.benefit,
.flow figure,
.steps,
.deflist,
.notice,
.buy figcaption,
.bench figcaption,
.footer {
  background-color: var(--rz-paper);
}

/* The blocks above are inline-sized to their text. Give them a little room so
   the paper reads as a deliberate surface rather than a tight cut-out. */
.benefit, .steps, .deflist { padding-inline: var(--rz-space-md); }
.benefit { padding-block: var(--rz-space-md) var(--rz-space-lg); }
.buy figcaption, .bench figcaption { padding: 4px 8px; border-radius: var(--rz-radius-sm); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- Benefit grid ---------- */

.benefit { padding-top: var(--rz-space-md); border-top: 2px solid var(--rz-oxblood); }
.benefit h3 {
  font-family: var(--rz-font-text); font-weight: 600; font-size: 19px;
  letter-spacing: 0; margin: 0 0 8px;
}
.benefit p { font-size: 17px; color: var(--rz-aluminium); margin: 0; text-wrap: pretty; }

/* ---------- What we buy ---------- */

/* minmax(0,1fr), not 1fr: a bare 1fr track floors at the content's min-content
   width, and these images are intrinsically 1100px wide. */
.buy { display: grid; gap: var(--rz-space-md); grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 640px) { .buy { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 980px) { .buy { grid-template-columns: repeat(5, minmax(0, 1fr)); } }

/* The five-across grid is for the homepage "what we buy" row. The per-page
   rows carry one or two images, and dropping those into a five-column track
   left them stranded at 198px in the first two columns with 60% of the row
   empty. These size to their content instead. */
.buy--few { grid-template-columns: repeat(auto-fit, minmax(220px, 320px)); justify-content: start; gap: var(--rz-space-lg); }
@media (min-width: 640px) { .buy--few { grid-template-columns: repeat(auto-fit, minmax(260px, 340px)); } }

.buy figure { margin: 0; text-align: center; }
/* Photos are alpha-keyed (tools/prep-photos.mjs) so they sit straight on the
   paper ground. A white card behind them would reintroduce the rectangle the
   keying exists to remove. */
.buy img {
  /* height:auto is load-bearing. The width/height attributes are on the tag to
     reserve layout space, and a specified height beats aspect-ratio — without
     this every image rendered at its intrinsic 1100px instead of filling its
     ~220px cell. */
  width: 100%; height: auto; aspect-ratio: 1; object-fit: contain; display: block;
  mix-blend-mode: multiply;
}
.buy figcaption {
  font-family: var(--rz-font-data); font-size: 13px; letter-spacing: .05em;
  text-transform: uppercase; color: var(--rz-aluminium); margin-top: 7px;
}

/* ---------- Process strip with imagery ---------- */

.flow { display: grid; gap: var(--rz-space-lg); }
@media (min-width: 760px) { .flow { grid-template-columns: repeat(3, 1fr); } }
.flow figure { margin: 0; }
.flow img { width: 100%; height: auto; max-width: 220px; aspect-ratio: 1; object-fit: contain; display: block; margin-inline: auto; mix-blend-mode: multiply; }
.flow h3 { font-family: var(--rz-font-text); font-weight: 600; font-size: 19px; letter-spacing: 0; margin: var(--rz-space-md) 0 7px; }
.flow p { font-size: 17px; color: var(--rz-aluminium); margin: 0; text-wrap: pretty; }

/* ---------- The bench (real photograph) ---------- */

.bench img {
  width: 100%; height: auto; border-radius: var(--rz-radius-md); display: block;
  border: var(--rule);
}
.bench figcaption { font-size: 15px; color: var(--rz-aluminium); margin-top: 11px; text-wrap: pretty; }

/* ---------- Stat row ---------- */

.stats { display: grid; gap: var(--rz-space-lg); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 760px) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stats dt {
  font-family: var(--rz-font-data); font-variant-numeric: tabular-nums;
  font-size: clamp(27px, 23.53px + 0.891vw, 36px); letter-spacing: -.02em; color: var(--rz-ink);
}
.stats dd {
  margin: 7px 0 0; font-size: 14px; color: var(--rz-aluminium);
  letter-spacing: .04em; text-transform: uppercase; font-family: var(--rz-font-data);
}

/* ---------- Diagrams ----------
   Hand-authored inline SVG. There was no SVG styling and no <svg> anywhere on
   this site before, so this is the whole component.

   NEVER nest a .diagram inside .buy or .flow: both set
   `mix-blend-mode: multiply` on their images, which is correct for the
   alpha-keyed photographs sitting on the paper ground and would eat an inline
   SVG's whites. This container deliberately sets none. */
.diagram { margin: 0; }
.diagram svg {
  display: block;
  width: 100%;
  max-width: 760px;
  height: auto;                 /* with viewBox, this is what keeps it responsive */
  margin-inline: auto;
  overflow: visible;
}
.diagram figcaption {
  font-family: var(--rz-font-data);
  font-size: 12px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--rz-aluminium);
  text-align: center;
  margin-top: var(--rz-space-sm);
}

/* Stroke and fill conventions, so twelve diagrams drawn separately read as one
   set. Bind to tokens — never a literal hex inside an SVG. */
.diagram .d-line   { stroke: var(--rz-aluminium-light); stroke-width: 1.5; fill: none; }
.diagram .d-rule   { stroke: var(--rz-aluminium); stroke-width: 1; fill: none; }
.diagram .d-node   { stroke: var(--rz-ink); stroke-width: 1.5; fill: var(--rz-paper); }
.diagram .d-accent { stroke: var(--rz-oxblood); stroke-width: 2; fill: none; }
.diagram .d-fill   { fill: var(--rz-oxblood); }
.diagram .d-dim    { fill: var(--rz-aluminium-light); stroke: none; }
.diagram .d-label  { font-family: var(--rz-font-text); font-size: 13px; fill: var(--rz-ink); }
.diagram .d-sub    { font-family: var(--rz-font-text); font-size: 12px; fill: var(--rz-aluminium); }
.diagram .d-num    { font-family: var(--rz-font-data); font-size: 12px; fill: var(--rz-oxblood); letter-spacing: .06em; }
.diagram .d-strike { stroke: var(--rz-aluminium); stroke-width: 1.5; }

@media (max-width: 560px) {
  .diagram .d-label { font-size: 12px; }
  .diagram .d-sub, .diagram .d-num { font-size: 11px; }
}

/* ---------- Four-across process strip ----------
   .flow is three columns; the homepage strip gains a fourth node so the
   graphic stops contradicting its own heading, which says "Four steps". */
@media (min-width: 760px) {
  .flow--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1040px) {
  .flow--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.flow--4 img { max-width: 170px; }
