/* Otto — generated by build.mjs from src/styles/. Do not edit public/styles/otto.css. */

/* ========================================================================
   01-tokens.css
   ======================================================================== */

/* ============================================================================
   TOKENS — the single place brand values are defined.
   Change a value here and it changes everywhere on the site.
   Nothing below this file should contain a raw hex colour or a magic px value
   that belongs to the brand rather than to one component's geometry.
   ============================================================================ */

:root {
  /* --- palette (identity system v1 names) --------------------------------- */
  --otto-green: #2c6a55;         /* "Seal green" — the ONLY accent */
  --otto-green-deep: #1f4d3e;    /* pressed / deep fills */
  --otto-green-tint: #dde7e1;    /* selected row, soft highlight */
  --otto-green-veil: rgba(44, 106, 85, .18);
  --otto-green-edge: rgba(44, 106, 85, .4);

  --otto-ink: #1d2320;           /* "Ink" — headlines, max contrast */
  --otto-grey-body: #4d534e;     /* paragraphs */
  --otto-grey-muted: #606861;    /* "Slate" — nav links, captions */
  --otto-grey-faint: #8b918a;    /* metadata */
  --otto-grey-fainter: #a8aca6;  /* icon strokes, disabled */
  --otto-grey-inactive: #8a9089; /* the "old way" progress fill */
  --otto-grey-panel: #5f665f;    /* labels inside the "old way" panel */
  --otto-grey-panel-head: #6b716c;

  --otto-paper: #f8f6f0;         /* "Letter cream" — page ground */
  --otto-paper-alt: #eceae2;     /* "Envelope" — tinted bands, cards on paper */
  --otto-paper-chrome: #f2f0ea;  /* mail-mock chrome bars */
  --otto-card: #fdfdfa;          /* raised card white */

  /* Copy on the green ground — see .band--accent. Cream at three strengths
     rather than three flat colours, so they hold up if the green ever moves. */
  --otto-paper-strong: rgba(248, 246, 240, .82);   /* body copy */
  --otto-paper-soft: rgba(248, 246, 240, .62);     /* labels, metadata */
  --otto-paper-hairline: rgba(248, 246, 240, .22);

  --otto-hairline: rgba(29, 35, 32, .12);
  --otto-hairline-card: rgba(29, 35, 32, .14);
  --otto-hairline-divider: rgba(29, 35, 32, .16);
  --otto-hairline-strong: rgba(29, 35, 32, .28);

  /* --- semantic aliases — prefer these in component CSS ------------------- */
  --surface-page: var(--otto-paper);
  --surface-band: var(--otto-paper-alt);
  --surface-accent: var(--otto-green);
  --surface-card: var(--otto-card);
  --surface-card-on-tint: var(--otto-paper);

  --text-heading: var(--otto-ink);
  --text-body: var(--otto-grey-body);
  --text-muted: var(--otto-grey-muted);
  --text-faint: var(--otto-grey-faint);
  --text-accent: var(--otto-green);
  --text-on-accent: var(--otto-paper);

  --border-hairline: 1px solid var(--otto-hairline);
  --border-card: 1px solid var(--otto-hairline-card);
  --border-divider: 1px solid var(--otto-hairline-divider);
  --rule-accent: var(--otto-green);

  --action-bg: var(--otto-green);
  --action-fg: var(--otto-paper);
  --action-hover-bg: var(--otto-ink);
  --action-secondary-border: var(--otto-hairline-strong);

  /* --- type: three families, never a fourth ------------------------------ */
  --font-serif: 'EB Garamond', Georgia, serif;            /* display + headings */
  --font-sans: Archivo, Helvetica, Arial, sans-serif;     /* body + UI */
  --font-mono: 'IBM Plex Mono', ui-monospace, monospace;  /* labels, CTAs, meta */

  --type-h1-size: 56px;          /* 40px under 820px */
  --type-h1-line: 1.04;
  --type-h1-track: -.02em;
  --type-hero-size: 68px;        /* landing hero only; 44px under 820px */
  --type-h2-size: 38px;          /* 30px under 820px */
  --type-h2-line: 1.1;
  --type-h2-track: -.02em;
  --type-h2-lg-size: 56px;       /* centred band title */
  --type-h2-band-size: 48px;     /* title inside a tinted band */
  --type-h3-size: 24px;          /* card headings, list statements */
  --type-h3-line: 1.15;
  --type-lead-size: 26px;
  --type-lead-line: 1.32;
  --type-pull-size: 30px;        /* serif emphasis line inside prose */
  --type-claim-size: 38px;       /* serif statement in a rule-list row */

  --type-body-size: 17px;
  --type-body-line: 1.7;
  --type-body-sm-size: 16px;
  --type-body-sm-line: 1.6;
  --type-caption-size: 15px;
  --type-caption-line: 1.6;

  --type-label-size: 11px;
  --type-label-track: .14em;
  --type-eyebrow-track: .18em;
  --type-cta-size: 12px;
  --type-cta-track: .14em;
  --wordmark-track: .28em;   /* the gap between the disc and "TTO" */

  /* --- space ------------------------------------------------------------- */
  /* Page gutter: centres a 1100px column, 56px minimum, 20px on mobile. */
  --g: max(56px, calc((100vw - 1100px) / 2));

  --measure-read: 720px;   /* long-form reading column */
  --measure-page: 1100px;  /* full-width band content */
  --measure-line: 820px;   /* substantiation copy inside wide rows */

  --space-1: 8px;
  --space-2: 12px;
  --space-3: 14px;
  --space-4: 16px;
  --space-5: 22px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 52px;    /* gap between long-form blocks */
  --space-9: 56px;

  --section-pad-top: 88px;
  --section-pad-bottom: 104px;
  --section-pad-band: 96px;    /* symmetrical full-width band */
  --section-pad-mobile: 48px;

  --card-pad: 26px 24px;
  --card-pad-lg: 34px 32px;
  --panel-pad: 52px 48px;

  --radius: 0px;               /* Otto has no rounded corners. Ever. */
  --breakpoint-mobile: 820px;

  /* --- motion ------------------------------------------------------------ */
  --ease-otto: cubic-bezier(.2, .8, .25, 1);
  --ease-wipe: cubic-bezier(.2, .8, .2, 1);
  --dur-entrance: .7s;
  --dur-hover: .22s;
  --dur-cta-wipe: .5s;
  --stagger: 120ms;
  --loop: 9s;                  /* the ambient comparison loop */
}

