/* Bob Mayo site — RNM7 Crisp Clay, concatenated from the design system. Generated; edit the source system, not this file. */

/* ==== tokens/fonts.css ==== */
/* Three families, three files (four — Source Sans 3 needs a true italic).
   Variable faces, latin, pinned to Fontsource 5.3.0. jsDelivr serves versioned
   paths immutably, so these bytes never change under us; nothing here tracks a
   moving upstream.

   To take the CDN out of the picture entirely: drop the four .woff2 files into
   assets/fonts/ and change the four src lines to url("../assets/fonts/<name>.woff2").
   Nothing else in the system references a font file. */

@font-face {
  font-family: "Bitter";
  font-weight: 100 900;
  font-display: swap;
  src: url("https://cdn.jsdelivr.net/fontsource/fonts/bitter:vf@5.3.0/latin-wght-normal.woff2") format("woff2-variations");
}
@font-face {
  font-family: "Source Sans 3";
  font-weight: 200 900;
  font-display: swap;
  src: url("https://cdn.jsdelivr.net/fontsource/fonts/source-sans-3:vf@5.3.0/latin-wght-normal.woff2") format("woff2-variations");
}
@font-face {
  font-family: "Source Sans 3";
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url("https://cdn.jsdelivr.net/fontsource/fonts/source-sans-3:vf@5.3.0/latin-wght-italic.woff2") format("woff2-variations");
}
@font-face {
  font-family: "JetBrains Mono";
  font-weight: 100 800;
  font-display: swap;
  src: url("https://cdn.jsdelivr.net/fontsource/fonts/jetbrains-mono:vf@5.3.0/latin-wght-normal.woff2") format("woff2-variations");
}


/* ==== tokens/colors.css ==== */
/* Warm clay ground, near-black ink, one working blue, one red for errors.
   Every colour in the system is here — one name per thing, no alias layer.
   Panels and figure blocks are the only tinted planes. There is no shadow token
   by design: if an element must separate, give it an outline. */
:root {
  /* Surfaces */
  --backdrop:       #F0E9E1;  /* a recessed plane, when one is genuinely needed */
  --surface:        #FCF9F5;  /* the page ground, and secondary buttons */
  --surface-alt:    #F3EDE5;  /* hover fills, quiet fills */
  --surface-input:  #F7F2EB;  /* form controls */
  --panel:          #EAF0F8;  /* cards — the blue plane */
  --tan:            #F4EBDF;  /* figure blocks, out of the blue family */

  /* Ink */
  --text:           #0B0C0E;  /* headings and body */
  --text-secondary: #514B44;  /* supporting prose inside a card */
  --text-muted:     #6A6157;  /* meta lines, captions, mono facts */
  --text-disabled:  #9AA4B0;

  /* The blue — links, labels, figures, the one primary action, the focus ring */
  --accent:         #12569E;
  --accent-hover:   #0E4380;
  --accent-on:      #FCF9F5;  /* ink on an accent fill */
  --accent-mark:    #185FA5;  /* the wordmark square */

  /* The one colour outside the blue: errors. No warning tier, no green —
     good news is stated in prose. */
  --critical:        #A3271C;
  --critical-fill:   #FBEDE8;
  --critical-border: #D9A79C;

  /* Borders — the only structural cue in this system */
  --border:         #B6ADA1;  /* the default outline */
  --border-panel:   #8FA5C0;  /* around a blue panel */
  --tan-border:     #CDBCA4;  /* around a figure block */
  --border-quiet:   #DCE2E9;  /* row dividers, disabled outlines */
}


/* ==== tokens/typography.css ==== */
:root {
  --font-display: "Bitter", Georgia, serif;
  --font-body:    "Source Sans 3", system-ui, sans-serif;
  --font-mono:    "JetBrains Mono", ui-monospace, monospace;

  --weight-regular: 400;
  --weight-semibold: 600; /* the UI bold */
  --weight-bold: 700;     /* labels, card links, display only */

  --size-display: 46px;   --lh-display: 1.1; /* @kind other */  --ls-display: -0.02em;
  --size-h1: 32px;        --lh-h1: 1.2; /* @kind other */
  --size-h2: 23px;        --lh-h2: 1.3; /* @kind other */
  --size-h3: 17px;        --lh-h3: 1.4; /* @kind other */
  --size-body: 18px;      --lh-body: 1.7; /* @kind other */
  --size-ui: 15.5px;
  --size-input: 16.5px;
  --size-small: 14px;     --lh-small: 1.6; /* @kind other */
  --size-label: 11.5px;   --ls-label: 0.12em;
  --size-mono: 12px;      --ls-mono: 0.06em;

  --measure: 66ch;
}

