/* Self-hosted IBM Plex (SIL OFL 1.1, licence in fonts/OFL.txt). Latin subset only:
   Plex Sans 400/600 for text, Plex Sans Condensed 600/700 for numbers, labels and headings. */
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("fonts/ibm-plex-sans-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/ibm-plex-sans-latin-600-normal.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans Condensed"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/ibm-plex-sans-condensed-latin-600-normal.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans Condensed"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("fonts/ibm-plex-sans-condensed-latin-700-normal.woff2") format("woff2"); }
/* Metric-matched fallbacks, so the swap to the web font causes no layout shift.
   Method: in Chromium, canvas measureText() at 100px on the sample "The rise is the vertical height
   the roof gains. Pitch 6/12 26.57° 50.0% 1.118 Run length", with each font loaded as a webfont.
     width at 100px:  Plex Sans 400 3899.4, Plex Sans Condensed 600 3631.2, Arial 3818.3, Roboto 400 3805.5
     Plex ascent 1.025 em, descent 0.275 em, line gap 0 (fontBoundingBoxAscent/Descent 103/28 at 100px)
   size-adjust = Plex width / fallback width
   ascent-override = 1.025 / size-adjust, descent-override = 0.275 / size-adjust
   (the overrides are scaled by size-adjust; checked: the Arial face then measures 103/27 like Plex).
   Arial faces cover Windows/macOS; Liberation Sans is metric-compatible with Arial (Linux);
   Roboto covers Android. */
@font-face { font-family: "Plex Sans Fallback"; src: local("Arial"), local("ArialMT"), local("Liberation Sans"), local("LiberationSans");
  size-adjust: 102.1%; ascent-override: 100.4%; descent-override: 26.9%; line-gap-override: 0%; }
@font-face { font-family: "Plex Condensed Fallback"; src: local("Arial"), local("ArialMT"), local("Liberation Sans"), local("LiberationSans");
  size-adjust: 95.1%; ascent-override: 107.8%; descent-override: 28.9%; line-gap-override: 0%; }
@font-face { font-family: "Plex Sans Fallback Roboto"; src: local("Roboto"), local("Roboto-Regular");
  size-adjust: 102.5%; ascent-override: 100.0%; descent-override: 26.8%; line-gap-override: 0%; }
@font-face { font-family: "Plex Condensed Fallback Roboto"; src: local("Roboto"), local("Roboto-Regular");
  size-adjust: 95.4%; ascent-override: 107.4%; descent-override: 28.8%; line-gap-override: 0%; }

/* ---------- Tokens ---------- */
/* Job-site palette: concrete paper, black ink, one safety-yellow accent. The accent marks
   results, the selected unit and hover/press feedback; it is only ever a fill behind ink text
   or a mark on the dark readout, never text on a light background. */
:root {
  /* Colour */
  --bg: #f3f2ed;            /* page */
  --paper: #ffffff;         /* card, inputs, drawing sheet */
  --ink: #141414;           /* text, borders, lines */
  --muted: #4a4a46;         /* secondary text */
  --rule: #c8c5ba;          /* light dividers */
  --accent: #ffc20e;        /* safety yellow */
  --fill: #ffe9a6;          /* pale accent: diagram triangle, hover */
  --press: #c8c5ba;         /* pressed control */
  --readout-bg: #141414;    /* meter-style readout, header, table head (dark in both modes) */
  --readout-ink: #ffffff;
  --readout-muted: #c2c2bd;
  --readout-rule: #444444;
  --error: #b0001a;
  --ad-bg: #e4e2db;
  /* Images can't read custom properties, so these repeat colour values: the grid uses the
     light divider tone (#e6e3da light / #262624 dark); the tape uses --readout-bg and --accent. */
  --grid-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Cpath d='M0 .5H20M.5 0V20' stroke='%23e6e3da'/%3E%3C/svg%3E");
  --tape-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='4'%3E%3Crect width='20' height='4' fill='%23141414'/%3E%3Cpath d='M0 4L4 0H14L10 4Z' fill='%23ffc20e'/%3E%3C/svg%3E");

  /* Type */
  --font-text: "IBM Plex Sans", "Plex Sans Fallback", "Plex Sans Fallback Roboto", sans-serif;
  --font-num: "IBM Plex Sans Condensed", "Plex Condensed Fallback", "Plex Condensed Fallback Roboto", sans-serif;
  --fs-xs: .8125rem;   /* 13 */
  --fs-sm: .875rem;    /* 14 */
  --fs-md: 1.0625rem;  /* 17, body */
  --fs-lg: 1.25rem;    /* 20 */
  --fs-xl: 1.5rem;     /* 24 */
  --fs-2xl: 1.875rem;  /* 30 */
  --fs-3xl: 2.25rem;   /* 36 */
  --fs-4xl: 3rem;      /* 48 */
  --fs-result: 92px;       /* main result, upper limit */
  --fs-result-pair: 68px;  /* metric angle + slope, upper limit */
  --lh-tight: 1.1;
  --lh-snug: 1.3;
  --lh-body: 1.6;
  --track: .08em;          /* letter-spacing for uppercase labels */
  --track-sm: .05em;       /* letter-spacing for small or dense uppercase */
  --fs-2xs: 11px;          /* floor for the readout labels on narrow panels */
  --lh-value: 1.15;        /* result values */
  --underline-offset: 3px;

  /* Space */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;
  --space-10: 128px;
  /* Vertical rhythm: large space BEFORE a section, small space INSIDE it. Each gap comes from one
     rule only (margins are set to 0 elsewhere so nothing stacks):
     --section-gap  content above -> next section's divider (also tool -> ad, ad -> divider,
                    last ad -> footer): 48 px on phones up to 80 px on desktop. The only large gap.
     --rule-gap     divider -> section heading: 24-32 px
     --head-gap     section heading -> its first content: 16 px
     --sub-above    space above a subheading: 24-32 px; --sub-below under it: 8 px
     --block-gap    lists, tables, diagrams and notes from the text around them: 16 px
     --para-gap     between paragraphs */
  --section-gap: clamp(var(--space-7), 6.25vw, 80px);
  --rule-gap: clamp(var(--space-5), 2.5vw, var(--space-6));
  --head-gap: var(--space-4);
  --sub-above: clamp(var(--space-5), 2.5vw, var(--space-6));
  --sub-below: var(--space-2);
  --block-gap: var(--space-4);
  --para-gap: .875em;

  /* Lines and sizes */
  --bw-1: 1px;   /* dividers */
  --bw-2: 2px;   /* controls, card, drawing sheet */
  --bw-3: 3px;   /* section rules, focus ring, invalid input */
  --bw-bar: 4px; /* accent bars, hazard tape */
  --tap: 44px;
  --control-h: 52px;
  --side-col: 280px;        /* heading column of .layout-side */
  --diagram-max-h: 360px;   /* drawing sheet on phones and tablets */
  --diagram-min-h: 260px;   /* drawing sheet on desktop */
  --ad-h: 280px;            /* 300x250 / 336x280 units */
  --ad-h-desktop: 90px;     /* 728x90 unit */
  --tile: 20px;             /* width of the grid and hazard-tape SVG tiles */

  /* Content column width and side gutter */
  --content-max: 1280px;
  --gutter: 32px;
  color-scheme: light dark;
}
@media (max-width: 700px) { :root { --gutter: 18px; } }
/* Dark: the same materials at night, not an inversion. The readout stays a black meter. */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #111111;
    --paper: #1b1b1a;
    --ink: #f2f1ec;
    --muted: #b8b7b0;
    --rule: #3a3a37;
    --fill: #3b3110;
    --press: #4a4a46;
    --readout-bg: #000000;
    --readout-muted: #b5b5ae;
    --readout-rule: #333333;
    --error: #ff7d88;
    --ad-bg: #222220;
    --grid-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Cpath d='M0 .5H20M.5 0V20' stroke='%23262624'/%3E%3C/svg%3E");
  }
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: var(--fs-md)/var(--lh-body) var(--font-text);
}
.wrap { max-width: var(--content-max); margin: 0 auto; padding: 0 var(--gutter); }
a { color: var(--ink); text-underline-offset: var(--underline-offset); }
a:hover { text-decoration-thickness: var(--bw-2); }
a:active { color: var(--muted); }
strong { font-weight: 600; } /* the loaded text weights are 400 and 600 */
/* Visually hidden but read by screen readers */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
:focus-visible { outline: var(--bw-3) solid var(--ink); outline-offset: var(--bw-2); }