@media (max-width: 820px) {
  :root {
    --g: 20px;
    --type-h1-size: 40px;
    --type-hero-size: 44px;
    --type-h2-size: 30px;
    --type-h2-lg-size: 40px;
    --type-h2-band-size: 34px;
    --type-claim-size: 28px;
  }
}


/* ========================================================================
   02-base.css
   ======================================================================== */

/* ============================================================================
   BASE — element defaults. A page with no classes at all should already look
   like Otto: cream paper, Archivo body, serif headings, square corners.
   ============================================================================ */

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--surface-page);
  color: var(--text-heading);
  font-family: var(--font-sans);
  font-size: var(--type-body-size);
  line-height: var(--type-body-line);
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
}

/* The page's own sections sit here; nav is above it and the footer below. */
main { flex: 1; }

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 400; /* never bold a serif heading */
  color: var(--text-heading);
  text-wrap: pretty;
}

h1 { font-size: var(--type-h1-size); line-height: var(--type-h1-line); letter-spacing: var(--type-h1-track); }
h2 { font-size: var(--type-h2-size); line-height: var(--type-h2-line); letter-spacing: var(--type-h2-track); }
h3 { font-size: var(--type-h3-size); line-height: var(--type-h3-line); }

p { margin: 0; color: var(--text-body); }

/* Bulleted copy reads as body copy that happens to be enumerated: same size,
   same colour, hanging markers so the text still lines up with the paragraph. */
ul, ol { margin: 0; padding-left: 20px; color: var(--text-body); }
li + li { margin-top: 6px; }
li::marker { color: var(--text-faint); }

a {
  color: var(--text-accent);
  text-decoration: none;
  transition: color var(--dur-hover) ease;
}
a:hover { color: var(--otto-ink); }

img, svg, video { max-width: 100%; }
img { height: auto; }

hr {
  border: 0;
  border-top: var(--border-divider);
  margin: 0;
}

::selection { background: var(--otto-green); color: var(--otto-paper); }

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

[hidden] { display: none !important; }

/* --- scroll reveal ---------------------------------------------------------
   Put data-reveal on any block; scripts/otto.js adds .is-in when it scrolls
   into view. Stagger siblings with style="--d:.12s".
   -------------------------------------------------------------------------- */
[data-reveal] { opacity: 0; }
[data-reveal].is-in { animation: ottoOpenCard var(--dur-entrance) var(--ease-otto) var(--d, 0s) both; }

/* Nothing decorative may be load-bearing. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  [data-reveal] { opacity: 1 !important; animation: none !important; }
  *, *::before, *::after {
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}


/* ========================================================================
   03-motion.css
   ======================================================================== */

/* ============================================================================
   MOTION — the shared keyframe library. Two kinds of motion only:
   (1) entrance, a 14px rise plus fade, fired once by the scroll observer;
   (2) ambient loops that make an argument (the stall vs. advance comparison).
   No scroll-jacking, no parallax. prefers-reduced-motion kills all of it.
   ============================================================================ */