/* Mobile. The scale steps down at the head and holds at the foot: display and h1
   are the only sizes that hurt on a 360px screen. Body never drops below 17px,
   small never below 14px, mono never below 12px — a spec you cannot read is not
   a spec. */
@media (max-width: 700px) {
  :root {
    --size-display: 32px; --ls-display: -0.015em;
    --size-h1: 26px;
    --size-h2: 21px;
    --size-body: 17px;
    --measure: 100%;
  }
}


/* ==== tokens/space.css ==== */
:root {
  /* 4px base */
  --space-1: 8px;
  --space-2: 14px;
  --space-3: 20px;
  --space-4: 28px;
  --space-5: 38px;

  --gap-stack: var(--space-3);
  --gap-row: var(--space-2);
  --pad-card: var(--space-3);
  --pad-card-wide: 24px 26px;

  /* Page: full-bleed background, content aligned to a centred measure */
  --content-max: 1080px; /* @kind other */
  --pad-page-x: max(var(--space-5), calc((100% - var(--content-max)) / 2));

  /* Minimum interactive target. Nothing tappable is smaller, on any screen. */
  --target-min: 44px;
}

/* Mobile gutters. 38px of side padding on a 360px screen spends a fifth of the
   width on nothing, so the gutter drops to 20px and the measure goes away. */
@media (max-width: 700px) {
  :root {
    --pad-page-x: var(--space-3);
    --pad-card-wide: var(--space-3);
    --gap-stack: var(--space-3);
  }
}


/* ==== tokens/shape.css ==== */
:root {
  --radius-card:  14px;
  --radius-input: 10px;
  --radius-pill:  24px;
  --radius-chip:  7px;

  --stroke: 1.5px;
  --stroke-focus: 2.5px;

  /* No shadow tokens exist in this system. If an element must separate,
     give it an outline. */
}


/* ==== base/reset.css ==== */
*, *::before, *::after { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--size-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
}


/* ==== base/type.css ==== */
.display { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--size-display); line-height: var(--lh-display); letter-spacing: var(--ls-display); margin: 0; max-width: 22ch; }
h1, .h1 { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--size-h1); line-height: var(--lh-h1); margin: 0; }
h2, .h2 { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--size-h2); line-height: var(--lh-h2); margin: 0; }
h3, .h3 { font-family: var(--font-body); font-weight: var(--weight-semibold); font-size: var(--size-h3); line-height: var(--lh-h3); margin: 0; }
p, .body { font-size: var(--size-body); line-height: var(--lh-body); margin: 0; }
/* Opt-in reading measure. Text only needs it when something sits beside it —
   inside .split the grid column already imposes it. */
.measure { max-width: var(--measure); }
.small { font-size: var(--size-small); line-height: var(--lh-small); color: var(--text-muted); }
em, .em { font-style: italic; }
.mono { font-family: var(--font-mono); font-size: var(--size-mono); letter-spacing: var(--ls-mono); color: var(--text-muted); }
.label { font-size: var(--size-label); font-weight: var(--weight-bold); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--text-muted); }
.label--accent { color: var(--accent); }
a { color: var(--accent); font-weight: var(--weight-semibold); text-decoration: underline; text-underline-offset: 4px; }
a:hover { color: var(--accent-hover); }
a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }


/* ==== patterns/layout.css ==== */
/* The page is full width: no box, no outline, no float on a backdrop. Rules and
   fills run edge to edge; content aligns to a centred --content-max measure. */
.shell {
  width: 100%;
  background: var(--surface);
}
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--gap-stack);
  padding: 0 var(--pad-page-x) 30px;
}
.stack:last-child { padding-bottom: var(--space-5); }
.row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-row); }
.grid-2 { display: grid; grid-template-columns: 1.3fr 1fr; gap: 18px; }
/* Prose column + side rail. Body copy keeps its 66ch measure; the rail takes
   the width the measure does not, so a full-width page is not a narrow column
   with an empty right half. */
