/* zamorak.ai: page layout on top of the design system (assets/ds/zamorak.css, vendored by
   tools/sync_design_system.py). Components come from the system; this file only lays out the home
   page, the page for labs and the 404, in the system's tokens. */

html { scroll-padding-top: calc(var(--z-header-h) + 1rem); }
:root { --page-green: light-dark(#237a4a, #6cc492); }   /* the one green on the page: the dollar signs, and "de-identified" on the ticket */

/* Author display values beat the UA's [hidden] rule; keep hidden things hidden. */
[hidden] { display: none !important; }

/* Touch: the header's logo and button, the nav's and the footer's links at 44 px or more to the finger
   (their look unchanged: the room is added around them). */
@media (pointer: coarse) {
  .z-header .z-logo, .z-header .z-btn--sm { min-height: 2.75rem; }
  .z-nav a:not(.z-btn), .z-footer__meta a, .page-mail a { padding-block: 0.75rem; }   /* inline: the padding widens the target and moves nothing */
  .z-footer__meta a { margin-block: -0.75rem; }   /* a flex item there, so its padding would add height: taken back */
  .z-footer__meta a { min-width: 44px; text-align: center; }   /* the narrower UI sans left "For labs" at 43 px */
}

/* Skip link: off-screen until focused. */
.page-skip { position: absolute; top: 0.75rem; left: var(--z-gutter); z-index: 20; transform: translateY(-300%); }
.page-skip:focus { transform: none; }

/* ---------- section heads (the archetype's Part A helpers): centered, a sentence heading at most two lines wide ---------- */
.page-head { display: grid; justify-items: center; gap: var(--z-space-4); margin-bottom: var(--z-space-12); text-align: center; }
.page-head h2 { max-width: 30ch; }
.page-head .z-lede { justify-self: center; text-align: left; }   /* the heading centered; its subtext a left-aligned block under the center */
@media (min-width: 600px) { .page-head .z-lede { text-wrap: balance; } }   /* its lines evened so no word is left alone; not on a phone, where evening a left-aligned block leaves its right side empty (owner, 2026-10-13) */

/* ---------- Data: four cards in a row from 1100 px, the exchange figure, and the terms on a card under it as three ringed bullets under their heading ---------- */
@media (min-width: 1100px) { .z-cards { grid-template-columns: repeat(4, 1fr); } }
.page-exchange { margin: 0 auto; max-width: 72rem; }   /* the exchange figure, first in its section, the terms card under it */
#exchange { padding-top: calc(var(--z-section) / 2); }   /* close under the value section's line */
/* The sequence runs in the SVG's own timeline (animateMotion and animate in the markup, in user units, so it
   holds in every browser): the record's way out from under the company and in under the Veil (0 to 1.4 s),
   the copies' way out and under the labs (1.4 to 3 s), the dollar signs' way from the labs under the Veil
   (from 3.2 s, each a little after the last), one larger dollar sign's way from the Veil under the company
   (5.1 to 6.4 s). site.js pauses the timeline and seeks it with the scroll, over the figure's passage through
   the viewport; without script it plays once on its own; under reduced motion it stays at the first frame. The system's own scroll-driven
   animation on the copies is switched off. */
.page-exchange .z-exchange__copy { animation: none; transform: none; }
.page-exchange .z-exchange__cash text, .page-exchange .z-exchange__payout text { font: 40px var(--z-serif); letter-spacing: 0; text-transform: none; fill: var(--page-green); }
.page-exchange .z-exchange__payout text { font-size: 60px; }   /* 1.5 times the others */
@media (max-width: 720px) { .page-exchange .z-exchange__cash text { font-size: 80px; } .page-exchange .z-exchange__payout text { font-size: 120px; } }
/* The figure's two labels are set in the SVG's own units, so they shrink with it: sized by band so they
   stand at 11 px or more on every screen (a phone draws the figure at under a third of its size). */
@media (max-width: 560px) { .page-exchange .z-exchange > text { font-size: 2.6rem; } }
@media (min-width: 561px) and (max-width: 820px) { .page-exchange .z-exchange > text { font-size: 1.75rem; } }
@media (min-width: 821px) and (max-width: 1150px) { .page-exchange .z-exchange > text { font-size: 1.1rem; } }

.page-terms { max-width: 48rem; margin: var(--z-space-12) auto 0; }   /* the terms on a card, centered under the figure */
.z-card.page-terms h3, .z-card.page-terms h2 { font-size: clamp(1.9rem, 1.3rem + 1.8vw, 3rem); line-height: 1.1; text-align: center; text-wrap: balance; }   /* between the card titles and the section heads (more specific than the card titles' rule below, which otherwise wins) */
.page-terms__list { display: grid; gap: var(--z-space-4); margin: 0; padding: 0; list-style: none; font-size: var(--z-text-md); line-height: 1.45; color: var(--z-ink-2); }
.page-terms__list li { position: relative; padding-left: 1.75rem; }
.page-terms__list li::before { content: ""; position: absolute; left: 0.2rem; top: 0.55em; width: 0.5rem; height: 0.5rem; border: var(--z-hair) solid var(--z-ink); border-radius: 50%; }   /* a small ring, the disk's motif */
@media (min-width: 1100px) { .z-card h3 { font-size: clamp(1.5rem, 1.1rem + 0.6vw, 2rem); } }   /* four abreast: every title on one line */
.z-card--specimen h3 { text-align: center; }   /* the data cards' titles centered */
.page-head--split { display: grid; gap: var(--z-space-6) clamp(2rem, 5vw, 4rem); }
@media (min-width: 900px) {
  .page-head--split { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: end; }
  .page-head--top { align-items: start; }
}
@media (min-width: 900px) { .page-head--even { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }   /* a long heading: half the width for it */

#value { padding-top: calc(var(--z-section) / 2); }   /* closer to the cards above it (owner, 2026-10-12) */
/* ---------- Value: one label over the three discs (the system's, equal), and the subheader with its line under them, centered ---------- */
.page-value__label { margin-bottom: var(--z-space-6); font-family: var(--z-ui); font-size: var(--z-text-xs); letter-spacing: 0; text-transform: none; text-align: center; color: var(--z-ink-3); }
.page-value__close { display: grid; justify-items: center; gap: var(--z-space-3); margin-top: var(--z-space-12); text-align: center; }
.page-value__close h3 { font-size: var(--z-text-xl); }
.page-value__close .z-lede { justify-self: center; width: fit-content; max-width: 100%; text-align: left; }   /* left-aligned; the break is in the markup, so the block is exactly as wide as its longer line and sits centered under the subheader in every browser */
@media (max-width: 719px) { .page-value__close .z-lede br { display: none; } }   /* on a phone the sentence wraps on its own */
@media (min-width: 600px) and (max-width: 719px) { .page-value__close .z-lede { text-wrap: balance; } }

/* The ambient layers (the page's Hopf canvas, 03's percolation, 05.1's cusp drift, 06's tiling), the
   live line, the 06 copy block and the footer's colophon are all the system's; nothing here. */

/* ---------- Process: steps carry h3 (the outline runs h2, h3), sized as the system's step h4 ---------- */
/* The path's nodes larger than the system's (2rem): 3.25rem rings with the number in the serif at lede size, plain 1 to 4 (no
   leading zero), the line through their centers, in both layouts. */
.z-step { --page-node: 3.25rem; padding-left: calc(var(--page-node) + 1rem); }
.z-step::before { content: counter(z-step); width: var(--page-node); height: var(--page-node); font-family: var(--z-serif); font-size: var(--z-text-lg); }   /* the numbers in the serif */
/* Stacked (under 800 px): the node centered on the plate beside it (15rem tall), the line from its foot to the next node's head. */
.z-step::before { top: calc((15rem - var(--page-node)) / 2); }
.z-step::after { left: calc(var(--page-node) / 2); top: calc((15rem + var(--page-node)) / 2); bottom: calc(-1 * (var(--z-space-8) + (15rem - var(--page-node)) / 2)); }
@media (min-width: 800px) {
  .z-step { padding: calc(var(--page-node) + 1.25rem) 0 0; }
  .z-step::before { left: calc(50% - var(--page-node) / 2); top: 0; }
  .z-step::after { left: calc(50% + var(--page-node) / 2); right: calc(var(--page-node) / 2 - 50% - var(--z-space-6)); top: calc(var(--page-node) / 2); bottom: auto; }
}
.z-step h3 { margin-bottom: var(--z-space-2); padding-top: 0.2rem; font-size: var(--z-text-lg); line-height: 1.25; letter-spacing: 0; text-align: center; }   /* centered under its plate in both layouts */
@media (min-width: 800px) { .z-step p { font-size: 1.125rem; line-height: 1.55; text-align: center; text-wrap: balance; } }   /* four abreast: each line centered under its title, at a size that holds its sentence in two lines, evened so no word is left alone */

/* ---------- three short notes in a row (the team's traits) ---------- */
.page-cols { display: grid; gap: var(--z-space-12) clamp(2rem, 4vw, 3rem); }
@media (min-width: 900px) { .page-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.page-col { display: grid; align-content: start; gap: var(--z-space-4); }
.page-col .z-eyebrow { margin-bottom: 0; }
.page-col p { max-width: var(--z-measure); color: var(--z-ink-2); }

/* ---------- Privacy: the mark alone under the heading, centered on it and large, level with the second guarantee at the right (in the ink band its paper half turns ink and its ink half paper, as the tokens flip) ---------- */
.page-privacy__mark { display: block; justify-self: center; width: clamp(6rem, 11vw, 9rem); height: clamp(6rem, 11vw, 9rem); margin-top: var(--z-space-4); color: var(--z-ink); }   /* on a phone, as much room over it (with the heading's leading) as the grid's gap under it */
@media (min-width: 900px) { .page-privacy__mark { margin-top: 5rem; } }   /* beside the guarantees, lower; on a phone, closer under the heading */

.page-guarantees { font-family: var(--z-serif); font-size: var(--z-text-xl); line-height: 1.25; letter-spacing: 0; }   /* over the guarantees, a size up from the subheads */
@media (max-width: 899px) { .page-guarantees { font-size: 2rem; } }   /* stacked under the heading on a phone: nearly its size */

/* ---------- Privacy: the heading at the left, the guarantees at the right; then the line beside the ticket (the line left, the ticket right, centered on each other) ---------- */
#privacy { padding-block: calc(var(--z-section) * 0.8) calc(var(--z-section) * 0.55); }   /* the band tighter, more so at its foot, so the whole of it fits a 1080p screen */
.page-privacy { display: grid; gap: var(--z-space-8); align-items: center; margin-top: var(--z-space-8); }   /* the line and the ticket closer under the guarantees */
@media (min-width: 900px) { .page-privacy { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: clamp(2rem, 4vw, 4rem); } }
@media (min-width: 600px) { .page-privacy .z-lede { text-wrap: balance; } }   /* on a phone the line fills its width */
.page-privacy .z-pseudo__text { padding-top: var(--z-space-4); padding-bottom: var(--z-space-3); }   /* the ticket shorter: less paper over and under the record (the script still holds the box at the taller of its two states) */
.page-privacy .z-pseudo { container: page-ticket / inline-size; }   /* its own width decides whether the bar's two items share a line (below) */
.page-privacy .z-pseudo__bar { padding-block: 0.6rem; }
/* The words at the right of the ticket's bar: while the demo plays (z-pseudo.js sets data-state="playing"
   from the first frame to the last), "de-identification in progress" in the accent on a gray box whose
   background pulses; once it has played (data-state="after"), "de-identified" in green on the box, still.
   Each fades in and out with its state; hidden before, at rest, and without script. */
.page-stamp { display: inline-grid; }
.page-stamp__box { grid-area: 1 / 1; justify-self: end; display: inline-block; padding: 0.35em 0.6em; border-radius: var(--z-radius); background: var(--z-bg-sunk); font-size: var(--z-text-sm); color: var(--z-accent); opacity: 0; transition: opacity 400ms var(--z-ease); }
.page-stamp__box--done { color: var(--page-green); }
.z-pseudo[data-state="playing"] .page-stamp__box--on { opacity: 1; animation: page-pulse 1.4s ease-in-out infinite; }
.z-pseudo[data-state="after"] .page-stamp__box--done { opacity: 1; }
@keyframes page-pulse { 50% { background-color: transparent; } }   /* the box alone pulses; the words stay */
@media (prefers-reduced-motion: reduce) { .page-stamp__box { transition: none; animation: none !important; } }
/* A ticket too narrow for the label and the stamp on one line (a phone, or the column beside the line just
   past 900px): the stamp takes a line of its own under the label, and its two boxes center on it. */
@container page-ticket (max-width: 35rem) {
  .page-stamp { flex-basis: 100%; }
  .page-stamp__box { justify-self: center; }
}

/* ---------- The page for labs: the heading with its lede, the terms beside it, on the cusp band ---------- */
.page-lead { display: grid; align-content: start; }
.page-lead__lede { margin-top: var(--z-space-6); }
/* The lead, centered as the home page's section heads are: the heading in two lines, the lede and the sentence on
   structure centered under it, the two buttons under them. */
.page-hero { margin-bottom: 0; }
.page-hero h1 { max-width: 22ch; }
@media (max-width: 599px) { .page-hero h1 br { display: none; } }   /* the break after "data" is in the markup; on a phone the first line does not fit, so the heading wraps on its own */
.page-hero .z-lede { max-width: 50ch; margin-top: var(--z-space-4); text-align: center; text-wrap: balance; }
.page-hero__sub { max-width: 58ch; font-size: var(--z-text-md); line-height: 1.45; color: var(--z-ink-2); text-wrap: balance; }
.page-hero__actions { justify-content: center; margin-top: var(--z-space-6); }
#labs { padding-bottom: calc(var(--z-section) / 2); }   /* the sources close under the lead */
#license { padding-top: 0; }   /* the license card close under the source cards */
#license .page-terms { margin-top: 0; }
@media (min-width: 900px) { .z-cards.page-cards--3 { grid-template-columns: repeat(3, 1fr); } }   /* the three sources abreast */
.page-listing .z-g { margin-left: calc(var(--i, 0) * 1.1rem); }   /* a greeked listing: each rule a line of code, indented by its depth */

/* ---------- Process: the close under the steps: a subhead, the flow figure (hairlines, as the exchange figure), a subhead ----------
   The streams run in the SVG's timeline (animateMotion along each line's path): each dot and each small
   sheet travels its line and comes round every 5 s, phased apart. site.js pauses the timeline and seeks it
   with the scroll (two rounds over the figure's passage); under reduced motion it holds them still part-way,
   spread along the lines. */
.page-flow-fig { margin: 5rem auto 0; max-width: 64rem; padding: var(--z-space-2) var(--z-space-6) var(--z-space-4); border: 2px solid var(--z-line-strong); border-radius: var(--z-radius-lg); }   /* on a plate: a rounded gray border, 2px; its top lower (less padding, the margin above grown by the same), its foot where it was */
.page-flow { display: block; width: 100%; height: auto; color: var(--z-ink); overflow: visible; }
.page-flow [stroke], .page-flow .page-flow__shape, .page-flow .page-flow__band, .page-flow .page-flow__edge, .page-flow .page-flow__thread, .page-flow .page-flow__gate, .page-flow .page-flow__row, .page-flow rect { vector-effect: non-scaling-stroke; }
.page-flow__edge { stroke: currentColor; opacity: 0.45; }
.page-flow__shape { fill: var(--z-surface); stroke: currentColor; }
.page-flow__band { fill: none; stroke: currentColor; opacity: 0.6; }
.page-flow__gate { fill: currentColor; stroke: none; }   /* the gate: a rounded square in ink */
.page-flow__thread { stroke: var(--z-bg); }   /* the line where it runs in front of the gate's far half: in paper, to show on the ink */
.page-flow__keyhole { fill: var(--z-bg); stroke: none; }   /* its keyhole, in paper */
.page-flow__row { stroke: currentColor; stroke-width: 2; opacity: 0.3; }
.page-flow__row--log { stroke-width: 1.5; }
.page-flow__smoke circle { fill: none; stroke: currentColor; }   /* its smoke, rings rising */
.page-flow__led { fill: #237a4a; }   /* the server's lights; the markup flips each between this green and a red */
.page-flow__lock { fill: none; stroke: currentColor; }
.page-flow__node { fill: var(--z-surface); stroke: currentColor; }
.page-flow__dot { fill: currentColor; opacity: 0.7; }
.page-flow text { font: 0.8125rem var(--z-ui); letter-spacing: 0; text-transform: none; fill: var(--z-ink-3); }
/* As the exchange figure's: the labels sized by band to stand at 11 px or more. On a phone the plate's
   padding is cut so the figure is as wide as it can be, each label says one word (the state after the
   dot is dropped: it would run off the plate), and the three under a shape step down clear of it. */
@media (min-width: 561px) and (max-width: 900px) { .page-flow text { font-size: 1.35rem; } }
@media (max-width: 560px) {
  .page-flow-fig { padding-inline: var(--z-space-3); }
  .page-flow text { font-size: 2.75rem; }
  .page-flow__more { display: none; }
  .page-flow__label { transform: translateY(14px); }
}
.page-close { margin-top: 10.5rem; }   /* the head over the figure, built as the sections' heads (.page-head): centered, its line under it, the same room under it before the plate as a section's head leaves before its cards */
.page-close__line { max-width: 44ch; font-size: var(--z-text-xl); line-height: 1.2; text-wrap: balance; }
.page-close + .page-flow-fig { margin-top: 0; }
@media (max-width: 720px) { .page-close { margin-top: 5rem; margin-bottom: var(--z-space-8); } }   /* stacked, the steps end close above: half the room */

#team { padding-top: calc(var(--z-section) * 0.75); }   /* the close of the process sits lower; the team not quite a full section away (owner, 2026-10-12) */

/* ---------- Team: a line under the heading, three cards abreast from 900 px (each centered: the name, the role, the line, the degree), a second line under them ---------- */
.page-team__text, .page-close__sub { width: fit-content; max-width: 100%; text-align: left; }   /* the two text blocks, left-aligned; the breaks are in the markup, so each block is exactly as wide as its longest line and sits centered */
.page-team__text--after { display: block; margin: var(--z-space-12) auto 0; }
@media (max-width: 999px) { .page-team__text br, .page-close__sub br { display: none; } }   /* narrower, the sentences wrap on their own */
@media (min-width: 600px) and (max-width: 999px) { .page-team__text, .page-close__sub { text-wrap: balance; } }
@media (min-width: 600px) and (max-width: 999px) { .page-close__sub { max-width: 45ch; } .page-head > .page-team__text { max-width: 51ch; } }   /* between a phone and the desktop a wrapped block would fill the column and stand at its left edge under a centered heading: held to its two lines' width, so it stays a block under the center */
.page-people { display: grid; gap: var(--z-space-4); margin: 0; padding: 0; list-style: none; }
@media (min-width: 900px) { .page-people { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.page-person { grid-template-rows: auto auto 1fr auto; align-content: stretch; justify-items: center; gap: var(--z-space-2); padding: var(--z-space-8) var(--z-space-6); text-align: center; }   /* the cards stand equal; the line takes the free row, so the degrees sit on one line across the three */
.page-person h3 { font-size: var(--z-text-xl); }
.page-person__role { color: var(--z-ink-2); }   /* the role in the same face and size as the line under it (owner, 2026-10-12) */
.page-person p:not([class]) { align-self: start; max-width: 40ch; margin-top: var(--z-space-4); color: var(--z-ink-2); text-wrap: balance; }   /* wide enough for each line to hold in two lines abreast */
.page-person__edu { margin-top: var(--z-space-2); font-family: var(--z-ui); font-size: var(--z-text-sm); color: var(--z-ink-2); }

/* ---------- Contact ---------- */
.page-contact { display: grid; gap: clamp(2rem, 5vw, 4rem); }
@media (min-width: 900px) { .page-contact { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); } }
.page-contact__lead { display: grid; align-content: start; gap: var(--z-space-6); }
.page-contact__lead .z-eyebrow { margin-bottom: 0; }
.page-mail { font-family: var(--z-mono); font-size: var(--z-text-sm); color: var(--z-ink-2); }
.page-send { gap: var(--z-space-4) var(--z-space-6); }
.page-sheet { padding: clamp(1.25rem, 3vw, 2rem); border: var(--z-hair) solid var(--z-line); border-radius: var(--z-radius-lg); background: var(--z-surface); }   /* the form on a sheet, like the cards */

/* ---------- Footer: no rule between the contact section and the colophon (the system draws a hairline on top of its footer; owner, 2026-10-12); and once the fibers have converged and the mark is revealed, the canvas (by then one circle on the mark's rim) fades out as the mark fades in, so the mark stands without an outline ---------- */
.z-footer__hold > .z-ambient--hopf { transition: opacity 1400ms var(--z-ease); }
.z-footer__hold:has(.z-mark-large.is-revealed) > .z-ambient--hopf { opacity: 0; }
.z-footer { border-top: 0; }
@media (prefers-reduced-motion: reduce) { .z-footer__hold > .z-ambient--hopf { transition: none; } }

/* ---------- 404 ---------- */
.page-404 { display: grid; align-content: center; min-height: calc(100vh - var(--z-header-h)); padding-block: var(--z-section); }
.page-404 .z-container { display: grid; justify-items: start; gap: var(--z-space-8); }
.page-404 .z-eyebrow { margin-bottom: 0; }
.page-404__path { color: var(--z-ink); overflow-wrap: anywhere; }
.page-404__at:has(> .page-404__path:empty) { display: none; }   /* no script: no path to show */