/* --- entrance ------------------------------------------------------------- */
@keyframes ottoOpenCard {
  0%   { opacity: 0; transform: translateY(14px) scale(.985); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes ottoOpenLine {
  0%   { opacity: 0; transform: translateY(8px); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes ottoReplyIn {
  0%   { opacity: 0; transform: translateX(-4px); }
  100% { opacity: 1; transform: translateX(0); }
}
/* The message unfolds out of the notification rather than arriving separately:
   the card is clipped down to the notification's own band, then opens from
   there. --clip-from is that closed band, set per breakpoint so it lands on
   the row (centred on desktop, at the top on mobile). */
@keyframes ottoCardUnfold {
  0%   { opacity: 0; clip-path: var(--clip-from); }
  1%   { opacity: 1; }
  100% { opacity: 1; clip-path: inset(0 round var(--mock-radius)); }
}

/* --- inbox sequence (the hero) -------------------------------------------- */
@keyframes ottoRowInTop {
  0%   { opacity: 0; transform: scale(0); }
  60%  { opacity: 1; }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes ottoRowClick {
  0%, 58%   { background: var(--otto-card); }
  64%, 76%  { background: var(--otto-green-tint); }
  82%, 100% { background: var(--otto-card); }
}
/* The notification does not collapse or slide away — it dissolves in place
   while the card grows out from underneath it, so the two read as one move. */
@keyframes ottoRowDissolve {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes ottoUnfoldFields {
  0%   { max-height: 0; opacity: 0; }
  40%  { opacity: 1; }
  100% { max-height: 130px; opacity: 1; }
}
@keyframes ottoUnfoldBody {
  0%   { max-height: 0; opacity: 0; }
  35%  { opacity: 1; }
  100% { max-height: 340px; opacity: 1; }
}

/* --- old way vs Otto way comparison band ---------------------------------- */
@keyframes ottoStall {
  0%   { width: 4%; }
  20%  { width: 7%; }
  26%  { width: 7%; }
  42%  { width: 17%; }
  62%  { width: 17%; }
  76%  { width: 23%; }
  100% { width: 23%; }
}
@keyframes ottoAdvance {
  0%   { width: 0%; }
  18%  { width: 34%; }
  30%  { width: 34%; }
  48%  { width: 68%; }
  60%  { width: 68%; }
  78%, 100% { width: 100%; }
}
@keyframes ottoStep1 { 0%, 10% { opacity: .72; } 18%, 100% { opacity: 1; } }
@keyframes ottoStep2 { 0%, 40% { opacity: .72; } 48%, 100% { opacity: 1; } }
@keyframes ottoStep3 { 0%, 70% { opacity: .72; } 78%, 100% { opacity: 1; } }
@keyframes ottoLand {
  0%, 72%   { opacity: 0; transform: translateY(4px); }
  82%, 100% { opacity: 1; transform: translateY(0); }
}
@keyframes ottoWait { 0%, 100% { opacity: .42; } 50% { opacity: 1; } }
@keyframes ottoPhase2 { 0%, 25.9% { opacity: 1; } 26%, 99.9% { opacity: 0; } 100% { opacity: 1; } }
@keyframes ottoPhase3 { 0%, 25.9% { opacity: 0; } 26%, 61.9% { opacity: 1; } 62%, 100% { opacity: 0; } }
@keyframes ottoPhase4 { 0%, 61.9% { opacity: 0; } 62%, 99.9% { opacity: 1; } 100% { opacity: 0; } }

/* --- ambient accents ------------------------------------------------------ */
@keyframes ottoBreathe { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
@keyframes ottoBlink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes ottoFlicker {
  0%, 92%, 100% { opacity: .9; }
  93% { opacity: .35; }
  95% { opacity: .95; }
  96% { opacity: .5; }
}
@keyframes ottoDash { to { background-position: 60px 0; } }
@keyframes ottoSpin { to { transform: rotate(360deg); } }


/* ========================================================================
   04-layout.css
   ======================================================================== */

/* ============================================================================
   LAYOUT — bands, columns, and the gutter system.

   Every full-width section is a .band. A band owns the page gutter (--g), so
   its content lines up with the nav and footer automatically. Bands that go
   edge to edge (the hero, the comparison) hand the gutter to their inner
   columns instead — see .bleed.
   ============================================================================ */

/* --- band ----------------------------------------------------------------- */
.band {
  padding: var(--section-pad-top) var(--g) var(--section-pad-bottom);
}

.band--even    { padding-block: var(--section-pad-band); }         /* symmetrical rhythm */
.band--tight   { padding-block: 76px; }
.band--tint    { background: var(--surface-band); }

/* The one band that inverts: cream on green, for the masthead of a page
   addressed to one person. It remaps the text tokens for its own subtree
   rather than restyling anything, so an eyebrow, a heading and a lead dropped
   inside it all follow with no --accent variant of each. Still the strongest
   thing on a page, and still counted against the two-bands-of-colour ceiling —
   a page with this has one more band of colour left, not two. */
.band--accent {
  background: var(--surface-accent);
  color: var(--otto-paper);
  --text-heading: var(--otto-paper);
  --text-body: var(--otto-paper-strong);
  --text-muted: var(--otto-paper-soft);
  --text-faint: var(--otto-paper-soft);
  --text-accent: var(--otto-paper-soft);
  --rule-accent: var(--otto-paper);
  --border-hairline: 1px solid var(--otto-paper-hairline);
  --border-divider: 1px solid var(--otto-paper-hairline);
}
/* The page-wide hover colour is ink, which is unreadable here. */
.band--accent a:hover { color: var(--otto-paper); }
.band--rule-top    { border-top: var(--border-hairline); }
.band--rule-bottom { border-bottom: var(--border-hairline); }
.band--edge-bottom { border-bottom: 2px solid var(--rule-accent); }

/* Full-bleed band: no gutter of its own, columns take it (see .bleed__col). */
.bleed { padding: 0; }
.bleed__col       { padding-inline: var(--g); }
.bleed__col--left  { padding-left: var(--g); }
.bleed__col--right { padding-right: var(--g); }

/* --- reading column ------------------------------------------------------- */
/* Long-form prose: 720px, 52px between blocks. Use for article pages. */
.prose {
  width: 100%;
  max-width: var(--measure-read);
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}

/* --- generic stacks and rows ---------------------------------------------- */
/* Override the gap inline where a pattern needs a specific one:
   <div class="stack" style="--gap:56px">                                      */
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--gap, var(--space-6));
}
.stack--xs { --gap: var(--space-1); }
.stack--sm { --gap: var(--space-3); }
.stack--md { --gap: var(--space-6); }
.stack--lg { --gap: var(--space-7); }
.stack--xl { --gap: var(--space-9); }

.row {
  display: flex;
  align-items: center;
  gap: var(--gap, var(--space-2));
  flex-wrap: wrap;
}

/* --- grids ---------------------------------------------------------------- */
.grid-2,
.grid-3 {
  display: grid;
  gap: var(--gap, var(--space-6));
}
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-full { grid-column: 1 / -1; }

@media (max-width: 820px) {
  .band { padding-block: var(--section-pad-mobile); }
  .band--tight { padding-block: 44px; }
  .bleed { padding: 0; }
  .bleed__col,
  .bleed__col--left,
  .bleed__col--right { padding-inline: var(--g); }
  .grid-2,
  .grid-3 { grid-template-columns: 1fr; }
}


/* ========================================================================
   05-components.css
   ======================================================================== */

/* ============================================================================
   COMPONENTS — every reusable piece of the Otto site.
   See /styleguide for a rendered copy of all of them.
   ============================================================================ */

/* --- logo lockup ---------------------------------------------------------- */
.logo {
  display: flex;
  align-items: center;
  gap: 1px;
  flex: none;
  color: var(--otto-green);
}
.logo:hover { color: var(--otto-green); }
.logo__mark {
  display: block;
  flex: none;
  width: var(--logo-size, 30px);
  height: var(--logo-size, 30px);
  transition: transform .8s cubic-bezier(.2, .75, .2, 1);
}
.logo:hover .logo__mark { transform: rotate(360deg); }
.logo__word {
  font-family: var(--font-serif);
  font-size: var(--logo-word-size, 24px);
  letter-spacing: var(--wordmark-track);
  text-indent: var(--wordmark-track);
  margin-right: calc(-1 * var(--wordmark-track));
  line-height: 1;
}
.logo--sm,
.site-footer .logo { --logo-size: 25px; --logo-word-size: 20px; }

/* --- nav ------------------------------------------------------------------ */
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 24px var(--g);
  border-bottom: var(--border-hairline);
  background: var(--surface-page);
}
.nav__links {
  display: flex;
  align-items: center;
  gap: var(--space-7);
  font-family: var(--font-mono);
  font-size: var(--type-label-size);
  letter-spacing: var(--type-label-track);
  text-transform: uppercase;
}
.nav__links a:not(.btn) { color: var(--text-muted); }

.nav__burger {
  display: none;
  flex-direction: column;
  gap: 5px;
  padding: 6px 2px;
  cursor: pointer;
  background: none;
  border: 0;
}
.nav__burger span {
  display: block;
  width: 22px;
  height: 1.5px;
  background: var(--otto-ink);
}

.nav-menu {
  display: none;
  padding: 18px var(--g) 24px;
  border-bottom: var(--border-hairline);
  background: var(--surface-page);
  flex-direction: column;
  gap: 18px;
  font-family: var(--font-mono);
  font-size: var(--type-cta-size);
  letter-spacing: var(--type-label-track);
  text-transform: uppercase;
}
.nav-menu a:not(.btn) { color: var(--text-muted); }
.nav-menu .btn { align-self: flex-start; }

/* --- buttons -------------------------------------------------------------- */
/* One accent, square corners, mono label. The fill wipes out from the centre. */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  isolation: isolate;
  overflow: hidden;
  padding: 18px 30px;
  border: 1px solid transparent;
  background: var(--action-bg);
  color: var(--action-fg);
  font-family: var(--font-mono);
  font-size: var(--type-label-size);
  letter-spacing: .16em;
  text-transform: uppercase;
  line-height: 1.2;
  cursor: pointer;
  transition: color .3s ease .05s, border-color .3s ease;
}
.btn::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 50%;
  /* The disc has to clear the button's diagonal, and a button can be as wide as
     the column it sits in — so size it off the button, not a fixed px. 150% of
     the width covers anything wider than it is tall, which is every button. */
  width: 150%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--action-hover-bg);
  transform: translate(-50%, -50%) scale(0);
  transition: transform var(--dur-cta-wipe) var(--ease-wipe);
}
.btn:hover::before { transform: translate(-50%, -50%) scale(1); }
.btn:hover { color: var(--action-fg); border-color: var(--action-hover-bg); }
.btn:active { transform: scale(.97); }

.btn--secondary {
  background: transparent;
  border-color: var(--action-secondary-border);
  color: var(--text-heading);
}
.btn--secondary:hover { color: var(--action-fg); }

.btn--sm { padding: 10px 18px; letter-spacing: var(--type-label-track); }
.btn--lg { padding: 20px 34px; letter-spacing: var(--type-eyebrow-track); }

@media (prefers-reduced-motion: reduce) {
  .logo:hover .logo__mark,
  .member-card:hover,
  .btn:active { transform: none; }
}

/* --- text links that wipe an underline in from the left ------------------- */
.nav__links a:not(.btn),
.nav-menu a:not(.btn),
.site-footer a:not(.btn):not(.logo) { position: relative; }

.nav__links a:not(.btn)::after,
.nav-menu a:not(.btn)::after,
.site-footer a:not(.btn):not(.logo)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-hover) var(--ease-wipe);
}
.nav__links a:not(.btn):hover::after,
.nav__links a[aria-current="page"]::after,
.nav-menu a:not(.btn):hover::after,
.site-footer a:not(.btn):not(.logo):hover::after { transform: scaleX(1); }