.split { display: grid; grid-template-columns: minmax(0, 2.1fr) minmax(280px, 0.9fr); gap: var(--space-5); align-items: start; }
.split__rail { display: flex; flex-direction: column; gap: 18px; }
/* Equal-width card/list columns across the full measure. */
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
@media (max-width: 980px) {
  .split { grid-template-columns: minmax(0, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.rule { height: 0; border: 0; border-top: var(--stroke) solid var(--border); margin: 0; }
@media (max-width: 700px) {
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  /* The rail stops being a rail: cards follow the prose they annotate. */
  .split { gap: var(--space-4); }
  .stack { padding-bottom: var(--space-4); }
  .card--wide { margin-bottom: var(--space-3); }
}


/* ==== patterns/masthead.css ==== */
.masthead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: 30px var(--pad-page-x) var(--space-3);
  border-bottom: var(--stroke) solid var(--border);
  margin-bottom: var(--space-4);
}
.masthead__end { display: flex; align-items: center; gap: var(--space-2); }
.masthead__nav { display: flex; align-items: center; gap: var(--space-3); }
.masthead__nav a { font-size: var(--size-small); font-weight: var(--weight-semibold); text-decoration: none; color: var(--text); }
.masthead__nav a:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 4px; }
.masthead__nav a[aria-current="page"] { color: var(--accent); }
.wordmark { display: block; width: 190px; height: auto; }

/* Brand lockup — the supplied artwork. The outlines are drawn, not set in a
   typeface, so an <img> of assets/wordmark.svg is equivalent to the component. */
.wordmark-lockup { display: block; height: auto; }

/* Mobile masthead. The wordmark shrinks, the nav drops to a scrolling row
   beneath the rule, and the icon action stays put at 44px — it is usually the
   menu. The rule still runs edge to edge. */
@media (max-width: 700px) {
  .masthead { padding: var(--space-3) var(--pad-page-x) var(--space-2); margin-bottom: var(--space-3); }
  .wordmark, .wordmark-lockup { width: 148px; }
  .masthead__nav { display: none; }
  .masthead--stacked { flex-wrap: wrap; }
  .masthead--stacked .masthead__nav {
    display: flex;
    order: 3;
    width: 100%;
    gap: var(--space-3);
    padding-top: var(--space-2);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .masthead--stacked .masthead__nav a { white-space: nowrap; padding: 6px 0; }
}


/* ==== patterns/buttons.css ==== */
.btn {
  font-family: var(--font-body);
  font-size: var(--size-ui);
  font-weight: var(--weight-semibold);
  border: var(--stroke) solid transparent;
  border-radius: var(--radius-pill);
  padding: 11.5px 22.5px;
  min-height: var(--target-min);
  cursor: pointer;
}
.btn--primary { color: var(--accent-on); background: var(--accent); border-color: var(--accent); }
.btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn--secondary { color: var(--text); background: var(--surface); border-color: var(--border); }
.btn--secondary:hover { background: var(--surface-alt); border-color: var(--accent); }
.btn:disabled { color: var(--text-disabled); background: var(--surface); border-color: var(--border-quiet); cursor: default; }
.icon-btn {
  display: flex; align-items: center; justify-content: center;
  width: var(--target-min); height: var(--target-min); flex: none;
  background: var(--surface); color: var(--text);
  border: var(--stroke) solid var(--border);
  border-radius: var(--radius-input);
  cursor: pointer;
}
.icon-btn:hover { background: var(--surface-alt); border-color: var(--accent); }
.icon-btn:disabled { color: var(--text-disabled); border-color: var(--border-quiet); cursor: default; }
.icon-btn svg { width: 24px; height: 24px; }
.btn:focus-visible, .icon-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }


/* ==== patterns/forms.css ==== */
.field { display: flex; flex-direction: column; gap: 7px; max-width: 350px; }
.field__label { font-size: var(--size-small); font-weight: var(--weight-semibold); }
.field__input {
  font-family: var(--font-body);
  font-size: var(--size-input);
  color: var(--text);
  background: var(--surface-input);
  border: none;
  border-radius: var(--radius-input);
  padding: 13px 14px;
  box-shadow: inset 0 0 0 var(--stroke) var(--border);
  width: 100%;
}
.field__input::placeholder { color: var(--text-disabled); }
.field__input:focus { box-shadow: inset 0 0 0 var(--stroke-focus) var(--accent); outline: none; }
.field__input:disabled { color: var(--text-disabled); box-shadow: inset 0 0 0 var(--stroke) var(--border-quiet); cursor: default; }
.field__hint { font-size: var(--size-small); color: var(--text-muted); }
select.field__input { appearance: none; background-image: none; }
textarea.field__input { min-height: 110px; resize: vertical; line-height: 1.55; }


/* ==== patterns/cards.css ==== */
.card {
  background: var(--panel);
  border: var(--stroke) solid var(--border-panel);
  border-radius: var(--radius-card);
  padding: var(--pad-card);
}
.card__title { margin-top: 9px; font-size: 20px; }
.card__body { margin-top: 9px; font-size: 15px; line-height: 1.65; color: var(--text-secondary); }
.card__spec { margin-top: 10px; font-size: 11.5px; line-height: 1.7; }
.card__link { display: inline-block; margin-top: 13px; font-size: 14.5px; font-weight: var(--weight-bold); }
.card.card--wide {
  display: flex; flex-direction: column; gap: 9px;
  margin: 0 var(--pad-page-x) var(--space-4);
  padding: var(--pad-card-wide);
}
.card--wide p { font-size: 14.5px; line-height: 1.6; color: var(--text-muted); }
.card--wide p b { color: var(--text); font-weight: var(--weight-semibold); }
.card--wide .spec { font-size: 13px; line-height: 1.5; color: var(--text); max-width: none; }
.stat {
  background: var(--tan);
  border: var(--stroke) solid var(--tan-border);
  border-radius: var(--radius-card);
  padding: var(--pad-card);
  display: flex; flex-direction: column; gap: 4px;
}
.stat__value { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: 50px; line-height: 1.05; color: var(--accent); margin: 0; }
.stat__unit { font-size: 19px; margin-left: 5px; color: var(--text-muted); }
.stat__note { font-size: var(--size-small); line-height: 1.55; color: var(--text-secondary); }
.swatches { display: grid; grid-template-columns: repeat(8, 1fr); gap: 9px; }
.swatch__chip { display: block; height: 40px; border-radius: var(--radius-chip); box-shadow: inset 0 0 0 1px rgba(20, 35, 60, 0.18); }
.swatch__chip--outlined { box-shadow: inset 0 0 0 var(--stroke) var(--border); }
.swatch__role { display: block; margin-top: 7px; font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); }
.swatch__hex { display: block; font-family: var(--font-mono); font-size: 10.5px; }
.swatch__hex--sub { color: var(--text-muted); }