/* Native controls: no browser rounding or styling */
input, button { -webkit-appearance: none; appearance: none; border-radius: 0; font: inherit; }

/* Square scrollbars (WebKit/Blink); Firefox scrollbars are square already */
::-webkit-scrollbar { width: var(--space-3); height: var(--space-3); }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--muted); border: var(--bw-2) solid var(--bg); }

/* ---------- Header: black bar with a hazard-tape edge (total 48 px) ---------- */
.site-header { background: var(--readout-bg); }
.site-header::after { content: ""; display: block; height: var(--bw-bar); background: var(--tape-img) repeat-x 0 0 / var(--tile) var(--bw-bar); }
.site-header .wrap { height: var(--tap); display: flex; align-items: stretch; }
/* The wordmark fills the bar height so its tap target is 44 px */
.wordmark {
  display: flex; align-items: center;
  font: 700 var(--fs-lg)/1 var(--font-num); letter-spacing: var(--track-sm); text-transform: uppercase;
  color: var(--readout-ink); text-decoration: none;
}
.wordmark:hover { color: var(--accent); }
.wordmark:focus-visible { outline-color: var(--accent); }

/* ---------- Headings and copy ---------- */
h1, h2, h3 { font-family: var(--font-num); line-height: var(--lh-tight); }
h1 { font-size: var(--fs-3xl); font-weight: 700; margin: var(--space-3) 0 var(--space-2); }
.intro { margin: 0 0 var(--space-4); color: var(--muted); }
h2 { font-size: var(--fs-2xl); font-weight: 700; margin: 0 0 var(--head-gap); }
h3 { font-size: var(--fs-lg); font-weight: 600; margin: 0 0 var(--sub-below); }
p { margin: 0 0 var(--para-gap); }
/* Sections below the tool: the top rule sits in the middle of the section gap */
main > section:not(.card) {
  margin-top: var(--section-gap); padding-top: var(--rule-gap);
  border-top: var(--bw-3) solid var(--ink);
}
/* Each formula stays on one line; lines wrap only between formulas. The size follows the width
   of the formulas block (container units), so the longest formula, about 14 px wide per px of
   font size, always fits, down to 320 px phones. */