.nav__links a:not(.btn):hover,
.nav-menu a:not(.btn):hover,
.site-footer a:not(.btn):not(.logo):hover { color: var(--otto-ink); }

/* --- labels --------------------------------------------------------------- */
/* Mono, uppercase, tracked. Never for running copy. */
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--type-label-size);
  letter-spacing: var(--type-eyebrow-track);
  text-transform: uppercase;
  color: var(--text-accent);
}
.label {
  font-family: var(--font-mono);
  font-size: var(--type-label-size);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
}
/* The one place Archivo is set as a label: panel and card roles. */
.tag {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--type-label-size);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-accent);
}
.tag--lg { font-size: var(--type-cta-size); }
.tag--muted { color: var(--otto-grey-panel); }

/* --- headings and prose voices -------------------------------------------- */
.hero-title { font-size: var(--type-hero-size); line-height: 1; letter-spacing: var(--type-h1-track); }

.lead {
  font-family: var(--font-serif);
  font-size: var(--type-lead-size);
  line-height: var(--type-lead-line);
  color: var(--text-body);
}
/* A serif line for emphasis inside prose. */
.pull {
  font-family: var(--font-serif);
  font-size: var(--type-pull-size);
  line-height: 1.3;
  letter-spacing: -.015em;
  color: var(--text-heading);
}

/* Centred section title with the 44×2 green rule under it. */
.section-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 18px;
}
.section-head > h2 { font-size: var(--type-h2-lg-size); line-height: 1.02; }
.section-head::after {
  content: "";
  width: 44px;
  height: 2px;
  background: var(--rule-accent);
}
.section-head--norule::after { display: none; }