/* ==== patterns/data.css ==== */
/* Data display. Numbers are machine facts, so they set in JetBrains Mono with
   tabular figures and align on their last digit. Language stays in Source Sans.
   The table is a reading object, not a grid: horizontal rules only, no zebra,
   no vertical lines, no fills. */
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 15px;
  line-height: 1.5;
}
.data-table caption {
  caption-side: top;
  text-align: left;
  padding-bottom: var(--space-2);
  font-size: var(--size-small);
  line-height: var(--lh-small);
  color: var(--text-muted);
}
.data-table thead th {
  text-align: left;
  vertical-align: bottom;
  padding: 0 var(--space-3) 9px 0;
  font-size: var(--size-label);
  font-weight: var(--weight-bold);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-muted);
  border-bottom: var(--stroke) solid var(--border);
  white-space: nowrap;
}
.data-table td {
  padding: 13px var(--space-3) 13px 0;
  border-bottom: var(--stroke) solid var(--border-quiet);
  color: var(--text);
  vertical-align: baseline;
}
/* Row header: the first column names the row, so it stays in body type and shares
   the baseline of the figures beside it. */
.data-table tbody th {
  text-align: left;
  vertical-align: baseline;
  padding: 13px var(--space-3) 13px 0;
  font-size: 15px;
  font-weight: var(--weight-regular);
  letter-spacing: 0;
  text-transform: none;
  color: inherit;
  border-bottom: var(--stroke) solid var(--border-quiet);
}
.data-table th:last-child, .data-table td:last-child { padding-right: 0; }
.data-table tr:last-child th, .data-table tr:last-child td { border-bottom: 0; }

/* Numeric columns. Mono, tabular, right-aligned so digits stack. The unit lives
   in the header — "COST (USD)" — and is never repeated in every cell. */