code { font-family: var(--font-num); font-weight: 600; font-size: min(var(--fs-lg), 7cqi); white-space: nowrap; }

/* ---------- Calculator ---------- */
.card { background: var(--paper); border: var(--bw-2) solid var(--ink); padding: var(--space-4); }

.toggle { display: grid; grid-template-columns: 1fr 1fr; border: var(--bw-2) solid var(--ink); }
.toggle button {
  position: relative; min-height: var(--tap); border: 0; border-bottom: var(--bw-bar) solid transparent; padding-top: var(--bw-bar); margin: 0; cursor: pointer;
  font: 700 var(--fs-md)/1 var(--font-num); letter-spacing: var(--track); text-transform: uppercase;
  background: var(--paper); color: var(--ink);
}
.toggle button + button { border-left: var(--bw-2) solid var(--ink); }
.toggle button[aria-pressed="false"]:hover { background: var(--fill); }
.toggle button[aria-pressed="false"]:active { background: var(--press); }
/* Selected: ink fill (dark on light, light on dark) + accent bar. Selected vs unselected
   background contrast: 18.4:1 light (#141414 vs #fff), 15.2:1 dark (#f2f1ec vs #1b1b1a). */
.toggle button[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-bottom-color: var(--accent); cursor: default; }
/* A 2 px dark line between the fill and the accent bar keeps the bar visible on the
   light dark-mode fill (in light mode it merges with the ink fill) */
.toggle button[aria-pressed="true"]::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; border-top: var(--bw-2) solid var(--readout-bg);
}
.toggle button:focus-visible { outline-offset: calc(-1 * (var(--bw-3) + var(--space-1))); }
.toggle button[aria-pressed="true"]:focus-visible { outline-color: var(--paper); }