/* A left-aligned title introducing a tinted band (e.g. "The team"). */
.band-title {
  font-size: var(--type-h2-band-size);
  line-height: 1.05;
  margin-bottom: var(--space-1);
}

/* --- rule-marked list of claims ------------------------------------------- */
.rule-list { display: flex; flex-direction: column; }
.rule-list__item {
  display: grid;
  grid-template-columns: 56px 1fr;
  gap: var(--space-6);
  padding: 30px 0;
  border-bottom: var(--border-card);
}
.rule-list__item:first-child { padding-top: 0; }
.rule-list__item:last-child { padding-bottom: 0; border-bottom: 0; }
/* The marker is static. These rows are statements, not controls — growing the
   rule on hover implied something was clickable. */
.rule-list__item::before {
  content: "";
  align-self: start;
  margin-top: 26px;
  width: 28px;
  height: 2px;
  background: var(--rule-accent);
}
.rule-list__claim {
  font-family: var(--font-serif);
  font-size: var(--type-claim-size);
  line-height: 1.08;
  letter-spacing: -.015em;
  color: var(--text-heading);
}
.rule-list__note {
  font-size: var(--type-body-sm-size);
  line-height: var(--type-body-sm-line);
  color: var(--text-muted);
  max-width: var(--measure-line);
}
.rule-list__body { display: flex; flex-direction: column; gap: var(--space-1); }

/* --- cards ---------------------------------------------------------------- */
.tint-card,
.paper-card {
  display: flex;
  flex-direction: column;
  gap: var(--gap, var(--space-3));
  border: var(--border-card);
}
.tint-card {
  background: var(--surface-band);
  padding: var(--card-pad);
  --card-title-size: var(--type-h3-size);
}
/* A card sitting on a tinted band: paper ground, roomier. */
.paper-card {
  background: var(--surface-card-on-tint);
  padding: var(--card-pad-lg);
  --gap: var(--space-4);
  --card-title-size: 34px;
}
.card__title {
  font-family: var(--font-serif);
  font-size: var(--card-title-size);
  line-height: 1.12;
  color: var(--text-heading);
}
.card__body {
  font-size: var(--type-body-sm-size);
  line-height: var(--type-body-sm-line);
  color: var(--text-body);
}
.tint-card .card__body { font-size: var(--type-caption-size); }

/* --- member dossier card -------------------------------------------------- */
/* A vetted member, shown without their name: a code, the role in serif, the
   metadata line, a rule, then what they did. Card white on paper — the top of
   the tint step, because these are the thing the page is about. */
.member-card {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 26px 26px 22px;
  background: var(--surface-card);
  border: var(--border-card);
  --card-title-size: 27px;
  transition: transform .3s var(--ease-wipe);
}
.member-card:hover { transform: translateY(-3px); }
.member-card__code {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: var(--type-eyebrow-track);
  text-transform: uppercase;
  color: var(--otto-grey-fainter);
}
.member-card__rule { border-top: var(--border-hairline); }
.member-card .card__body {
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-line);
  text-wrap: pretty;
}

/* --- role card ------------------------------------------------------------ */
/* One role on a member's shortlist: who the company is, the title in serif, the
   facts in mono, why we picked it, what the job actually is, then what is not
   ideal about it. Card white on paper, the same ground as .member-card, because
   the roles are the thing the page is about.

   The caveat is an envelope inset — a tint step down, not a coloured warning.
   Otto has no alert colours, and the reservation is part of the argument. */
.role-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: 34px 34px 30px;
  background: var(--surface-card);
  border: var(--border-card);
  --card-title-size: 30px;
}
.role-card__head { display: flex; flex-direction: column; gap: 10px; }
.role-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 2px var(--space-5);
  font-family: var(--font-mono);
  font-size: var(--type-cta-size);
  letter-spacing: .04em;
  line-height: 1.7;
  color: var(--text-faint);
}
.role-card__comp { color: var(--text-accent); }
.role-card__why {
  font-size: var(--type-body-sm-size);
  line-height: var(--type-body-sm-line);
  color: var(--text-body);
  max-width: var(--measure-line);
}
/* Body copy that happens to be enumerated — same voice as .role-card__why. */
.role-card__points {
  max-width: var(--measure-line);
  font-size: var(--type-body-sm-size);
  line-height: var(--type-body-sm-line);
}
.role-card__points li + li { margin-top: 10px; }

.role-card__caveat {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: var(--measure-line);
  padding: 18px 20px;
  background: var(--surface-band);
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-line);
  color: var(--text-body);
}

/* The link out to the posting. Mono like every other CTA, and a hairline that
   goes green — the same move as .link-serif, one size down. */
.role-card__jd {
  align-self: flex-start;
  font-family: var(--font-mono);
  font-size: var(--type-cta-size);
  letter-spacing: var(--type-cta-track);
  text-transform: uppercase;
  color: var(--text-accent);
  border-bottom: 1px solid var(--otto-green-edge);
  padding-bottom: 4px;
  transition: color var(--dur-hover) ease, border-bottom-color .25s ease;
}
.role-card__jd:hover { border-bottom-color: var(--otto-green); }

/* A row that dissolves downward: show a few, imply more. The mask is an alpha
   ramp, not a painted gradient — nothing on the page gains a gradient surface.
   Whatever it wraps is decoration: mark it aria-hidden, and it must be safe to
   delete. */
.fade-out {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, rgba(0, 0, 0, .35) 52%, transparent 92%);
          mask-image: linear-gradient(to bottom, #000 0%, rgba(0, 0, 0, .35) 52%, transparent 92%);
  pointer-events: none;
}

/* The CTA that sits centred over a fading row — the way out of the teaser. */
.peek { position: relative; }
.peek__cta {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  display: flex;
  justify-content: center;
}