.data-table [data-numeric], .data-table th[data-numeric] { text-align: right; }
.data-table td[data-numeric] {
  font-family: var(--font-mono);
  font-size: var(--size-mono);
  letter-spacing: var(--ls-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  white-space: nowrap;
}
/* The row under discussion. Accent, not bold — bold spots the page. */
.data-table tr[data-emphasis] th, .data-table tr[data-emphasis] td { color: var(--accent); }
.data-table__note { margin-top: 10px; font-size: var(--size-small); color: var(--text-muted); }

/* Wide tables scroll rather than shrink: nothing in a table drops below 12px. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-scroll > .data-table { min-width: 520px; }

/* Key/value specs — the two-column form of the same content, for a rail or a
   card where a table would be too wide. */
.kv { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 9px var(--space-3); margin: 0; }
.kv dt { font-size: var(--size-small); color: var(--text-secondary); }
.kv dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--size-mono);
  letter-spacing: var(--ls-mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--text);
  white-space: nowrap;
}
.mono, .stat__value { font-variant-numeric: tabular-nums; }


/* ==== patterns/figures.css ==== */
/* Figures. An image is a plane like any other: 1.5px outline, radius 14, no
   shadow, no full-bleed. It carries a caption in small ink and, when it shows a
   real house or a real bill, an attribution — the same dated honesty the prose has. */
.figure { display: flex; flex-direction: column; gap: 9px; margin: 0; }
.figure__frame {
  position: relative;
  overflow: hidden;
  border: var(--stroke) solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-alt);
}
.figure__frame > img, .figure__frame > image-slot, .figure__frame > svg { display: block; width: 100%; height: 100%; object-fit: cover; }
.figure--3-2 .figure__frame { aspect-ratio: 3 / 2; }
.figure--4-3 .figure__frame { aspect-ratio: 4 / 3; }
.figure--square .figure__frame { aspect-ratio: 1 / 1; }
.figure figcaption { font-size: var(--size-small); line-height: var(--lh-small); color: var(--text-secondary); }
.figure__credit { font-family: var(--font-mono); font-size: var(--size-mono); letter-spacing: var(--ls-mono); color: var(--text-muted); }

/* Placeholder — what a slot looks like before the real photograph arrives.
   It names the ratio and the subject so the gap is a brief, not a hole. */
.figure__placeholder {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  width: 100%; height: 100%;
  padding: var(--space-3);
  text-align: center;
  background: var(--surface-alt);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--size-mono);
  letter-spacing: var(--ls-mono);
}


/* ==== patterns/states.css ==== */
/* States. Every interactive element in this system answers for five of them:
   rest, hover, focus, disabled, and — where it can fail — error. Loading and
   empty are page states, not element states, and live at the bottom.
   No shadows, no colour-only signals: state is carried by outline weight,
   fill, and words. */

/* Focus. One ring, everywhere, keyboard only. 2.5px accent offset 2px, so it
   reads outside the element's own 1.5px outline rather than replacing it. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--stroke-focus) solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-chip);
}
.field__input:focus-visible { outline: none; }

/* Disabled. Ink and outline both drop to the quiet step; the element keeps its
   footprint so the layout does not move. Never lower opacity — it fogs text. */
:where(button, input, select, textarea)[disabled],
[aria-disabled="true"] {
  color: var(--text-disabled);
  border-color: var(--border-quiet);
  cursor: default;
  pointer-events: none;
}
.btn[disabled], .btn[aria-disabled="true"] { background: var(--surface-alt); color: var(--text-disabled); border-color: var(--border-quiet); }

/* Error. The one place a second colour is allowed. The outline thickens to the
   focus weight so the field is findable without colour, and the message is a
   sentence that says what to do — never "Invalid input". */
.field__input[aria-invalid="true"] {
  box-shadow: inset 0 0 0 var(--stroke-focus) var(--critical);
  background: var(--critical-fill);
}
.field__error {
  display: flex;
  gap: 6px;
  font-size: var(--size-small);
  line-height: var(--lh-small);
  font-weight: var(--weight-semibold);
  color: var(--critical);
}
.field__error::before { content: "\2014"; }

/* Page-level notice. Same outlined plane as a card, tinted by severity. */
.notice {
  display: flex; flex-direction: column; gap: 6px;
  padding: var(--pad-card);
  border: var(--stroke) solid var(--border-panel);
  border-radius: var(--radius-card);
  background: var(--panel);
  font-size: 15px;
  line-height: 1.6;
}
.notice__title { font-weight: var(--weight-semibold); color: var(--text); }
.notice--critical { background: var(--critical-fill); border-color: var(--critical-border); }
.notice--critical .notice__title { color: var(--critical); }