.fields { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); margin-top: var(--space-5); }
.field label, .r-label {
  display: block; font: 600 var(--fs-sm)/var(--lh-snug) var(--font-num); letter-spacing: var(--track); text-transform: uppercase;
}
.field label { margin-bottom: var(--space-2); }
.input-wrap { position: relative; }
.input-wrap input {
  width: 100%; height: var(--control-h); padding: 0 var(--space-3);
  font: 600 var(--fs-xl)/1 var(--font-num); font-variant-numeric: tabular-nums;
  color: var(--ink); background: var(--paper); border: var(--bw-2) solid var(--ink);
}
.input-wrap input:hover { background: var(--bg); }
.input-wrap input:focus { background: var(--paper); }
.input-wrap.has-unit input { padding-right: var(--space-7); }
.input-wrap input[aria-invalid="true"] { border-color: var(--error); border-width: var(--bw-3); }
.unit {
  position: absolute; right: var(--space-3); top: 50%; transform: translateY(-50%); pointer-events: none;
  font: 600 var(--fs-md)/1 var(--font-num); color: var(--muted);
}
.help { margin: var(--space-2) 0 0; font-size: var(--fs-sm); color: var(--muted); line-height: var(--lh-snug); }
.error { margin: var(--space-2) 0 0; font-size: var(--fs-sm); color: var(--error); font-weight: 600; }
/* Empty errors stay rendered (zero height) so their live region is always present */
.error:empty { margin: 0; }

/* Readout: black panel, like a meter display. When empty it keeps its size and shows nothing. */
.results {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--space-2) var(--space-3);
  margin-top: var(--space-5); padding: var(--space-4);
  background: var(--readout-bg); color: var(--readout-ink);
  container-type: inline-size; /* readout text scales with the panel, not the window */
}
.results.is-empty > * { visibility: hidden; }
.r-value:empty::before { content: "\00a0"; }
.result { display: flex; flex-direction: column; min-width: 0; grid-column: span 2; }
.results .r-label { color: var(--readout-muted); font-size: clamp(var(--fs-2xs), 4.8cqi, var(--fs-xs)); letter-spacing: var(--track-sm); }
/* Long values shrink to stay on one line: each size is also capped by the column width
   divided by the character count (--chars, set by script.js; condensed figures are ~0.55 em). */