/* A serif link that keeps a green hairline under it (team names, references). */
.link-serif {
  align-self: flex-start;
  font-family: var(--font-serif);
  font-size: var(--card-title-size, 34px);
  line-height: 1.08;
  color: var(--text-heading);
  border-bottom: 1px solid var(--otto-green-edge);
  padding-bottom: 3px;
  transition: border-bottom-color .25s ease;
}
.link-serif:hover { color: var(--text-heading); border-bottom-color: var(--otto-green); }

/* --- divided example list ------------------------------------------------- */
.divided-list { display: flex; flex-direction: column; gap: var(--space-5); }
.divided-item {
  display: flex;
  flex-direction: column;
  gap: 10px;
  border-top: var(--border-divider);
  padding-top: 18px;
}
.divided-item__statement {
  font-family: var(--font-serif);
  font-size: var(--type-h3-size);
  line-height: 1.3;
  color: var(--text-heading);
}

/* --- two-panel comparison ------------------------------------------------- */
/* The green ground shows through as the 2px seam between the panels. */
.compare {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  background: var(--otto-green);
  border-bottom: 2px solid var(--otto-green);
}
.compare__panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding: var(--panel-pad);
}
.compare__panel--old {
  background: var(--surface-band);
  padding-left: var(--g);
}
.compare__panel--otto {
  background: var(--surface-page);
  border-left: 2px solid var(--otto-green);
  padding-right: var(--g);
}
.compare__head {
  font-family: var(--font-serif);
  font-size: 40px;
  line-height: 1.08;
  white-space: nowrap;
}
.compare__panel--old .compare__head { color: var(--otto-grey-panel-head); }

/* --- numbered steps ------------------------------------------------------- */
.steps {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  font-size: var(--type-body-sm-size);
  line-height: 1.55;
  color: var(--text-heading);
}
.steps__item { display: flex; gap: var(--space-3); }
.steps__num {
  font-family: var(--font-mono);
  font-size: var(--type-cta-size);
  padding-top: 3px;
  color: var(--text-accent);
  flex: none;
}
.compare__panel--old .steps__num { color: var(--otto-grey-panel); }
/* Steps light up in sequence alongside the progress bar. */
.steps--lit .steps__item:nth-child(1) { animation: ottoStep1 var(--loop) ease-out infinite; }
.steps--lit .steps__item:nth-child(2) { animation: ottoStep2 var(--loop) ease-out infinite; }
.steps--lit .steps__item:nth-child(3) { animation: ottoStep3 var(--loop) ease-out infinite; }

/* --- progress + status ---------------------------------------------------- */
.progress-group { margin-top: 10px; display: flex; flex-direction: column; gap: 10px; }

.progress { height: 3px; background: var(--otto-hairline); }
.progress__bar { height: 3px; display: block; }

.progress--stall { background: var(--otto-hairline); }
.progress--stall .progress__bar {
  width: 23%;
  background: var(--otto-grey-inactive);
  animation: ottoStall var(--loop) cubic-bezier(.2, 0, .1, 1) infinite;
}
.progress--advance { background: var(--otto-green-veil); }
.progress--advance .progress__bar {
  width: 100%;
  background: var(--otto-green);
  animation: ottoAdvance var(--loop) cubic-bezier(.4, 0, .2, 1) infinite;
}

.status {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: var(--type-label-size);
  letter-spacing: var(--type-label-track);
  text-transform: uppercase;
  color: var(--otto-grey-panel);
}
.status__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
  background: var(--otto-grey-inactive);
  animation: ottoWait 2.4s ease-in-out infinite;
}
/* Three phrases crossfading in place; the box is sized so nothing reflows. */
.status__rotator {
  position: relative;
  display: inline-block;
  width: 236px;
  height: 14px;
  flex: none;
}
.status__rotator > span {
  position: absolute;
  left: 0;
  top: 0;
  white-space: nowrap;
}
.status__rotator > span:nth-child(1) { animation: ottoPhase2 var(--loop) steps(1, end) infinite; }
.status__rotator > span:nth-child(2) { animation: ottoPhase3 var(--loop) steps(1, end) infinite; }
.status__rotator > span:nth-child(3) { animation: ottoPhase4 var(--loop) steps(1, end) infinite; }

.status--done {
  gap: var(--space-1);
  color: var(--text-accent);
  animation: ottoLand var(--loop) ease-out infinite;
}

/* --- site footer ---------------------------------------------------------- */
.site-footer {
  padding: 28px var(--g);
  border-top: var(--border-hairline);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px 32px;
  flex-wrap: wrap;
}
.site-footer__email {
  font-family: var(--font-mono);
  font-size: var(--type-cta-size);
  letter-spacing: .08em;
  color: var(--text-accent);
}

/* --- mobile --------------------------------------------------------------- */
@media (max-width: 820px) {
  .nav { padding-block: 18px; }
  .nav__links { display: none; }
  .nav__burger { display: flex; }
  .nav-menu:not([hidden]) { display: flex; }

  .compare { grid-template-columns: 1fr; }
  .compare__panel { padding: 36px var(--g); }
  .compare__panel--otto { border-left: 0; border-top: 2px solid var(--otto-green); }
  .compare__head { font-size: 30px; white-space: normal; }

  .rule-list__item { grid-template-columns: 32px 1fr; gap: var(--space-3); }

  .role-card { padding: 26px 22px 24px; --card-title-size: 24px; }
  .role-card__caveat { padding: 16px 18px; }

  /* One column: a faded row would be three tall cards trailing off, and the CTA
     would land far below the fold. Drop the teaser, keep the way out. */
  .peek .fade-out { display: none; }
  .peek__cta { position: static; }

  .site-footer { padding-block: 22px; }
}

@media (min-width: 821px) and (max-width: 940px) {
  .compare__head { font-size: 33px; }
}


/* ========================================================================
   06-hero.css
   ======================================================================== */

