/* Archetypes web system: the page base. Load after ../tokens.css. Every value is a token; this file arranges them.
   Holds: reset, type roles as classes, the grid, cap trimming, spacing utilities named by token, reduced motion. */

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; background: var(--page); -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--page); color: var(--ink); font: 400 var(--body)/var(--body-lh) var(--sans); }
/* The page never scrolls sideways: the door's glow and reflection may pass the viewport's edge where the margin is
   narrow (390 to 1279), and are cut there, by the viewport, never by their section. clip, not hidden, so sticky pins
   keep working. */
html, body { overflow-x: clip; }
h1, h2, h3, h4, p, figure, blockquote, ul, ol, dl, dd { margin: 0; padding: 0; }
ul, ol { list-style: none; }
a { color: inherit; }
img, svg, canvas, video { display: block; }
button, input, select, textarea { font: inherit; color: inherit; }
[hidden] { display: none !important; }
/* Lenis 1.3.11's own rules, so smooth scroll never fights the page. */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }

/* ---------- Cap trimming: vertical gaps run from cap height to baseline, so a 48 px gap is 48 px of white
   between the letters (system section 2). Every heading, paragraph and label is trimmed. ---------- */
h1, h2, h3, h4, p, figcaption, blockquote, .trim,
.display, .statement, .h3, .lead, .body, .ui, .label, .cap, .quote, .big { text-box: trim-both cap alphabetic; }
/* A trimmed box cuts its descenders when it also clips (an ellipsis, overflow hidden): such text opts out. */
.untrim, .ellipsis { text-box: none; }
.ellipsis { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Trimmed text in a clipping box: the trim lets ascenders and descenders hang 3 to 4 px outside the text's box, so a box
   that clips them (overflow hidden, a clip-path) holds its text 4 px in from each clipped edge. .clipbox does it without
   moving anything: 4 px of padding inside, the same 4 px taken back outside. A box that animates to 0 tall (a disclosure)
   puts the 4 px on its text instead, so it can close. */
.clipbox { overflow: hidden; padding-block: var(--s1); margin-block: calc(-1 * var(--s1)); }

/* ---------- Type roles (system section 4, sizes from tokens.css; section 17 steps display to 64 / 56 / 48 / 40). */
.display { font: var(--w-display) var(--display)/var(--display-lh) var(--serif); letter-spacing: var(--display-ls); }
.statement { font: 400 var(--statement)/var(--statement-lh) var(--serif); letter-spacing: var(--statement-ls); text-wrap: balance; }
.h3 { font: 400 var(--h3)/var(--h3-lh) var(--serif); letter-spacing: var(--h3-ls); text-wrap: balance; }
.quote { font: 400 var(--quote)/var(--quote-lh) var(--serif); }
.lead { font: 400 var(--lead)/var(--lead-lh) var(--sans); color: var(--ink-2); text-wrap: pretty; }
.body { font: 400 var(--body)/var(--body-lh) var(--sans); color: var(--ink-2); text-wrap: pretty; }
.ui { font: 400 var(--ui)/var(--ui-lh) var(--sans); }
.label { font: 500 var(--label)/var(--label-lh) var(--sans); color: var(--ink); }
.cap { font: 400 var(--label)/var(--label-lh) var(--sans); color: var(--ink-3); font-feature-settings: var(--num-features); }
.num { font-family: var(--sans); font-weight: 500; font-feature-settings: var(--num-features); }
.big { font: 500 var(--num-large)/1 var(--sans); letter-spacing: var(--num-ls); font-feature-settings: var(--num-features); }
em { font-style: normal; color: var(--ink); }

/* ---------- The grid (section 17): margins 20 / 40 / 80 / 140 / 160 / 240 / 320, content 1120 at 1440 and 1360
   from 1920, 12 columns from 768 and 6 below, 12 px gutters. Column n of 12 starts at (n - 1) x (column + 12). */
.wrap { width: min(var(--content-max), 100% - 2 * var(--margin)); margin-inline: auto; }
.grid { display: grid; grid-template-columns: repeat(var(--columns), minmax(0, 1fr)); column-gap: var(--gutter); }
.full { grid-column: 1 / -1; }

/* ---------- Spacing utilities, named by token. Margins and paddings on the block axis, and row gaps. ---------- */
.mt-s1 { margin-top: var(--s1); } .mt-s2 { margin-top: var(--s2); } .mt-s3 { margin-top: var(--s3); } .mt-s4 { margin-top: var(--s4); }
.mt-s5 { margin-top: var(--s5); } .mt-s6 { margin-top: var(--s6); } .mt-s7 { margin-top: var(--s7); } .mt-s8 { margin-top: var(--s8); }
.mt-s9 { margin-top: var(--s9); } .mt-s10 { margin-top: var(--s10); } .mt-s11 { margin-top: var(--s11); } .mt-s12 { margin-top: var(--s12); }
.mt-s13 { margin-top: var(--s13); } .mt-s14 { margin-top: var(--s14); }
.mb-s1 { margin-bottom: var(--s1); } .mb-s2 { margin-bottom: var(--s2); } .mb-s3 { margin-bottom: var(--s3); } .mb-s4 { margin-bottom: var(--s4); }
.mb-s5 { margin-bottom: var(--s5); } .mb-s6 { margin-bottom: var(--s6); } .mb-s7 { margin-bottom: var(--s7); } .mb-s8 { margin-bottom: var(--s8); }
.mb-s9 { margin-bottom: var(--s9); } .mb-s10 { margin-bottom: var(--s10); } .mb-s11 { margin-bottom: var(--s11); } .mb-s12 { margin-bottom: var(--s12); }
.mb-s13 { margin-bottom: var(--s13); } .mb-s14 { margin-bottom: var(--s14); }
.pt-s9 { padding-top: var(--s9); } .pt-s10 { padding-top: var(--s10); } .pt-s11 { padding-top: var(--s11); } .pt-s12 { padding-top: var(--s12); }
.pt-s13 { padding-top: var(--s13); } .pt-s14 { padding-top: var(--s14); }
.pb-s9 { padding-bottom: var(--s9); } .pb-s10 { padding-bottom: var(--s10); } .pb-s11 { padding-bottom: var(--s11); } .pb-s12 { padding-bottom: var(--s12); }
.pb-s13 { padding-bottom: var(--s13); } .pb-s14 { padding-bottom: var(--s14); }
.gap-s2 { row-gap: var(--s2); } .gap-s3 { row-gap: var(--s3); } .gap-s4 { row-gap: var(--s4); } .gap-s5 { row-gap: var(--s5); }
.gap-s6 { row-gap: var(--s6); } .gap-s7 { row-gap: var(--s7); } .gap-s8 { row-gap: var(--s8); } .gap-s9 { row-gap: var(--s9); }
/* Section steps that halve under 1024 (tokens: --section, --section-wide, --statement-space, --interval). */
.sec { padding-block: var(--section); } .sec-wide { padding-block: var(--section-wide); }
.sec-statement { padding-block: var(--statement-space); } .interval { margin-top: var(--interval); }

/* ---------- Reveal by line (core.js A.reveal): an 8 px rise and a fade over 640 ms on the ease curve. Frozen pages
   and reduced motion show the settled state. ---------- */
[data-js] .rv { opacity: 0; transform: translateY(8px); transition: opacity var(--t3) var(--ease), transform var(--t3) var(--ease); }
[data-js] .rv.in, [data-frozen] .rv { opacity: 1; transform: none; }
[data-frozen] .rv { transition: none; }

/* ---------- Reduced motion: every transition and animation off, every settled state shown (tokens set the
   durations to 0; this catches anything a page writes by hand). ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0ms !important; animation-duration: 0ms !important; animation-iteration-count: 1 !important; }
  [data-js] .rv { opacity: 1; transform: none; }
}

/* Visually hidden, for labels screen readers need and the page does not show. */
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* ---------- The rotating word (core.js A.rotor): a slot as wide as the widest word, the words stacked in it, the
   full stop after the current word. The old word fades over 160 ms; the new one rises 8 px over 320 ms. ---------- */
.rot { position: relative; display: inline-block; white-space: nowrap; text-box: none; }
.rot .sizer { visibility: hidden; }
.rot .rw { position: absolute; left: 0; top: 0; opacity: 0; transform: translateY(8px); }
.rot .rw.on { opacity: 1; transform: none; transition: opacity var(--t2) var(--ease), transform var(--t2) var(--ease); }
.rot .rw.off { opacity: 0; transform: none; transition: opacity var(--t1) var(--ease); }

/* ---------- Sticky head beside rows (atlas A3 and D2; round nine, from the validation page): the head in columns 1 to
   4 held 120 under the top of the view while the rows in columns 5 to 12 pass. Under 1024 the head stands over the rows,
   64 above them. Markup: <div class="wrap grid split"><div class="split-head">..</div><div class="split-rows">..</div></div> */
.split { align-items: start; }
.split-head { grid-column: 1 / span 4; position: sticky; top: var(--s11); padding-right: var(--s8); }
.split-head .body { margin-top: var(--s5); }
.split-rows { grid-column: 5 / span 8; }
@media (max-width: 1023px) {
  .split-head { grid-column: 1 / -1; position: static; max-width: 34em; padding: 0; }
  .split-rows { grid-column: 1 / -1; margin-top: var(--s9); }
}

/* ---------- Lineage rows (atlas D3): a 1 px line on top; left, columns 1 to 5: the years, the name in the serif, who
   publishes it, a label, two sentences; right, columns 7 to 12: a label over a product card. Rows 24 under their line
   and 80 apart. Markup: <div class="lin"><div class="grid lin-row"><div class="lin-l">..</div><div class="lin-r">..</div></div></div> */
.lin { display: grid; }
.lin-row { box-shadow: inset 0 1px 0 var(--line); padding-block: var(--s5) var(--s10); align-items: start; }
.lin-row:last-child { padding-bottom: 0; }
.lin-l { grid-column: 1 / span 5; }
.lin-r { grid-column: 7 / span 6; }
.lin-y { color: var(--ink-2); }
.lin-n { margin-top: var(--s5); font: 400 24px/1.3 var(--serif); letter-spacing: -0.005em; text-wrap: balance; }
.lin-by { margin-top: var(--s3); color: var(--ink-2); }
.lin-l .label { margin-top: var(--s6); }
.lin-l .body { margin-top: var(--s3); max-width: 30em; }
.lin-r > .label { margin-bottom: var(--s4); }
@media (max-width: 1023px) { .lin-l, .lin-r { grid-column: 1 / -1; } .lin-r { margin-top: var(--s7); } }