.r-value { font: 600 min(var(--fs-xl), 8cqi, calc(52cqi / var(--chars, 1)))/var(--lh-value) var(--font-num); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.r-pitch { grid-column: span 6; padding-bottom: var(--space-2); border-bottom: var(--bw-1) solid var(--readout-rule); }
.r-pitch .r-value { font-size: min(var(--fs-result), 32cqi, calc(170cqi / var(--chars, 1))); font-weight: 700; line-height: 1; color: var(--accent); }

/* Metric: angle + slope large at equal weight; pitch + multiplier in the secondary row */
.results.is-metric .r-angle { order: 1; grid-column: span 3; }
.results.is-metric .r-slope { order: 2; grid-column: span 3; }
.results.is-metric .r-pitch { order: 3; grid-column: span 3; padding-bottom: 0; border-bottom: 0; }
.results.is-metric .r-mult  { order: 4; grid-column: span 3; }
.results.is-metric .r-angle, .results.is-metric .r-slope { padding-bottom: var(--space-2); border-bottom: var(--bw-1) solid var(--readout-rule); }
.results.is-metric .r-angle .r-value,
.results.is-metric .r-slope .r-value {
  font-size: min(var(--fs-result-pair), 15cqi, calc(80cqi / var(--chars-pair, 1))); font-weight: 700; line-height: 1; color: var(--accent);
}
.results.is-metric .r-pitch .r-value { font-size: min(var(--fs-xl), 8cqi, calc(80cqi / var(--chars, 1))); font-weight: 600; line-height: var(--lh-value); color: inherit; }

/* Rafter row */
.rafter { margin-top: var(--space-5); padding-top: var(--space-5); border-top: var(--bw-2) dashed var(--rule); }
.rafter-result { margin-top: var(--space-5); padding-left: var(--space-3); border-left: var(--bw-bar) solid var(--accent); }
.rafter-value { display: block; font: 700 var(--fs-2xl)/var(--lh-tight) var(--font-num); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.caveat { margin: var(--space-2) 0 0; font-size: var(--fs-sm); color: var(--muted); }

/* Diagram: drafting sheet with a light grid; reserved space, no layout shift */
.diagram-box {
  margin-top: var(--space-5); width: 100%; aspect-ratio: 16 / 9; max-height: var(--diagram-max-h);
  border: var(--bw-2) solid var(--ink);
  background: var(--grid-img) 0 0 / var(--tile) var(--tile), var(--paper);
}
.diagram-box svg { display: block; width: 100%; height: 100%; }
/* Sizes below are SVG user units (the drawing is 400 x 225 and scales with the box) */
#diagram text, .parts-svg text {
  font: 600 18px var(--font-num); font-variant-numeric: tabular-nums; fill: var(--ink);
  paint-order: stroke; stroke: var(--paper); stroke-width: 5px; stroke-linejoin: miter; stroke-miterlimit: 2;
}
#diagram .d-note { font-weight: 700; letter-spacing: var(--track-sm); }
.d-shape { fill: var(--fill); stroke: var(--ink); stroke-width: 3; stroke-linejoin: miter; }
.d-dim, .d-ext, .d-tick, .d-arc { fill: none; stroke: var(--ink); }
.d-dim { stroke-width: 1.25; }
.d-ext { stroke-width: 1; }
.d-tick { stroke-width: 2; }
.d-arc { stroke-width: 1.5; }

/* Parts-of-a-roof drawing: same sheet, lines and labels as the calculator diagram */
.figure {
  border: var(--bw-2) solid var(--ink); padding: var(--space-2);
  background: var(--grid-img) 0 0 / var(--tile) var(--tile), var(--paper);
}
.parts-svg { display: block; width: 100%; height: auto; }
.parts-svg text { font-size: 20px; } /* user units: about 14 px on a 320 px phone */
.p-wall { fill: var(--fill); stroke: var(--ink); stroke-width: 2; }
.p-plate { fill: var(--ink); }
.p-rafter { fill: none; stroke: var(--ink); stroke-width: 4; stroke-linejoin: miter; }
.p-level { stroke: var(--muted); stroke-width: 1; stroke-dasharray: 6 4; }

/* ---------- Ad slots ---------- */
/* Fixed size so a real ad can never grow the box. Intended units: 300x250 or 336x280 on
   mobile (280 px tall box), 728x90 at >= 1024 px (90 px box). */
.ad-slot {
  position: relative; height: var(--ad-h); overflow: hidden; margin: var(--section-gap) 0 0;
  background: var(--ad-bg); border: var(--bw-1) dashed var(--rule);
}
.ad-label { position: absolute; top: var(--space-1); left: var(--space-2); font-size: var(--fs-xs); color: var(--muted); }

/* ---------- Sections below the tool ---------- */
/* Each spans the full content width; on phones they stack:
   .layout-figure text beside a diagram (text left, diagram right)
   .layout-side   heading in a narrow left column, text in the wide right column
   .layout-steps  numbered steps across the width
   .layout-table  full-width reference table
   .layout-list   heading on top, full-width list of rows (FAQ) */
.steps { list-style: none; margin: 0; padding: 0; counter-reset: step; }
.steps > li { counter-increment: step; padding: var(--space-3) 0; border-top: var(--bw-1) solid var(--rule); }
.steps > li::before {
  content: counter(step); display: block; margin-bottom: var(--space-2);
  font: 700 var(--fs-2xl)/1 var(--font-num); font-variant-numeric: tabular-nums;
}
.steps p { margin: 0; }
.note { margin: var(--block-gap) 0 0; padding-left: var(--space-3); border-left: var(--bw-3) solid var(--ink); }

/* Text beside the parts drawing */
.figure-text h3 { margin-top: var(--sub-above); }
.figure-text p:first-child { margin-top: 0; }
.figure { margin-top: var(--block-gap); }
.parts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-2) var(--space-4); margin: 0; }
.parts dt { font: 600 var(--fs-md)/var(--lh-body) var(--font-num); }
.parts dd { margin: 0; }