/* ============================================================================
   HERO + MAIL MOCK — the landing hero. Copy on the left, an inbox that opens
   itself on the right: a notification arrives, is clicked, and the message
   unfolds downward out of it. The whole right column is decorative and safe to
   delete; the copy column stands on its own.

   The unfold only reads as one move if the notification sits exactly on the
   card's top edge — that way the first thing revealed is the message's own
   header, which looks like the notification. .mailstack is what guarantees it:
   the row is absolutely positioned against the card, not against the column.
   ============================================================================ */

.hero {
  /* Geometry the unfold depends on: the notification's own radius and its
     rendered height. Keep --mock-row in step with .mailrow__inner's padding
     and line count, or the card will not open from exactly the row's edges. */
  --mock-radius: 12px;
  --mock-row: 79px;

  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  min-height: calc(100vh - 84px - 148px);
  border-bottom: 2px solid var(--otto-green);
}
.hero__copy {
  position: relative;
  z-index: 1;
  padding: 92px 48px 84px var(--g);
  display: flex;
  flex-direction: column;
  gap: 28px;
}
.hero__copy .lead { max-width: 440px; }
.hero__actions { display: flex; gap: var(--space-2); padding-top: 4px; flex-wrap: wrap; }

.hero__mail {
  z-index: 1;
  padding: 92px var(--g) 84px 44px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 376px;
}
.mailstack { position: relative; }

/* The mock is a picture of someone else's UI, so it opts out of Otto's
   generous body line-height; each row sets its own. */
.mailrow,
.mailmock { line-height: normal; }

/* --- the notification that arrives, is clicked, and unfolds --------------- */
/* It sits on the card's top edge and is exactly --mock-row tall. The card is
   clipped to that same band until 1.5s, so when the notification dissolves the
   message grows out of it rather than arriving on its own. Both animations
   start together; only the fill differs — the dissolve uses `forwards` so it
   does not override the entrance fade before its delay elapses. */
.mailrow {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 2;
  transform-origin: top center;
  animation:
    ottoRowInTop .5s var(--ease-otto) .25s both,
    ottoRowDissolve .18s ease-out 1.42s forwards;
}
.mailrow__inner {
  background: var(--surface-card);
  border: var(--border-card);
  border-radius: var(--mock-radius);
  padding: 14px 16px 14px 12px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  animation: ottoRowClick 1.6s linear .2s both;
}
.mailrow__unread {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
  background: var(--otto-green);
  margin-top: 6px;
}
.mailrow__lines { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mailrow__top { display: flex; align-items: baseline; gap: 10px; }
.mailrow__from { flex: 1; font-size: var(--type-caption-size); font-weight: 600; letter-spacing: -.01em; }
.mailrow__time { font-size: var(--type-cta-size); color: var(--text-faint); flex: none; }
.mailrow__subject,
.mailrow__preview { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mailrow__subject { font-size: 14px; }
.mailrow__preview { font-size: 13px; color: var(--text-faint); }

/* --- the opened message --------------------------------------------------- */
/* This is the one place a shadow is allowed: it is a picture of a mail client,
   not an Otto surface. Otto's own surfaces never carry one. */
.mailmock {
  position: relative;
  z-index: 1;
  background: var(--surface-card);
  border: var(--border-card);
  border-radius: var(--mock-radius);
  box-shadow: 0 18px 40px -30px rgba(29, 35, 32, .6);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  opacity: 0;
  /* Closed state: a --mock-row band on the card's top edge, under the row. */
  --clip-from: inset(0 0 calc(100% - var(--mock-row)) 0 round var(--mock-radius));
  /* Starts at 1.55s, 130ms into the notification's 180ms dissolve: the card
     takes over the exact same rectangle just as the notification leaves it, so
     there is no window where both are legible at once and no gap between them.
     Deliberately NOT --ease-otto — that easing is front-loaded and would throw
     the card open while the notification was still on screen, which is what
     made this read as two unrelated events. */
  animation: ottoCardUnfold .75s cubic-bezier(.4, 0, .2, 1) 1.55s both;
}
.mailmock__chrome {
  padding: 13px 16px;
  border-bottom: 1px solid rgba(29, 35, 32, .1);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--otto-paper-chrome);
}
.mailmock__back { display: flex; align-items: center; gap: 5px; color: var(--otto-green); font-size: 14px; }
.mailmock__chrome-icons { display: flex; align-items: center; gap: 14px; color: var(--otto-grey-fainter); }

.mailmock__header {
  padding: 16px 18px 14px;
  border-bottom: 1px solid rgba(29, 35, 32, .1);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.mailmock__subject { font-size: 19px; font-weight: 600; letter-spacing: -.015em; line-height: 1.25; }
.mailmock__meta { display: flex; align-items: center; gap: 11px; }
.mailmock__avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  flex: none;
  background: var(--otto-green);
  color: var(--otto-paper);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-serif);
  font-size: 17px;
}
.mailmock__who { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.mailmock__name { font-size: var(--type-caption-size); font-weight: 600; letter-spacing: -.01em; }
.mailmock__to,
.mailmock__time { font-size: 13px; color: var(--text-faint); }
.mailmock__time { flex: none; }

.mailmock__body { padding: 20px 18px 22px; display: flex; flex-direction: column; gap: var(--space-4); }
.mailmock__quote { font-family: var(--font-serif); font-size: 22px; line-height: 1.38; color: var(--text-heading); }
.mailmock__sign { font-size: 14px; line-height: 1.5; color: var(--text-muted); }

.mailmock__actions {
  padding: 12px 18px;
  border-top: 1px solid rgba(29, 35, 32, .1);
  background: var(--otto-paper-chrome);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.mailmock__reply {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  color: var(--otto-green);
  font-size: 13px;
  opacity: 0;
  animation: ottoReplyIn .45s ease-out 2.5s both;
}
.mailmock__tools { display: flex; align-items: center; gap: 18px; color: var(--otto-grey-fainter); }

@media (max-width: 820px) {
  .hero { grid-template-columns: 1fr; min-height: 0; }
  .hero__copy { padding: 44px var(--g) 12px; gap: 20px; }
  .hero__mail {
    padding: 20px var(--g) 52px;
    min-height: 330px;
    justify-content: flex-start;
  }
  /* Nothing to move: .mailstack keeps the notification on the card's top edge
     at every width, so the unfold is identical here. */
}


/* ========================================================================
   07-utilities.css
   ======================================================================== */

/* ============================================================================
   UTILITIES — small, boring helpers. If you find yourself wanting a new one,
   check whether the thing you are building is really a component first.
   ============================================================================ */

.text-body   { color: var(--text-body); }
.text-muted  { color: var(--text-muted); }
.text-faint  { color: var(--text-faint); }
.text-accent { color: var(--text-accent); }
.text-center { text-align: center; }

.body-sm { font-size: var(--type-body-sm-size); line-height: var(--type-body-sm-line); }
.caption { font-size: var(--type-caption-size); line-height: var(--type-caption-line); }
.mono    { font-family: var(--font-mono); }
.serif   { font-family: var(--font-serif); }

.measure      { max-width: var(--measure-line); }
.measure-read { max-width: var(--measure-read); }
.nowrap       { white-space: nowrap; }

.center-self { align-self: center; }
.start-self  { align-self: flex-start; }

/* Visible to screen readers only. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Skip link: off-screen until focused. */
.skip-link {
  position: absolute;
  left: var(--g);
  top: -100px;
  z-index: 10;
  padding: 12px 18px;
  background: var(--otto-green);
  color: var(--otto-paper);
  font-family: var(--font-mono);
  font-size: var(--type-label-size);
  letter-spacing: var(--type-label-track);
  text-transform: uppercase;
  transition: top .15s ease;
}
.skip-link:focus { top: 12px; color: var(--otto-paper); }


/* ========================================================================
   08-styleguide.css
   ======================================================================== */

/* ============================================================================
   STYLEGUIDE — the only rules here style /styleguide itself. Nothing on a real
   page should use these classes.
   ============================================================================ */

.demo {
  border: var(--border-card);
  background: var(--surface-card);
}
.demo__stage {
  padding: 32px 28px;
  background: var(--surface-page);
  border-bottom: var(--border-card);
}
.demo__code {
  margin: 0;
  padding: 18px 20px;
  overflow-x: auto;
  background: var(--surface-band);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.65;
  color: var(--text-body);
  tab-size: 2;
}
.demo__code code { white-space: pre; }

/* A demo whose component needs the full page width (nav, compare, hero). */
.demo--bleed .demo__stage { padding: 0; }

.swatches { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--space-3); }
.swatch { border: var(--border-card); }
.swatch__chip { height: 72px; }
.swatch__meta { padding: 10px 12px; background: var(--surface-card); }
.swatch__name { font-family: var(--font-mono); font-size: 11px; letter-spacing: .06em; color: var(--text-heading); }
.swatch__value { font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }

.sg-toc { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-6); }
.sg-toc a { font-family: var(--font-mono); font-size: var(--type-label-size); letter-spacing: var(--type-label-track); text-transform: uppercase; }