/* Loading. Literal words first ("Searching…"), a skeleton only where the shape
   of the answer is already known. Skeletons are quiet fills at the height of
   the text they replace — never spinners over content. */
.is-loading { color: var(--text-muted); }
.skeleton {
  display: block;
  background: var(--surface-alt);
  border-radius: var(--radius-chip);
  height: 1em;
}
.skeleton--line { height: 12px; margin: 7px 0; }
.skeleton--line:nth-child(3n) { width: 72%; }
.skeleton--block { height: 96px; border: var(--stroke) solid var(--border-quiet); background: var(--surface-alt); border-radius: var(--radius-card); }
@media (prefers-reduced-motion: no-preference) {
  .skeleton { animation: skeleton-fade 1.4s ease-in-out infinite; }
  @keyframes skeleton-fade { 0%, 100% { opacity: 1 } 50% { opacity: 0.55 } }
}

/* Empty. Never a shrug. Say what would be here, why it is not, and give the one
   next step — in the same outlined frame the content would have occupied. */
.empty {
  display: flex; flex-direction: column; gap: 9px; align-items: flex-start;
  padding: var(--pad-card-wide);
  border: var(--stroke) solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.empty__title { font-family: var(--font-body); font-weight: var(--weight-semibold); font-size: var(--size-h3); }
.empty__body { font-size: 15px; line-height: 1.6; color: var(--text-secondary); max-width: 52ch; }


/* ==== base/print.css ==== */
/* Print. The ground goes pure white — the clay warmth is a screen decision, and
   on paper it costs ink and muddies scans. Outlines survive: they are the only
   structural cue this system has, and paper needs them more than a screen does.
   Planes keep a fill, but a monochrome one: light neutral greys that photocopy
   and fax cleanly, so a card still reads as a card. Nothing here changes the screen. */
@media print {
  :root {
    --surface: #FFFFFF;
    --backdrop: #FFFFFF;
    --surface-alt: #F7F7F7;
    --panel: #F1F1F1;        /* cards — the darkest plane on paper */
    --surface-input: #F7F7F7;
    --tan: #F7F7F7;          /* figure blocks — a step lighter than a card */
    --text: #000000;
    --text-secondary: #1A1A1A;
    --text-muted: #333333;
    --accent: #000000;
    --accent-hover: #000000;
    --accent-mark: #000000;
    --accent-on: #FFFFFF;
    --border: #000000;
    --border-panel: #000000;
    --border-quiet: #767676;
    --tan-border: #000000;
    --stroke: 1px;

    /* Paper type scale, in points. Nothing prints below 9pt. */
    --size-display: 26pt;
    --size-h1: 19pt;
    --size-h2: 14pt;
    --size-h3: 12pt;
    --size-body: 11pt;
    --size-small: 9.5pt;
    --size-label: 8pt;
    --size-mono: 9pt;
  }
  @page { margin: 18mm 16mm; }
  html, body { background: #FFFFFF; }
  body { -webkit-print-color-adjust: exact; print-color-adjust: exact; }

  /* Content aligns to the paper edge; the screen measure is meaningless here. */
  :root { --pad-page-x: 0; --content-max: none; /* @kind other */ }
  .shell, .stack, .card--wide { margin-left: 0; margin-right: 0; }

  /* Screen-only chrome. Navigation, controls and anything that cannot be
     actioned on paper come out. */
  .masthead__nav, .masthead__end, .btn, .icon-btn, .kit-tabs, .warmth-bar,
  video, audio, [data-print="hide"] { display: none !important; }

  /* Planes stay planes: the fill prints, so the grey has to be exact. */
  .card, .stat, .notice, .empty, .figure__frame, .field__input { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .notice--critical { background: #F1F1F1; }

  /* An outlined system prints as an outlined system. */
  .card, .stat, .figure, .data-table { break-inside: avoid; }
  h1, h2, h3, .display, .label { break-after: avoid; }
  .stat__value { color: #000000; }

  /* Links: the destination has to be on the page, because paper cannot click. */
  a { color: #000000; text-decoration: underline; }
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-family: var(--font-mono);
    font-size: var(--size-mono);
    font-weight: 400;
    word-break: break-all;
  }
  a[href^="#"]::after, a[data-print-url="hide"]::after { content: ""; }

  /* Data tables get a repeated header and hairline rules. */
  .data-table thead { display: table-header-group; }
  .data-table tr { break-inside: avoid; }
}