/* Formulas: the block is the container that sizes the code (see code above) */
.formulas { container-type: inline-size; }
.formulas h3 { margin-top: var(--sub-above); }
.formulas h3:first-child { margin-top: 0; }
.formulas p { margin: 0 0 var(--para-gap); }
/* Grid cells can't collapse margins outward, so their last child ends flush (no stacked gaps) */
.formulas > :last-child, .figure-text > :last-child { margin-bottom: 0; }

/* Chart */
.table-wrap { overflow-x: auto; }
.chart { width: 100%; border-collapse: collapse; font: 600 var(--fs-md)/var(--lh-tight) var(--font-num); font-variant-numeric: tabular-nums; }
.chart th, .chart td { padding: var(--space-2) var(--space-4); text-align: right; }
.chart th:first-child, .chart td:first-child { text-align: left; }
.chart thead th {
  background: var(--readout-bg); color: var(--readout-ink);
  font-size: var(--fs-sm); letter-spacing: var(--track); text-transform: uppercase;
}
.chart tbody tr { border-bottom: var(--bw-1) solid var(--rule); }
.chart tbody tr:nth-child(even) { background: var(--paper); }
.chart td:first-child { font-weight: 700; }

/* FAQ: native details/summary, the whole row toggles; +/− shows state as well as the answer */
/* 1 px dividers between rows only: none above the first question (the section divider is above the heading) */
.faq-list details + details { border-top: var(--bw-1) solid var(--ink); }
summary {
  display: block; list-style: none; cursor: pointer; position: relative;
  min-height: var(--tap); padding: var(--space-3) var(--space-7) var(--space-3) 0;
}
summary::-webkit-details-marker { display: none; }
summary::marker { content: ""; }
summary::after {
  content: "+"; position: absolute; right: var(--space-2); top: 50%; transform: translateY(-50%);
  font: 700 var(--fs-2xl)/1 var(--font-num);
}
summary:hover h3 { text-decoration: underline; text-decoration-thickness: var(--bw-2); text-underline-offset: var(--underline-offset); }
summary:active { background: var(--fill); }
details[open] > summary::after { content: "−"; }
details[open] > summary { padding-bottom: var(--space-2); } /* answer sits 8 px below the question */
/* Focus ring drawn inside the row, flush with the divider edges */
summary:focus-visible { outline-offset: calc(-1 * var(--bw-3)); }
summary h3 { display: inline; margin: 0; }
details p { margin: 0 0 var(--space-4); }

/* ---------- Footer ---------- */
.site-footer { margin-top: var(--section-gap); padding: var(--space-5) 0 var(--space-6); border-top: var(--bw-3) solid var(--ink); font-size: var(--fs-sm); }
.site-footer p { margin: 0; }
.site-footer a { display: inline-flex; align-items: center; min-height: var(--tap); }

/* ---------- Privacy page: one full-width column, same width and padding as the main page ---------- */
.prose .updated { margin-top: 0; color: var(--muted); font-size: var(--fs-sm); }
/* The whole policy is one section; its topics are subsections. One section break (divider plus
   the section gap) between the title area and the first topic; after that, topic headings use
   the subheading style with 32 px above and 8 px below, and no dividers. */
.prose h2 {
  font-size: var(--fs-lg); font-weight: 600;
  margin: var(--space-6) 0 var(--space-2); padding: 0; border: 0;
}
.prose h2:first-of-type { margin-top: var(--section-gap); padding-top: var(--rule-gap); border-top: var(--bw-3) solid var(--ink); }
.prose h2 ~ p { margin-bottom: .75em; }
.prose h2 ~ p:has(+ ul) { margin-bottom: var(--space-2); } /* list sits 8 px below its lead-in */
.prose ul { list-style: square; margin: var(--space-2) 0; padding-left: var(--space-5); }
.prose li + li { margin-top: var(--space-1); }

/* ---------- Breakpoints ---------- */

/* Phones: compact table cells so the 4-column chart fits 375 px without its own scrollbar */
@media (max-width: 700px) {
  .chart th, .chart td { padding-left: var(--space-3); padding-right: var(--space-3); }
  .chart thead th { letter-spacing: var(--track-sm); }
}

/* Tablet and up: footer items spread across the full width */
@media (min-width: 701px) {
  .site-footer .wrap { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--space-1) var(--space-5); }
}