/* ========================================================================
   09-print.css
   ======================================================================== */

/* ============================================================================
   PRINT — how a page behaves on paper, and in "save as PDF".

   This is not a nicety. A member's profile page is the deliverable a hiring
   manager saves and forwards, and the admin portal offers the same page as a
   downloadable file specifically so it can be printed. Everything here exists
   because a default print dialog gets one of these wrong.

   Last in filename order on purpose: it is the only file allowed to override
   what the ones above it decided, and only inside @media print.
   ============================================================================ */

@media print {
  /* Wide enough to read, tight enough that a scorecard row does not split. */
  @page { margin: 18mm; }

  /* Navigation on paper is dead weight — nothing here can be clicked. */
  .nav,
  .nav-menu,
  .nav__burger,
  .skip-link { display: none !important; }

  /* True white, not letter cream. This is the one place a raw colour belongs
     outside 01-tokens.css: it is the absence of ink rather than a brand value,
     and printing the page ground would tint every sheet. */
  html,
  body { background: #fff !important; }

  /* Otto's depth is the tint step — paper, envelope, card white — and the green
     rule markers. Browsers drop backgrounds by default, which erases the
     scorecard's structure and the accent band entirely. */
  *,
  *::before,
  *::after {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* Entrance animations are opacity:0 until a scroll observer fires, and print
     does not scroll. Without this, every revealed block prints blank — which is
     most of a profile page and every role on a shortlist. */
  [data-reveal] {
    opacity: 1 !important;
    animation: none !important;
  }

  /* Band padding is sized for a scrolling viewport. On paper the page margin is
     already doing that job, and 88px of it wastes a third of the first sheet. */
  .band {
    padding-top: 0;
    padding-bottom: 28px;
    padding-inline: 0;
  }
  .band--rule-top { border-top: 0; }

  /* Keep a claim with its substantiation. A scorecard row or a role card broken
     across a page boundary reads as two half-arguments. */
  section,
  .tint-card,
  .paper-card,
  .member-card,
  .role-card,
  .role-card__caveat,
  .rule-list__item,
  .divided-item,
  .steps__item { break-inside: avoid; }

  /* The hairline is set in alpha over the page ground, which no longer exists
     once the ground is white. */
  .site-footer {
    border-top: 1px solid var(--otto-hairline-strong);
    padding-inline: 0;
  }

  /* Green link text on a monochrome printer is grey text with no underline —
     indistinguishable from body copy, and unclickable either way. */
  a { color: inherit; }
}