/* Desktop: inputs | readout | drawing */
@media (min-width: 1024px) {
  h1 { font-size: var(--fs-4xl); margin-top: var(--space-5); }
  .card {
    display: grid; gap: 0 var(--space-6); padding: var(--space-5);
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr) minmax(0, 1.6fr);
    grid-template-areas: "toggle toggle diagram" "fields results diagram" "rafter rafter diagram";
    grid-template-rows: auto auto 1fr;
    align-items: start;
  }
  .toggle { grid-area: toggle; }
  .fields { grid-area: fields; }
  .results { grid-area: results; }
  .rafter { grid-area: rafter; }
  /* The drawing fills the whole right column: the sheet stretches to the card's height */
  .diagram-box { grid-area: diagram; align-self: stretch; margin-top: 0; aspect-ratio: auto; max-height: none; min-height: var(--diagram-min-h); }
  .ad-slot { height: var(--ad-h-desktop); }
  /* Heading left, text right; the top rule spans both columns */
  .layout-side { display: grid; grid-template-columns: var(--side-col) minmax(0, 1fr); gap: 0 var(--space-7); align-items: start; }
  .layout-side > h2 { grid-column: 1; margin-bottom: 0; }
  .layout-side > :not(h2) { grid-column: 2; }
  .layout-side > p:first-of-type { margin-top: 0; }
  /* Text left, drawing right; the heading spans both */
  .layout-figure { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 var(--space-7); align-items: start; }
  .layout-figure > h2 { grid-column: 1 / -1; }
  .layout-figure .figure { margin-top: 0; }
  /* Numbered steps side by side across the full width */
  .steps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0 var(--space-6); }
  /* Metric: angle and slope stack (equal size) so they can be the largest numbers on the page */
  .results.is-metric .r-angle, .results.is-metric .r-slope { grid-column: span 6; }
  .results.is-metric .r-angle .r-value,
  .results.is-metric .r-slope .r-value { font-size: min(var(--fs-result-pair), 30cqi, calc(170cqi / var(--chars-pair, 1))); }
}

/* ---------- Windows high contrast / forced colours ---------- */
@media (forced-colors: active) {
  .toggle button[aria-pressed="true"] { forced-color-adjust: none; background: Highlight; color: HighlightText; border-bottom-color: Highlight; }
  .toggle button[aria-pressed="false"] { border-bottom-color: Canvas; }
  .toggle button[aria-pressed="true"]::after { display: none; }
  .r-pitch .r-value, .results.is-metric .r-angle .r-value, .results.is-metric .r-slope .r-value { color: CanvasText; }
  .rafter-result { border-left-color: CanvasText; }
  .d-shape { fill: Canvas; stroke: CanvasText; }
  .d-dim, .d-ext, .d-tick, .d-arc { stroke: CanvasText; }
  #diagram text, .parts-svg text { fill: CanvasText; stroke: Canvas; }
  .p-wall { fill: Canvas; stroke: CanvasText; }
  .p-plate { fill: CanvasText; }
  .p-rafter, .p-level { stroke: CanvasText; }
  .figure { background: Canvas; }
  .diagram-box { background: Canvas; }
  .site-header::after { background: CanvasText; }
  /* Text backplates are taller than a line-height of 1; give big values room so they don't cover the labels */
  .r-value, .r-pitch .r-value,
  .results.is-metric .r-angle .r-value, .results.is-metric .r-slope .r-value { line-height: 1.25; }
}

/* ---------- Print: result, drawing and reference content in black on white ---------- */
@media print {
  :root {
    --bg: #ffffff; --paper: #ffffff; --ink: #000000; --muted: #333333; --rule: #999999;
    --accent: #000000; --fill: #eeeeee; --readout-bg: #ffffff; --readout-ink: #000000;
    --readout-muted: #333333; --readout-rule: #999999;
    --grid-img: none;
  }
  .site-header, .site-footer, .ad-slot, .toggle, .help, .error, .rafter .field { display: none; }
  .results { border: var(--bw-1) solid var(--ink); }
  .card, .results, .diagram-box, .chart tr, details { break-inside: avoid; }
  .card { border-width: var(--bw-1); }
  h2, h3 { break-after: avoid; }
  summary::after { content: none; } /* answers are opened for printing by script.js */
}
