/* stefankovalik.com: base, components, Home and the case pages.
   Values from the v5 design system (docs/plans/2026-10-29-design-system-v5-spec.md) and Home study 2.
   Colors come only from tokens.css (the one site color and its palette). */
:root {
  --display: larken, "Iowan Old Style", Georgia, serif;
  --sans: mundial, "Helvetica Neue", Arial, sans-serif;
  /* Larken Bold (700) is not in the web font kit (xnh4mor has 400 and 900), so a 700 request renders as Black until the kit has it; Black stays on the nav's name and each page's
     title and hero line (wave 1, Stefan's Figma comment 1999274136: "make all the instances of larken black ... bold instead", the title and name aside). */
  --display-weight: 700;
  --display-black: 900;
  --side: 48px;
  /* Motion, from the Studio Sauvé read (docs/refs/2026-10-30-studiosauve-motion.md): one curve, three durations
     for a state change and one for an entrance. */
  --ease: cubic-bezier(.2, .8, .2, 1);
  --zoom: 1.04;
  --dur-fill: 200ms;
  --dur-fade: 300ms;
  --dur-move: 450ms;
  --dur-rise: 900ms;
  --dur-reveal: 600ms;  /* the theme toggle's radial reveal (the 2026-10-24 plan: View Transitions, 600 ms from the button) */
  --dur-slide-in: 360ms;   /* a menu or panel coming in on --ease-slide-in, an eighth of its travel at most per 60 Hz frame */
  --dur-slide-out: 280ms;  /* going out on --ease-slide-out */
  /* Service Station V7's eases: an entrance decelerates, a change there and back eases both ways, an exit accelerates away; a sheet
     slides in on a curve that builds up and settles long, and out on an even acceleration. Today's --ease and --dur-* stay (docs/motion.md). */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-in: cubic-bezier(0.7, 0, 0.84, 0);
  --ease-slide-in: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-slide-out: cubic-bezier(0.3, 0, 1, 1);
  /* The z stack: the page's layers by name. */
  --z-under: -1;      /* the glass behind a block's text */
  --z-trail: 1;       /* the cursor trail, over the tunnel and under the glass */
  --z-raised: 2;      /* a block over the trail, the hero card */
  --z-menu: 20;       /* the phone menu */
  --z-panel: 20;      /* the color panel */
  --z-header: 30;     /* the sticky bar */
  --z-progress: 40;   /* the reading bar, over the bar */
  --z-skip: 50;       /* the skip link */
  --z-viewer: 70;     /* the piece viewer (a non-modal view under the header) */
  --z-viewer-foot: 72; /* its Previous and Next bar under 1024 px */
  --z-viewer-nav: 75; /* the site's header while a piece is open: over the viewer */
  --z-viewer-step: 1; /* its arrows over the image */
  --z-viewer-bar: 2;  /* its count and Close, pinned while it scrolls */
  --dur-snap: 700ms;
}
@media (max-width: 1023px) { :root { --side: 24px; } }
@media (max-width: 767px) { :root { --side: 0px; } }
/* Above 1920 px the rail keeps its 1920 width and centers (plan 2026-11-04, Task 1): --side grows by half of what the window adds; backgrounds that pad with --side still span it. */
@media (min-width: 1921px) { :root { --side: calc(48px + (100vw - 1920px) / 2); } }

*, *::before, *::after { box-sizing: border-box; }
html { background: var(--bg); -webkit-text-size-adjust: 100%; }
body { margin: 0; padding: 20px; background: var(--bg); color: var(--text); font: 400 var(--fs-body)/var(--lh-body) var(--sans); }
h1, h2, h3, p, figure, ul { margin: 0; }
img { display: block; max-width: 100%; }
a { color: inherit; }
hr { border: 0; border-top: 1px solid var(--border); margin: 0; width: 100%; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.skip { position: absolute; left: -999px; top: 8px; z-index: var(--z-skip); background: var(--accent); color: var(--accent-text); padding: 8px 16px; }
.skip:focus { left: 8px; }
[data-needs-js] { display: none !important; }
.js [data-needs-js] { display: flex !important; }
[hidden] { display: none !important; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
button:disabled { cursor: default; opacity: 0.4; }

/* Type */
/* .sub is a type role; on a page's body (the 404 and the Resume take body.sub for their subpage colors) it would set the whole page, header and footer
   included, in Larken, so it applies to elements only. */
.display, .sub:not(body) { font-family: var(--display); font-weight: var(--display-weight); }
.display { font-size: var(--fs-display); line-height: var(--lh-display); }
/* The Results line, one size on every case page (R45): 40/46 from 1440 px, 30/35 at 390, between them in step. */
.display.results-line { font-size: clamp(30px, calc(30px + (100vw - 390px) * 0.009524), 40px); line-height: clamp(35px, calc(35px + (100vw - 390px) * 0.010476), 46px); }
.sub:not(body) { font-size: var(--fs-sub); line-height: var(--lh-sub); }
.lead { font-size: var(--fs-lead); line-height: var(--lh-lead); }
.small { font-size: var(--fs-small); line-height: var(--lh-small); }
.label { font-size: var(--fs-label); line-height: var(--lh-label); letter-spacing: 0; text-transform: none; font-weight: 400; color: var(--text-dim); }
.label.ink { color: var(--accent-ink); }

/* Blocks: one opener (rule and label row), two container levels at most */
.opener { display: flex; align-items: center; gap: 24px; margin-bottom: 16px; }
.opener hr { flex: 1; }
.corners { display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.inline-link, .linklike { color: var(--accent-ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.arrow-link { display: inline-flex; gap: 8px; align-items: center; font-size: var(--fs-label); line-height: var(--lh-label); font-weight: 700; letter-spacing: 0; color: var(--accent-ink); text-decoration: none; }

/* Buttons: the 2024 pair, square, with a 2px outline */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 56px; padding: 0 24px; font-size: var(--fs-small); line-height: 20px; font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase; text-decoration: none; border: 2px solid var(--accent); }
.btn-fill { background: var(--accent); color: var(--accent-text); }
.btn-fill:hover { background: var(--accent-hover); }
/* No shadow on the hero's main button (Stefan, 2026-11-02: "I also said no shadow for the main cta on the hero section."). */
.statement .btn-fill { box-shadow: none; }
/* Light on dark and dark on light, no shadow (Stefan, 2026-11-02: "Button in the hero second doesn't need a color shadow"). */
.btn-solid { background: var(--text); color: var(--bg); border-color: var(--text); }
.btn-solid:hover { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.btn:active { opacity: 0.8; }
/* A pressed filled button dims its fill and its text together, 10% darker, not 20% toward the page: faded toward the page the text lost its 4.5:1 on the accent (3.47:1 on Red by Day, R45). */
.btn-fill:active { opacity: 1; filter: brightness(0.9); }
/* The outlined button, text-colored (the contact row, R43): the border and the label are the page's text, and a hover fills it. */
.btn-outline { color: var(--text); border-color: var(--text); }
.btn-outline:hover { background: var(--text); color: var(--bg); }

/* Nav */
.nav { display: flex; align-items: center; gap: 32px; padding: 32px var(--side); min-height: 90px; }
/* The links stand at the left, after the name on a subpage (Stefan's comment #58; his words 10 of 2026-11-02 put them back after Task 1 moved them); Day / Night and the color keep the right. */
.nav-name { font-family: var(--display); font-weight: var(--display-black); font-size: 16px; line-height: 22px; text-decoration: none; }
.home .nav-name { display: none; }
.nav-links { display: flex; gap: 32px; font-size: var(--fs-small); line-height: 20px; margin-right: auto; }
.nav-links a, .footer-links a { text-decoration: none; }
/* Hover underlines (feedback plan 2, B3): a 1 px line in --accent-ink draws from the left (scaleX) on --dur-move and --ease and goes back the same way; the current page's link keeps it drawn; --u-dur is 0s with ?effects=off. */
:root[data-effects="off"] { --u-dur: 0s; }
:is(.nav-links a, .footer-links a, .crumb a, .fact .links a, .mini-tab span, .parts .part-name, .pfd-work-title) { position: relative; }
:is(.nav-links a, .footer-links a, .crumb a, .fact .links a, .mini-tab span, .parts .part-name)::after, .pfd-work-title::before { content: ""; position: absolute; left: 0; right: 0; bottom: -3px; }
:is(.nav-links a, .footer-links a, .crumb a, .fact .links a, .mini-tab span, .parts .part-name, .card-name)::after, .pfd-work-title::before { height: 1px; background: var(--accent-ink); transform: scaleX(var(--u, 0)); transform-origin: left; transition: transform var(--u-dur, var(--dur-move)) var(--ease); pointer-events: none; }
.card-name { width: fit-content; max-width: 100%; }
.card-name::after { content: ""; display: block; margin-bottom: -1px; }  /* in flow: the stretched link's ::after owns the card's positioning */
.parts .part-name, .fact .links a, .pfd-work-title { justify-self: start; }
:is(.nav-links a:hover, .nav-links a[aria-current="page"], .footer-links a:hover, .crumb a:hover, .fact .links a:is(:hover, :focus-visible), .parts a:hover .part-name, .mini-tab:hover span, .card:is(:hover, :focus-within) .card-name, a.pfd-work:is(:hover, :focus-visible) .pfd-work-title) { --u: 1; }
.nav-controls { display: flex; gap: 32px; align-items: center; font-size: var(--fs-small); line-height: 20px; margin-left: auto; }
/* The bar is sticky in CSS alone and never hides (plan 2026-11-04, Task 2); its glass is ::before, the stage color at 85% (its texts need 4.5:1, smoke 52) with a blur, out to the window's edges. --nav-h feeds scroll-padding. */
:root { --nav-h: 90px; --clear: 80px; }  /* --clear: the first block's text sits this far under the bar: 48 px of page for the cursor effect and the glass's 32 past the text */
@media (max-width: 767px) { :root { --nav-h: 68px; --clear: 72px; } }
html { scroll-padding-top: calc(var(--nav-h) + 16px); }
.nav { position: sticky; top: 0; z-index: var(--z-header); }
.nav::before { content: ""; position: absolute; inset: -20px -20px 0 -20px; z-index: var(--z-under); pointer-events: none; background: var(--bg); background: color-mix(in srgb, var(--bg) 85%, transparent); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
/* View transitions (plan 2026-11-02, Task 5): the theme toggle's radial reveal (ui.mjs animates the new view's clip-path) and a
   card's image growing into its case hero (the two share a view-transition-name; a cross-document transition). Both are off
   under reduced motion; ?effects=off skips them from the head. */
html[data-vt="theme"]::view-transition-old(root), html[data-vt="theme"]::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
html[data-vt="theme"]::view-transition-old(root) { z-index: var(--z-trail); }
html[data-vt="theme"]::view-transition-new(root) { z-index: var(--z-raised); }
html[data-vt="color"]::view-transition-group(root), html[data-vt="color"]::view-transition-old(root), html[data-vt="color"]::view-transition-new(root) { animation-duration: var(--dur-fade); animation-timing-function: var(--ease); } /* a color change: a plain crossfade, the page's old color to its new */
/* A theme or color change keeps only the root's group: a named element (card images, case heroes) would paint over the root snapshot's nav. */
html[data-vt="theme"] [style*="view-transition-name"], html[data-vt="color"] [style*="view-transition-name"] { view-transition-name: none !important; }
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }
::view-transition-group(*) { animation-duration: var(--dur-move); animation-timing-function: var(--ease); }
::view-transition-group(root) { animation-duration: var(--dur-fade); }
.day-night { display: inline-flex; gap: 8px; font-size: var(--fs-small); line-height: 20px; }
.day-night { --dn-dim: 0.64; }
/* In the bar the dimmed word is stronger: 64% fell under 4.5:1 over the glass (smoke 52). */
.nav .day-night { --dn-dim: 0.72; }
.day-night .dn-day, .day-night .dn-night { opacity: var(--dn-dim); }
[data-theme="light"] .dn-day, :root:not([data-theme="light"]) .dn-night { opacity: 1; }
.color-open { display: inline-flex; gap: 12px; align-items: center; }
.color-dot { width: 16px; height: 16px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent-ink); }
.menu-open { display: none; }
.menu-open svg { display: block; width: 20px; height: 16px; }
.panel { position: absolute; right: var(--side); top: 76px; z-index: var(--z-panel); width: 300px; display: grid; gap: 12px; padding: 24px; background: var(--surface); border: 1px solid var(--border); }
/* Tint and Brightness (Stefan's comment #54): the thumb is a color dot; the track shows the colors it reaches from here. */
.slider { display: grid; gap: 8px; }
.slider input { -webkit-appearance: none; appearance: none; width: 100%; height: 24px; margin: 0; background: transparent; cursor: pointer; }
.slider input::-webkit-slider-runnable-track { height: 8px; border-radius: 4px; background: var(--track, var(--border)); }
.slider input::-moz-range-track { height: 8px; border-radius: 4px; background: var(--track, var(--border)); }
.slider input::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 20px; height: 20px; margin-top: -6px; border: 0; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--text); }
.slider input::-moz-range-thumb { width: 20px; height: 20px; border: 0; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--text); }
@keyframes slide-in { from { opacity: 0; transform: translateY(-16px); } }
@keyframes slide-out { to { opacity: 0; transform: translateY(-16px); } }
.panel:not([hidden]), .menu:not([hidden]) { animation: slide-in var(--dur-slide-in) var(--ease-slide-in) both; }
.panel[data-closing], .menu[data-closing] { animation: slide-out var(--dur-slide-out) var(--ease-slide-out) both; }
.menu { display: none; }
@media (max-width: 767px) {
  .nav { padding: 12px 0; min-height: 68px; gap: 16px; }
  .nav-links { display: none; }
  /* As the Home 390 mockup: the color and a three-line menu, 44 px each, 4 px apart, flush right. */
  .menu-open { display: inline-flex; min-width: 44px; min-height: 44px; align-items: center; justify-content: center; font-size: 0; }
  .nav-controls { gap: 4px; }
  .color-open { min-width: 44px; min-height: 44px; justify-content: center; font-size: 0; gap: 0; }
  .menu:not([hidden]) { display: grid; position: absolute; top: 68px; left: 0; right: 0; z-index: var(--z-menu); gap: 8px; padding: 16px; background: var(--surface); border: 1px solid var(--border); font-size: 22px; line-height: 44px; }
  .menu .day-night { font-size: 22px; line-height: 44px; }
  .panel { right: 0; left: 0; width: auto; top: 68px; }
}

/* Home: masthead (wave 1, R59 item 4: the role as a readable line under the name, the place and the kind small beside it; at 390 and under 1024 the place and the kind stand above the name,
   Stefan's placement, "sf bay area and selected work"). Name 14.4cqw Black; role Mundial 28/36 (20/28 under 768); the pair 14 px, sentence case, untracked. */
.masthead { container-type: inline-size; padding: var(--clear) var(--side) 0; display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name name" "role where" "rule rule"; align-items: end; }
.masthead h1 { grid-area: name; font-family: var(--display); font-weight: var(--display-black); font-size: 14.4cqw; line-height: 0.9; letter-spacing: -0.01em; white-space: nowrap; min-width: 0; }
@container (max-width: 400px) { .masthead h1 { font-size: 28cqw; white-space: normal; line-height: 0.95; } }
.masthead .role { grid-area: role; font-size: 28px; line-height: 36px; }
.masthead .where { grid-area: where; display: flex; gap: 24px; color: var(--text-dim); }
.masthead hr { grid-area: rule; }
.nw { white-space: nowrap; }  /* the role line keeps "e-commerce" whole at 390, as the draft's non-breaking hyphen does */
@media (max-width: 1023px) {
  .masthead { grid-template-columns: minmax(0, 1fr); grid-template-areas: "where" "name" "role" "rule"; }
  .masthead .where { justify-content: space-between; }
}
@media (max-width: 767px) { .masthead .role { font-size: 20px; line-height: 28px; } }

/* Home: the hero (Stefan, 2026-10-31; plan 2026-10-31-hero-shader-palettes-cursor, R1 and R2): the tunnel edge to edge behind the statement text, drawn with premultiplied alpha so each theme's stage
   shows through; the text sits in a glass card over its bottom fade. No stacking context: the trail (z-index 1) runs over the tunnel and under the card (z-index 2). */
.statement { position: relative; margin: 40px -20px 0; padding: 48px calc(20px + var(--side)); min-height: 680px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); grid-template-rows: 1fr; column-gap: 32px; align-items: center; }
.hero-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.hero-fade { position: absolute; left: 0; bottom: 0; width: 100%; height: 40%; background: linear-gradient(to bottom, transparent, var(--bg)); pointer-events: none; }
.statement-text { container-type: inline-size; position: relative; z-index: var(--z-raised); grid-column: 1; grid-row: 1; display: grid; gap: 32px; align-content: start; padding: 64px 48px; background: color-mix(in srgb, var(--bg) 20%, transparent); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); border-radius: 4px; }
/* By Night the tunnel is near white at some moments of its flight, and the statement's light text needs 4.5:1 on what is behind it (README, smoke section 52): the card's tint goes from 20% to 70%, the blur and the shape unchanged. By Day it holds as it is. */
:root:not([data-theme="light"]) .statement-text { background: color-mix(in srgb, var(--bg) 70%, transparent); }
.lead-line { font-family: var(--display); font-weight: var(--display-black); font-size: min(54px, 15.6cqw); line-height: 62px; text-wrap: balance; }
.lead-sub { margin-top: -8px; font-family: var(--display); font-style: italic; font-weight: 400; font-size: var(--fs-lead-sub); line-height: var(--lh-lead-sub); text-wrap: balance; }
.cta { display: flex; gap: 16px; flex-wrap: wrap; }
/* The sub line's link over the moving tunnel: the accent ink fails 4.5:1 at the tunnel's bright moments (1.9:1 measured), so the words stay the text color and the underline carries the accent. */
.lead-sub .inline-link { color: inherit; text-decoration-color: var(--accent-ink); text-decoration-thickness: 2px; }
@media (min-width: 1600px) { .lead-line { font-size: min(96px, 15.6cqw); line-height: 96px; letter-spacing: -1px; } .statement { grid-template-columns: minmax(0, 1fr) minmax(0, 1.44fr); } }
@media (max-width: 1023px) { .statement { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; min-height: 560px; align-content: end; } }
@media (max-width: 767px) { .lead-line { font-size: min(34px, 15.6cqw); line-height: 40px; } .lead-sub { margin-top: -16px; } .statement { padding-top: 24px; padding-bottom: 24px; } .statement-text { padding: 40px 24px; } .cta .btn { flex: 1 1 100%; } }

/* The dithered cursor trail (cursor.mjs, a port of aurochs.agency's v3.css rule): page wide and out of the way of clicks, over
   the page and the tunnel and under the glass card and the dots (z-index 2). By day it multiplies, by night it screens. */
.dither-canvas { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: var(--z-trail); mix-blend-mode: screen; }
[data-theme="light"] .dither-canvas { mix-blend-mode: multiply; opacity: 0.95; }
@media print { .dither-canvas { display: none; } }

/* The trail under glass (plan 2026-11-01-cursor-under-glass; aurochs-site v3.css): each content block rises over the trail on the page color at 72% with a 12px blur, only while
   the trail runs (cursor.mjs sets data-trail); the glass is the block's ::before, inset by --glass-top and --glass-bottom (glassInsets(), feedback plan 2 B2) and takes no room. */
[data-trail="on"] main > :not(.statement, .progress, .band, .contact, hr, dialog, .after-band),
[data-trail="on"] body > footer { position: relative; z-index: var(--z-raised); }
[data-trail="on"] main > :not(.statement, .progress, .band, .contact, hr, dialog, .after-band)::before,
[data-trail="on"] body > footer::before { content: ""; position: absolute; inset: var(--glass-top, 0px) 0 var(--glass-bottom, 0px); z-index: var(--z-under); pointer-events: none; background: var(--bg); background: color-mix(in srgb, var(--bg) 72%, transparent); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); border-radius: 4px; }
[data-trail="on"] main > .band, [data-trail="on"] main > .contact { position: relative; z-index: var(--z-raised); }


/* Home: what I do */
.what { padding: var(--space-section) var(--side) 0; }
.what p { max-width: 1000px; }
.what .lead { font-family: var(--display); font-weight: var(--display-weight); font-size: var(--fs-statement); line-height: var(--lh-statement); text-wrap: balance; }  /* PFD, feedback plan 2 B1: bigger, Larken, upright */

/* Home: selected work, one row per entry. Hover and the small-screen pattern follow Studio Sauvé's project rows
   (Stefan's Figma comment #50; docs/refs/2026-10-30-studiosauve-motion.md): the row fills, the name slides 14 px and
   the arrow fades and slides in, while the thumbnail stays put. Below 1024 the rows go compact and drop the types. */
.selected { padding: var(--space-section) var(--side); }
.selected .corners { padding-bottom: 16px; }
.rows-list { list-style: none; padding: 0; margin: 0; border-top: 1px solid var(--border); }
.work-row { display: grid; grid-template-columns: 120px minmax(0, 1.6fr) minmax(0, 1.1fr) 150px 24px; gap: 32px; align-items: center; padding: 16px 0; border-bottom: 1px solid var(--border); text-decoration: none; transition: background-color var(--dur-fill) ease, opacity var(--dur-rise) var(--ease), transform var(--dur-rise) var(--ease); }
.work-row img { width: 120px; height: 120px; object-fit: cover; object-position: top; }
.row-name { font-family: var(--display); font-weight: var(--display-weight); font-size: var(--fs-row-name); line-height: var(--lh-row-name); transition: transform var(--dur-move) var(--ease); }
.work-row .arrow { color: var(--accent-ink); font-size: 18px; opacity: 0; transform: translateX(-10px); transition: opacity var(--dur-fade) ease, transform var(--dur-move) var(--ease); }
.work-row:hover, .work-row:focus-visible { background: var(--accent-surface); }
.work-row:hover .row-name, .work-row:focus-visible .row-name { transform: translateX(14px); }
.work-row:hover .arrow, .work-row:focus-visible .arrow { opacity: 1; transform: none; }
/* The entrance (Stefan's go, 2026-10-30): ui.mjs marks the rows still below the fold, and each rises 32 px and fades in
   as it reaches the viewport. Being marked is a cut, so a row never fades out first. Without the script, in print and
   under reduced motion every row stands in place. */
.work-row[data-rise] { opacity: 0; transform: translateY(32px); transition: none; }
@media print { .work-row { transition: none; } .work-row[data-rise] { opacity: 1; transform: none; } }
@media (max-width: 1023px) { .work-row { grid-template-columns: 48px minmax(0, 1fr) auto 24px; gap: 16px; } .work-row img { width: 48px; height: 48px; } .row-types { display: none; } }
@media (max-width: 767px) { .work-row { grid-template-columns: 44px minmax(0, 1fr) 24px; gap: 4px 16px; } .work-row picture, .work-row .pfd-art { grid-row: 1 / span 2; } .work-row img { width: 44px; height: 44px; } .row-name, .row-years { grid-column: 2; } .work-row .arrow { grid-column: 3; grid-row: 1; } }
/* Touch: nothing waits on hover, so the arrow goes and the rows close up without its column. */
@media (hover: none) { .work-row .arrow { display: none; } }
@media (hover: none) and (max-width: 1023px) { .work-row { grid-template-columns: 48px minmax(0, 1fr) auto; } }
@media (hover: none) and (max-width: 767px) { .work-row { grid-template-columns: 44px minmax(0, 1fr); } }
/* Reduced motion: the fill and the arrow still show (the global rule below makes them a cut); nothing slides. */
@media (prefers-reduced-motion: reduce) { .work-row .arrow, .work-row:hover .row-name, .work-row:focus-visible .row-name { transform: none; } .work-row[data-rise] { opacity: 1; transform: none; } }

/* Home: the band (the one color moment). Four layouts, each chosen for what fits there (docs/design/2026-11-04-band-adapt.md):
   1280 and up: the picker column (headline, line, picker, link, at most 680 wide) beside the bag (at most 560), the pair centered in the band when the window is wider than it needs (1304 px of content, 680 and 560 and the gap: the red still runs edge to edge);
   768 to 1279: the headline and the line across the band, the picker beside the bag under them, the link under the picker;
   under 768: headline, line, bag (240), picker across the column, link. */
.band { display: grid; grid-template-columns: minmax(480px, 1fr) minmax(0, 560px); column-gap: 64px; row-gap: 32px; align-items: center; padding: 96px max(var(--side), calc((100% - 1304px) / 2)); background: var(--accent); color: var(--accent-text); }
.band .display { text-wrap: balance; }
.band-demo { display: grid; gap: 24px; }
.band-head { display: grid; gap: 24px; }
.band-head p { max-width: 640px; }
.band-demo .inline-link { justify-self: start; color: inherit; }
/* The picker is the band's container: what its own width allows (the Night and Day tiles side by side, the color-now row) follows its width, not the window's. */
.mini-demo { container-type: inline-size; display: grid; gap: 16px; width: 100%; max-width: 480px; padding: 24px; background: var(--surface); color: var(--text); border: 1px solid var(--border); }
.mini-demo .mini-field-wrap { height: 200px; }
.mini-demo .mini-full { padding: 0; }
.mini-demo .mini-field-wrap { touch-action: pan-y; }
.mini-demo .mini-thumb { touch-action: none; }
.mini-demo .mini-thumb::before { content: ""; position: absolute; inset: -10px; }
.mini-demo .mini-dots button { width: auto; flex: 0 1 44px; min-width: 0; }  /* 35 px each at 320 */
/* The picker is 480 px wide, 520 from 1600; the bag's column is the wider (feedback plan 3, D1): 560 px at most (its box 835 px tall; 640 would match the column of 1034 px that the picker's third line and edit controls make, but under the software renderer the smoke runs on, the model took 230 to 330 ms to start on a pick against section 9's 150 ms bound, as it did at 600, and passes at 560), its box about as tall as the column beside it. */
@media (min-width: 1600px) { .mini-demo { max-width: 520px; } }
.band picture { display: block; }
.band img { width: 100%; height: auto; }
/* The band's bag is live (comment #52): its box takes the column's width at its own ratio. */
.band .live-box { width: 100%; translate: 0 5.8%; }  /* the bag drawing's center (the poster's pixels over 50% alpha) sits 5.8% of the box above its middle: the box moves down by that, onto the picker column's center (Stefan, #64) */
/* 768 to 1279: the headline and the line run across both columns (at 300 px they broke the headline into four lines); under them the picker beside the bag, the bag centered on the picker and the link. */
@media (max-width: 1279px) {
  .band { grid-template-columns: minmax(380px, 1fr) minmax(0, 560px); }
  .band-demo { display: contents; }
  .band-head { grid-column: 1 / -1; grid-row: 1; }
  .band-demo > [data-needs-js] { grid-column: 1; grid-row: 2; }
  .band-demo .inline-link { grid-column: 1; grid-row: 3; }
  .band .live-box { grid-column: 2; grid-row: 2 / span 2; }
}
@media (max-width: 1023px) { .band { grid-template-columns: minmax(300px, 9fr) minmax(0, 11fr); column-gap: 32px; } }  /* the tablet keeps one proportion, the bag the wider */
/* Under 768: one column, the bag (240) before the picker, the picker across the whole column (a phone's thumb wants the room), a little closer inside. */
@media (max-width: 767px) {
  .band { grid-template-columns: minmax(0, 1fr); padding: 48px 16px; }
  .band-head { grid-column: 1; grid-row: 1; }
  .band .live-box { grid-column: 1; grid-row: 2; max-width: 240px; justify-self: center; translate: none; }
  .band-demo > [data-needs-js] { grid-column: 1; grid-row: 3; }
  .band-demo .inline-link { grid-column: 1; grid-row: 4; }
  .mini-demo { max-width: none; padding: 16px; }
  .mini-demo .mini-field-wrap { height: 176px; }
}
/* The page's gutters leave the band 288 px of text at 360 and 303 at 375; the headline's 40 px needs 305 for "It's just a simple", so under 390 it is 36 and keeps its two lines. */
@media (max-width: 389px) { .band .display { font-size: 36px; line-height: 42px; } }
.after-band { height: var(--space-section); }

/* Cards: raised, with the hard shadow stepping through the palette's own colors along the grid (wave 1, R54 item 5: steps 3, 4 and 5; the text inks the shadows were bound to
   are lightened by Night and read bright, Stefan's Figma comment 1999272525). Shadows are the cards' alone (R59 item 5): no button, panel or menu draws one. */
.cards { display: grid; grid-template-columns: minmax(0, 1fr); gap: 32px; padding: var(--space-section) var(--side); }
.cards-two { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 32px; }
.card { position: relative; display: grid; align-content: start; gap: 12px; padding: 24px; background: var(--surface); border: 1px solid var(--border); box-shadow: 8px 8px 0 var(--p3); }
.cards-two .card:nth-child(1) { box-shadow: 8px 8px 0 var(--p3); } .cards-two .card:nth-child(2) { box-shadow: 8px 8px 0 var(--p4); }
.cards-two .card:nth-child(3) { box-shadow: 8px 8px 0 var(--p5); } .cards-two .card:nth-child(4) { box-shadow: 8px 8px 0 var(--p3); }
.cards-two .card:nth-child(5) { box-shadow: 8px 8px 0 var(--p4); } .cards-two .card:nth-child(6) { box-shadow: 8px 8px 0 var(--p5); }
.card img { width: 100%; height: auto; aspect-ratio: 586 / 368; object-fit: cover; object-position: top; }
.card-featured img { aspect-ratio: 1254 / 707; }
.card-name { overflow-wrap: anywhere; font-family: var(--display); font-weight: var(--display-weight); font-size: var(--fs-card-name); line-height: var(--lh-card-name); text-decoration: none; }
.card-foot { display: flex; justify-content: space-between; gap: 16px; align-items: center; flex-wrap: wrap; }
.card a.stretch::after { content: ""; position: absolute; inset: 0; }
@media (max-width: 1023px) { .cards-two { grid-template-columns: minmax(0, 1fr); } }
/* Wave 1, Home's section heads (R59 item 2, "A8-alt"): a real Larken heading at the page's section size with a sentence-case subtitle under it in a text ink; no label row, no rule. */
.h-section { font-family: var(--display); font-weight: var(--display-weight); font-size: 40px; line-height: 48px; }
.h-sub { font-size: 16px; line-height: 24px; color: var(--ink-3); }
@media (max-width: 767px) { .h-section { font-size: 28px; line-height: 36px; } }
.more { display: grid; gap: 24px; padding: 0 var(--side) var(--space-section); }
.more .rows-list { margin-top: 0; }
.more-sub { margin-top: 40px; margin-bottom: -8px; }
.about-head { display: grid; gap: 4px; }
.about-text { display: grid; gap: 32px; justify-items: start; }
.contact-line { margin: 0; }
.cards .corners { justify-content: flex-end; }
.card-title { display: grid; gap: 20px; }
/* The year takes the ink of its shadow step (R59 item 3), pulled 30% toward the text so it keeps 4.5:1 on the card's surface (the ink alone reads 4.0 to 4.3:1 there on Night). */
.cards-two .card:nth-child(3n + 1) .card-years { color: color-mix(in srgb, var(--ink-3) 70%, var(--text)); }
.cards-two .card:nth-child(3n + 2) .card-years { color: color-mix(in srgb, var(--ink-4) 70%, var(--text)); }
.cards-two .card:nth-child(3n) .card-years { color: color-mix(in srgb, var(--ink-5) 70%, var(--text)); }
/* The card slideshows (Stefan, 2026-11-04, #59 and #60: "make this into a slideshow showing some other images from this case study in sequence"): slides.mjs lays each next image over the card's own, in DOM order (no stacking value on a slide, so the stretched link stays above them), and fades it in. */
.slide { position: absolute; inset: 0; background: var(--surface); opacity: 0; transition: opacity var(--dur-move) var(--ease); }
.slide.is-on { opacity: 1; }
.card .slide img { height: 100%; aspect-ratio: auto; }
.slides { position: relative; }
.slides-toggle { position: absolute; right: 12px; bottom: 12px; z-index: var(--z-raised); display: grid; place-items: center; width: 32px; height: 32px; padding: 0; background: var(--surface); color: var(--text); border: 1px solid var(--border); cursor: pointer; }
.slides-toggle::before { content: ""; width: 10px; height: 12px; background: linear-gradient(90deg, currentColor 0 35%, transparent 35% 65%, currentColor 65%); }
.slides-toggle[aria-pressed="true"]::before { background: currentColor; clip-path: polygon(0 0, 100% 50%, 0 100%); }
@media (pointer: coarse) { .slides-toggle { width: 44px; height: 44px; } }
/* Cognograph's card is wide (#60: "make this a wide two column card"): both columns of the grid; from 1024 the image takes 7/12 on the left and the text 5/12. */
.card-wide { grid-column: 1 / -1; }
@media (min-width: 1024px) {
  .cards-two .card-wide { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); grid-template-rows: auto auto 1fr auto; column-gap: 32px; }
  .card-wide > .slides { grid-column: 1; grid-row: 1 / span 4; }
  .card-wide > :not(.slides) { grid-column: 2; }
  .card-wide > .card-foot { align-self: end; }
}
@media (max-width: 767px) { .card { padding: 16px; } }
/* The PFD card art (docs/design/2026-11-03-pfd-hero-refine.md, section 4): a live still of the PFD hero at rest on Home's PFD card, Mehrwerk's next card and a row thumbnail. Tokens only; it sizes from its own
   box (container units), and under 300 px the names give way to the bars. The credit is set in Larken. */
.pfd-art { container-type: size; position: relative; width: 100%; aspect-ratio: 586 / 368; background: var(--bg); border: 1px solid var(--border); overflow: hidden; }
.pfd-art-square { aspect-ratio: 1; }
.pfd-art-in { position: absolute; inset: 9cqh 7cqw 9cqh 7cqw; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 4cqh; }
.pfd-art-rule { font-family: var(--display); font-weight: var(--display-weight); font-size: 7.4cqh; line-height: 1.1; color: var(--text); }
.pfd-art-stack { display: flex; flex-direction: column; justify-content: flex-end; border-bottom: max(2px, 0.6cqh) solid var(--text); width: 78%; }
.pfd-art-stack span { position: relative; display: flex; align-items: center; gap: 3cqw; flex: 1 1 0; min-height: 0; margin-top: -1px; padding: 0 3.2cqw; border: 1px solid var(--border); color: var(--text-dim); font-family: var(--display); font-weight: var(--display-weight); font-size: 5.6cqh; line-height: 1; white-space: nowrap; }
.pfd-art-stack span b { font-family: var(--sans); font-weight: 700; font-size: 3.4cqh; letter-spacing: 0.2em; }
.pfd-art-stack span[data-holding] { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.pfd-art-stack span[data-chosen] { margin-right: -6%; }
.pfd-art-note { position: absolute; right: 3.2cqw; font-family: var(--sans); font-weight: 400; font-size: 3cqh; letter-spacing: 0.2em; text-transform: uppercase; }
.pfd-art-stack span i, .pfd-art-note { font-style: normal; }
.pfd-art-credit { font-family: var(--display); font-weight: var(--display-weight); font-size: 3.4cqh; line-height: 1.2; color: var(--text-dim); }
@container (max-width: 300px) {
  .pfd-art-rule, .pfd-art-credit, .pfd-art-note, .pfd-art-stack span i { display: none; }
  .pfd-art-in { inset: 12cqh 12cqw; grid-template-rows: minmax(0, 1fr); }
  .pfd-art-stack { width: 100%; }
  .pfd-art-stack span b { font-size: 9cqh; }
}

/* About */
.about { padding: 0 var(--side) var(--space-section); display: grid; gap: 32px; }
.about-body { display: grid; grid-template-columns: 360px 1fr; gap: 64px; padding-top: 32px; align-items: center; }  /* the text centers against the fan (Stefan, #62) */
/* The portrait fan (feedback plan 3, D4; Stefan, 2026-11-04: "my headshot in color on the right ... On mobile have it be horizontal and 80% width, where it's two columns rotate it counter clockwise so it's vertical and the top color photo of me is at the top"). Seven circles (wave 1), each 180 of a 320 run with 23.3 between their starts, in
   percentages so the fan scales with its box: five back circles take the palette's steps, the sixth (the front, the last in the markup and so on top) is his headshot in natural color. One column: horizontal, 80% of the column (at most 560), the photo at the right. Two columns (the page's 1024): a quarter turn counterclockwise, 180 wide, the photo at the top. */
.fan { position: relative; width: 80%; max-width: 560px; aspect-ratio: 320 / 180; }
.fan span { position: absolute; top: 0; left: calc(var(--i) * 7.29%); width: 56.25%; aspect-ratio: 1; border-radius: 50%; overflow: hidden; isolation: isolate; background: var(--c); }  /* no outline (wave 1, Stefan's Figma comment 1999270763: "there's a black outline, I don't like that"; it was a 4 px ring in the page's color, which Night reads as black) */
.fan span picture { display: block; width: 100%; height: 100%; }
.fan span img { width: 100%; height: 100%; object-fit: cover; mix-blend-mode: multiply; transform: scale(1.06); }  /* the portrait's 8 px black rim falls outside the circle: no outline */
.fan span::after { content: ""; position: absolute; inset: 0; background: color-mix(in srgb, var(--c) 40%, var(--bg)); mix-blend-mode: lighten; }  /* shadows are the circle's own color toward the page, not black */
[data-theme="light"] .fan span::after { background: color-mix(in srgb, var(--c) 55%, #000); }  /* by Day the shadow is the circle's color darkened */
.fan .front { background: none; }
.fan .front img { mix-blend-mode: normal; }  /* the photo as it is: no tint, no floor */
.fan .front::after { content: none; }
.fan span:nth-child(1) { --i: 0; --c: var(--ink-1); } .fan span:nth-child(2) { --i: 1; --c: var(--ink-2); } .fan span:nth-child(3) { --i: 2; --c: var(--ink-3); }
.fan span:nth-child(4) { --i: 3; --c: var(--ink-4); } .fan span:nth-child(5) { --i: 4; --c: var(--ink-5); } .fan span:nth-child(6) { --i: 5; --c: var(--ink-6); } .fan span:nth-child(7) { --i: 6; }  /* the palette's six steps, then the photo; seven circles (S7) */
@media (min-width: 1024px) {
  .fan { width: 240px; aspect-ratio: 180 / 320; margin-inline: auto; }  /* 240 wide, centered in its 360 column (Stefan, #67: "center horizontally and make this larger") */
  .fan span { left: 0; width: 100%; top: calc((6 - var(--i)) * 7.29%); }
}
.about-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px; padding-top: 32px; }
.about-cols ul { list-style: none; padding: 0; display: grid; gap: 8px; margin-top: 12px; }
@media (max-width: 1023px) { .about-body { grid-template-columns: minmax(0, 1fr); gap: 32px; } .about-cols { grid-template-columns: minmax(0, 1fr); } }

/* Contact: on the page's main accent (Stefan, Figma comment 53, 2026-10-30; it was palette step 6) */
.contact { container-type: inline-size; display: grid; gap: 40px; padding: 96px var(--side) 48px; background: var(--accent); color: var(--accent-text); }
.contact .label { color: inherit; }
.contact-email { font-family: var(--display); font-weight: var(--display-weight); font-size: clamp(32px, 7.4cqw, 96px); line-height: 1; letter-spacing: -0.01em; overflow-wrap: anywhere; text-decoration: none; }
.tags { display: flex; gap: 12px; flex-wrap: wrap; }
.tags a { display: inline-flex; align-items: center; min-height: 34px; padding: 0 16px; border: 2px solid currentColor; font-size: var(--fs-label); font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase; text-decoration: none; }
.tags a:hover { background: var(--accent-text); color: var(--accent); }
.contact-foot { display: flex; justify-content: space-between; align-items: end; gap: 24px; }
.contact-foot picture { display: block; }
/* The bottle grew by about half (feedback plan 3, D3): 390 px tall from 1024, 320 from 768, 260 under 768. */
.contact-foot .live-box { flex: none; width: auto; height: 390px; }
@media (max-width: 1023px) { .contact-foot .live-box { height: 320px; } }
@media (max-width: 767px) { .contact-foot .live-box { height: 260px; } }
@media (max-width: 767px) { .contact { padding: 64px 16px 32px; } }

/* The Resume's rows are the arrow-out link rows, row N on step N of the nearest-first steps (--near-N); the 404 is below, in the w2-1 block. */
.link-rows { list-style: none; margin: 0; padding: 32px var(--side) var(--space-section); display: grid; gap: 40px; }
.link-row { display: grid; gap: 8px; justify-items: start; }
.link-row-a { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-label); line-height: var(--lh-label); font-weight: 700; letter-spacing: 0; color: var(--text); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
span.link-row-a { cursor: default; }
body.sub .link-row .arrow { color: var(--step); text-decoration: none; }
body.sub .link-row .caption { color: var(--step); }
body.sub [data-near="1"] { --step: var(--near-1); }
body.sub [data-near="2"] { --step: var(--near-2); }
body.sub [data-near="3"] { --step: var(--near-3); }
body.sub [data-near="4"] { --step: var(--near-4); }
body.sub [data-near="5"] { --step: var(--near-5); }
body.sub [data-near="6"] { --step: var(--near-6); }
/* The Resume (Stefan, 2026-11-03, his words 18; docs/content/2026-11-03-page-packs/RULINGS.md, "The Resume page"): the product resume as a page in the site's
   chrome, its text applications/2026-10-21-base-resumes/resume-product.md's. */
.resume-positioning { max-width: 1040px; }
.resume-contacts { display: grid; gap: 4px; color: var(--text-dim); }
.resume-contacts a { color: var(--text); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; white-space: nowrap; }
.resume-summary { padding: 48px var(--side) 0; }
.resume-summary-text { max-width: 760px; font-size: 22px; line-height: 32px; }
.resume-part { display: grid; gap: 24px; padding: 64px var(--side) 0; }
.resume-part .opener { margin-bottom: 0; }
main > .resume-part:last-child { padding-bottom: var(--space-section); }
.resume-xp { display: grid; gap: 8px; max-width: 880px; }
@media (min-width: 1024px) { .resume-xp { max-width: none; } }  /* the date sits at the content's right edge (Stefan, #66: "these need to align right on larger resolutions"); the bullets keep their 74ch */
.resume-xp + .resume-xp { margin-top: 8px; }
.resume-role { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 4px 24px; font-weight: 400; }
.resume-org { font-family: var(--display); font-weight: var(--display-weight); font-size: var(--fs-sub); line-height: 28px; }
.resume-when { white-space: nowrap; }
.resume-title { color: var(--text-dim); }
.resume-points { margin: 0; padding-left: 20px; display: grid; gap: 6px; }
.resume-points li::marker { color: var(--accent-ink); }
.resume-line, .resume-points li { max-width: 74ch; }
.resume-line a, .resume-points a { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
@media (max-width: 767px) { .resume-summary-text { font-size: 18px; line-height: 26px; } .resume-part { padding-top: 48px; } }

/* Footer: the nav echo (wave 1, docs/reviews/2026-11-09-footer-refactor.md sections 5 and 7; Stefan, 2026-11-09, "go with all your recs"): the pages left and the color controls right, as the bar
   has them, then the address and LinkedIn left and the (c) right, quiet. Two rows at 1440 (170 px: 48, 24, 32, 18, 48); stacked groups under 768 (about 330 px). Every text Mundial 14/18, sentence case. */
.footer { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "pages controls" "contact copy"; gap: 32px 24px; align-items: center; padding: 48px var(--side); font-size: var(--fs-small); line-height: 18px; }
.footer-links { grid-area: pages; display: flex; gap: 12px 32px; flex-wrap: wrap; align-items: center; min-height: 24px; }
.footer-contact { grid-area: contact; display: flex; gap: 12px 32px; flex-wrap: wrap; align-items: center; }
.footer-contact a { text-decoration: none; }
.footer-contact a { position: relative; }
.footer-controls { grid-area: controls; justify-self: end; display: flex; align-items: center; gap: 24px; flex-wrap: nowrap; min-height: 24px; }
.footer-controls .day-night, .footer-controls .color-open { line-height: 18px; }
.footer-steps { display: flex; margin: 0 0 0 -8px; padding: 0; list-style: none; }
.footer-steps li { width: 32px; height: 24px; }
.footer-controls button[aria-pressed="true"] { font-weight: 700; }
.footer-copy { grid-area: copy; justify-self: end; opacity: 0.64; }
/* The 404's footer (partials/footer-404.html): the nav and the email, nothing under them. */
.footer-min { display: flex; gap: 0; }
@media (max-width: 767px) {
  .footer { grid-template-columns: minmax(0, 1fr); grid-template-areas: "pages" "controls" "contact" "copy"; gap: 24px; padding: 32px 0; }
  .footer-links { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 16px; }
  .footer-links a, .footer-contact a { display: inline-flex; align-items: center; min-height: 44px; }
  .footer-links a:nth-child(n+3) { justify-self: start; }
  .footer-controls { justify-self: start; gap: 4px 20px; min-height: 44px; flex-wrap: wrap; }  /* the line is 338 of 350 px at 390 and wraps below that (320 px) */
  .footer-controls .day-night { min-height: 44px; align-items: center; }
  .footer-steps li { width: 26px; }
  .footer-steps { margin-left: -8px; }
  .footer-copy { justify-self: start; }
  .footer .color-open { min-width: 0; min-height: 44px; font-size: var(--fs-small); gap: 12px; }
}
@media (max-width: 359px) { .footer-controls { flex-wrap: wrap; row-gap: 0; } }  /* the controls line is 335 px; a 320 px phone has 280, so the six steps drop under Day / Night and Color (no sideways scroll) */

/* Case pages */
.progress { position: sticky; top: 0; z-index: var(--z-progress); height: 3px; background: var(--border); }
.progress span { display: block; height: 100%; width: 100%; background: var(--accent); transform-origin: 0 50%; transform: scaleX(var(--progress, 0)); }
.crumb { display: flex; gap: 24px; justify-content: space-between; flex-wrap: wrap; padding: calc(var(--clear) - 3px) var(--side) 0; }  /* the reading bar is 3 px of the way down */
.crumb a { text-decoration: none; }
.case-title { container-type: inline-size; display: grid; gap: 24px; padding: 48px var(--side) 0; }
main > .case-title:first-child { padding-top: var(--clear); }
.case-title h1 { font-family: var(--display); font-weight: var(--display-black); font-size: 8cqw; line-height: 0.9; letter-spacing: -0.01em; text-wrap: balance; }
.thesis { max-width: 1040px; }
.hero { display: grid; gap: 12px; padding: 48px var(--side) 0; }
.hero img { width: 100%; height: auto; }
.hero figcaption { display: grid; gap: 4px; max-width: 760px; }
.status { display: inline-block; font-size: var(--fs-label); line-height: var(--lh-label); letter-spacing: 0; font-weight: 700; color: var(--accent-ink); }
.intro-facts { display: grid; grid-template-columns: minmax(0, 760px) minmax(0, 448px); justify-content: space-between; gap: 96px; padding: var(--space-intro) var(--side) 0; }
.fact { display: grid; gap: 4px; padding: 16px 0; border-top: 1px solid var(--border); }
.parts { display: flex; gap: 24px; padding: 96px var(--side) 0; flex-wrap: wrap; }
.parts a { flex: 1 1 200px; display: grid; gap: 8px; text-decoration: none; }
.chapter { display: grid; gap: 32px; padding: var(--space-section) var(--side) 0; scroll-margin-top: 16px; }
.chapter-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 32px; }
.chapter-head .display { text-wrap: balance; }
.chapter-lines { display: grid; gap: 16px; }
.chapter-lines p:not(:first-child) { color: var(--text-dim); }
.chapter-rows { display: grid; gap: 48px; padding-top: 16px; }
.piece-row { display: flex; gap: 16px; align-items: flex-start; }
.piece, .piece-group { flex: var(--aspect) 1 0%; min-width: 0; display: grid; gap: 8px; }
.group-images { display: flex; gap: 16px; }
.group-images .piece-btn { flex: var(--aspect) 1 0%; min-width: 0; }
/* A video piece shows its poster with a play mark (the row; the strip shows the poster alone): the circle is ::before, the triangle ::after, which paints over it. */
.piece-btn[data-video] { position: relative; }
.piece-btn[data-video]::before { content: ""; position: absolute; left: 50%; top: 50%; width: 56px; height: 56px; margin: -28px 0 0 -28px; border-radius: 50%; background: var(--bg); box-shadow: 0 0 0 2px var(--text); pointer-events: none; }
.piece-btn[data-video]::after { content: ""; position: absolute; left: 50%; top: 50%; margin: -10px 0 0 -6px; border-style: solid; border-width: 10px 0 10px 18px; border-color: transparent transparent transparent var(--text); pointer-events: none; }
/* Decisions and a chapter's link (page packs): a list of title and line beside the part's lines, and the link that closes them. */
.decisions { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 24px; }
.decision { display: grid; gap: 4px; }
.decision-title { font-family: var(--display); font-weight: var(--display-weight); font-size: var(--fs-sub); line-height: 28px; }
.decision-line { font-size: var(--fs-body); line-height: 24px; color: var(--text-dim); }
.chapter-link-line { margin-top: 4px; }
.chapter-link-plain { font-size: var(--fs-label); line-height: var(--lh-label); font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase; color: var(--accent-ink); }
.link-row-plain { color: var(--text); }
.group-images[data-cols] { display: grid; grid-template-columns: repeat(var(--cols), minmax(0, 1fr)); gap: 8px; }
.group-images[data-cols="6"] { --cols: 6; }
.group-images[data-cols="2"] { --cols: 2; gap: 16px; }
@media (min-width: 768px) { .piece-group[style*="--gaps"] { flex-basis: var(--gaps); } }
.piece[style*="--cap"] { max-width: var(--cap); }
.case-title h1[style*="--title-size"] { font-size: var(--title-size); line-height: 0.9; letter-spacing: -0.01em; white-space: nowrap; }
.fact .links .link-line { display: block; }
.link-gloss { color: var(--text-dim); }
.fact .links { display: grid; gap: 0; }
.fact .links a { color: var(--accent-ink); text-decoration: none; }
.links .arrow { font-family: var(--sans), "Segoe UI Symbol", "Noto Sans Symbols 2", "Apple Symbols", "DejaVu Sans", sans-serif; font-variant-emoji: text; font-style: normal; }
.piece-btn { display: block; width: 100%; cursor: zoom-in; }
.piece-btn img { width: 100%; height: auto; aspect-ratio: var(--aspect); object-fit: cover; object-position: top; }
.piece-btn:hover:not(:focus-visible) { outline: 2px solid var(--accent-border); outline-offset: 2px; }
/* The image zoom (plan 2026-11-04, Task 9): a clickable image grows to --zoom in its frame on the row name's timing; hover only, never on touch, reduced motion or ?effects=off. */
.card:has(.stretch) picture, .piece-btn, .work-row picture { overflow: hidden; }
:is(.card:has(.stretch), .piece-btn, .work-row) :is(img, .pfd-art-in) { transform: scale(var(--zs, 1)); transition: transform var(--dur-move) var(--ease); }
@media (prefers-reduced-motion: no-preference) {
  :root:not([data-effects="off"]) :is(.card:has(.stretch:focus-visible), .piece-btn:focus-visible, .work-row:focus-visible) { --zs: var(--zoom); }
  @media (hover: hover) { :root:not([data-effects="off"]) :is(.card:has(.stretch):hover, .piece-btn:hover, .work-row:hover) { --zs: var(--zoom); } }
}
:root[data-vt] :is(.card:has(.stretch), .piece-btn, .work-row) :is(img, .pfd-art-in) { --zs: 1; transition: none; } /* at rest while a view transition captures it: a capture ignores the frame's clip */
/* The case colors (plan 2026-11-02 subpages and content, Task 1b; Stefan, 2026-11-02: "add more theme colors besides just the one to subpages as well"): the structure
   takes --accent-ink, each part its own --ink-N step (marked data-step by the renderer); both hold 4.5:1 on each stage (color.mjs). Home and the hero's status stay. */
body:is(.case, .sub) .case-title hr, body:is(.case, .sub) main .opener hr { border-top-color: var(--accent-ink); }
body:is(.case, .sub) main .opener .label, body:is(.case, .sub) .crumb a.label, body:is(.case, .sub) .next .corners .label:first-child { color: var(--accent-ink); }
body:is(.case, .sub) [data-step="1"] { --step: var(--ink-1); }
body:is(.case, .sub) [data-step="2"] { --step: var(--ink-2); }
body:is(.case, .sub) [data-step="3"] { --step: var(--ink-3); }
body:is(.case, .sub) [data-step="4"] { --step: var(--ink-4); }
body:is(.case, .sub) [data-step="5"] { --step: var(--ink-5); }
body:is(.case, .sub) [data-step="6"] { --step: var(--ink-6); }
body:is(.case, .sub) .parts a[data-step] .label, body:is(.case, .sub) main .chapter[data-step] .opener .label, body:is(.case, .sub) .chapter[data-step] .status { color: var(--step); }
body:is(.case, .sub) main .chapter[data-step] .opener hr { border-top-color: var(--step); }
.piece-meta { display: grid; gap: 4px; }
.piece-meta .caption { white-space: pre-line; }
/* The contact row (X3, R43): Email me as the filled button (no drop shadow, as the frames draw it), LinkedIn and Resume outlined, then the address at body size. Case pages place it after "Why it works" (partials/contact-row.html). */
.contact-row { display: flex; flex-wrap: wrap; align-items: center; gap: 24px 32px; padding: 48px var(--side) 0; }
.contact-row-buttons { display: flex; flex-wrap: wrap; gap: 12px 16px; }
.contact-row .btn-fill { box-shadow: none; }
.contact-row-mail { font-size: var(--fs-body); line-height: var(--lh-body); white-space: nowrap; text-decoration: none; }
.contact-row-mail:hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
/* The arrow the frames draw after each label (R45). Under 768 px the three buttons stack at the full width, 16 px apart, the address under them (the 390 frame: 32 px above, 270 high). */
.contact-row .btn .arrow { letter-spacing: 0; font-variant-emoji: text; }
@media (max-width: 767px) { .contact-row { flex-direction: column; align-items: stretch; gap: 16px; padding-top: 32px; } .contact-row-buttons { flex-direction: column; flex-wrap: nowrap; gap: 16px; } .contact-row-mail { align-self: flex-start; } }
/* The show-all toggle (R43, What Claude reads' two lists; assets/js/toggle.mjs): a text link in the label type with the accent arrow. Without script the list shows whole and the button stays hidden. */
.toggle { display: inline-flex; align-items: center; gap: 8px; min-height: 40px; margin-top: 8px; font-size: var(--fs-label); line-height: var(--lh-label); font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase; color: var(--text); }
.toggle-label { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.toggle-arrow { color: var(--accent-ink); font-size: 16px; line-height: 16px; letter-spacing: 0; }
.toggle:hover .toggle-label { text-decoration-thickness: 2px; }
.why { display: grid; gap: 32px; padding: var(--space-section) var(--side) 0; }
.why p.display { max-width: 1040px; text-wrap: balance; }
.next { padding: var(--space-section) var(--side) 128px; }
.next .card { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 48px; padding: 32px; }
.next .card-text { display: grid; gap: 16px; align-content: space-between; }
@media (max-width: 1023px) {
  .intro-facts { grid-template-columns: minmax(0, 1fr); gap: 48px; }
  .parts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(var(--rows, 3), auto); grid-auto-flow: column; }
  .parts a { align-content: start; }
  .chapter-head { grid-template-columns: minmax(0, 1fr); }
  .next .card { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 767px) {
  .piece-row { flex-direction: column; align-items: stretch; }
  .piece, .piece-group { flex: none; }
  .piece.strip { overflow-x: auto; scroll-snap-type: x mandatory; }
  .piece.strip .piece-btn { width: auto; height: 160px; scroll-snap-align: start; }
  .piece.strip .piece-btn img { width: auto; height: 160px; }
  .case-title, .hero, .crumb, .next { padding-inline: 0; }
  .group-images[data-cols="6"] { --cols: 3; }
}

/* The piece viewer (docs/design/2026-11-02-viewer.md): a view under the site's own header. Only the site's tokens (tokens.css and the values ui.mjs sets for a
   picked color) and its type sizes. The part's ink (--ink, set per part by viewer.mjs from --ink-N) colors the part's name and the status. Rules that must beat
   the glass layer's on main's children use the id. */
/* While a piece is open the page does not scroll, and the header is fixed at the top, above the viewer, still usable. */
html[data-viewing] { overflow: hidden; }
html[data-viewing] .nav { position: fixed; top: 0; left: 20px; right: 20px; z-index: var(--z-viewer-nav); background: var(--bg); box-shadow: -20px 0 0 var(--bg), 20px 0 0 var(--bg); }
html[data-viewing] .nav::before { content: none; }

#piece-viewer {
  position: fixed; inset: var(--pv-top, 90px) 0 0 0; z-index: var(--z-viewer); box-sizing: border-box;
  width: auto; height: auto; max-width: none; max-height: none; margin: 0; border: 0;
  padding: 0 calc(20px + var(--side)) 32px; background: var(--bg); color: var(--text);
}
#piece-viewer::before { content: none; }
#piece-viewer[open] { display: grid; grid-template-rows: auto minmax(0, 1fr); }
#piece-viewer:focus { outline: none; }

.pv-bar { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 64px; border-top: 1px solid var(--border); }
.pv-body { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 48px; min-height: 0; }

/* The image: as large as the stage allows, whole. The steps sit at the stage's sides, over its edges. */
.pv-stage { position: relative; min-height: 0; touch-action: pan-y; -webkit-user-select: none; user-select: none; }
.pv-figure { position: absolute; inset: 0; margin: 0; }
.pv-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; -webkit-user-drag: none; }
.pv-step {
  position: absolute; top: 50%; z-index: var(--z-viewer-step); width: 48px; height: 48px; margin-top: -24px; display: grid; place-items: center;
  color: var(--text); background: var(--bg); background: color-mix(in srgb, var(--bg) 88%, transparent); border: 1px solid var(--border);
}
.pv-prev { left: 0; }
.pv-next { right: 0; }
.pv-step svg { width: 20px; height: 20px; }
.pv-step:hover:not(:disabled) { border-color: var(--text-dim); }

/* The panel: where the piece sits, what it is, the part it belongs to, what the image shows; at its foot, the part's pieces
   and the way on. */
.pv-panel { display: flex; flex-direction: column; gap: 12px; min-height: 0; overflow-y: auto; padding: 4px 4px 4px 0; }
.pv-where { display: grid; gap: 4px; }
.pv-case { color: var(--text-dim); }
.pv-part { color: var(--ink); }
.pv-title { margin-top: 12px; font-family: var(--display); font-weight: var(--display-weight); font-size: 28px; line-height: 36px; }
/* The title takes focus on open so a screen reader starts there; it is not a control, so it shows no ring. */
.pv-title:focus, .pv-title:focus-visible { outline: none; }
.pv-status { color: var(--ink); }
.pv-line { font-size: var(--fs-body); line-height: 24px; }
.pv-desc { display: grid; gap: 6px; margin-top: 12px; }
.pv-desc-text { color: var(--text-dim); }
.pv-nav { display: grid; gap: 16px; margin-top: auto; padding-top: 16px; border-top: 1px solid var(--border); }
.pv-strip { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; margin: 0; padding: 0; }
.pv-thumb { display: block; width: 64px; height: 44px; padding: 0; border: 1px solid var(--border); }
.pv-thumb img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.pv-thumb[aria-current="true"] { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--text); }
.pv-onward { min-height: 16px; }
.pv-onward .arrow-link { text-align: left; }

/* The viewer's buttons: the case pages' viewer style, 44 px, a 2 px accent edge, 12 px capitals. */
.pv-btn { min-height: 44px; padding: 0 16px; border: 2px solid var(--accent); font-size: 12px; line-height: 16px; font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase; }
.pv-btn:hover:not(:disabled) { background: var(--accent); color: var(--accent-text); }
.pv-foot { display: none; }
.pv-sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Under 1024 the panel follows the image, the whole view scrolls, and Previous and Next sit in a bar at the foot. */
@media (max-width: 1023px) {
  #piece-viewer[open] { display: block; overflow-y: auto; padding-bottom: 96px; }
  .pv-bar { position: sticky; top: 0; z-index: var(--z-viewer-bar); background: var(--bg); }
  .pv-body { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .pv-stage { height: min(56vh, 560px); }
  .pv-step { display: none; }
  .pv-panel { overflow: visible; padding: 0; }
  .pv-nav { margin-top: 12px; }
  .pv-foot {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-viewer-foot);
    padding: 12px calc(20px + var(--side)) 16px; background: var(--bg); border-top: 1px solid var(--border);
  }
}
@media (max-width: 767px) {
  .pv-bar { min-height: 56px; }
  .pv-stage { height: auto; aspect-ratio: var(--pv-aspect, 1.6); max-height: 50vh; }
  .pv-title { font-size: 22px; line-height: 28px; }
  .pv-thumb { width: 56px; height: 40px; }
}

/* A video piece (page packs, RULINGS.md pack 02): the video plays in the stage over its poster; nothing plays until the reader presses play. */
.pv-video { position: absolute; inset: 0; width: 100%; height: 100%; background: var(--bg); object-fit: contain; }
.pv-video[hidden] { display: none; }

@media print { #piece-viewer { display: none !important; } }

@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; animation: none !important; scroll-behavior: auto !important; } }

/* Grid items may shrink below their content, so nothing widens the page at 390. */
.card, .statement-text, .about, .chapter, .why, .masthead, .case-title, .hero, .piece, .piece-group, .contact, .footer, .facts-list, .chapter-lines { grid-template-columns: minmax(0, 1fr); }
.next .card, .chapter-head, .intro-facts { min-width: 0; }

/* The live models: each poster (its model's box) first, the model in the same box, no shift. A model's element is its
   render's size, placed so the box shows (--vx, --vy, --vw, --vh, written per model by scripts/build_pages.py from
   site/assets/model/<id>.json); the box keeps the model's ratio (--ar) in its slide, the width or the height whichever
   binds; --s is the render scale's step. */
.live-box { --s: 1; position: relative; width: min(100cqw, 100cqh * var(--ar)); aspect-ratio: var(--ar); overflow: hidden; }
.live-box picture { position: relative; display: block; width: 100%; height: 100%; }
.live-box picture canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.live-box[data-recolored] img { visibility: hidden; }
.live-box img { width: 100%; height: 100%; object-fit: fill; }
.live-box model-viewer { position: absolute; left: var(--vx); top: var(--vy); width: calc(var(--vw) * var(--s)); height: calc(var(--vh) * var(--s)); transform: scale(calc(1 / var(--s))); transform-origin: 0 0; background: transparent; --poster-color: transparent; opacity: 0; transition: opacity 0.2s; }
.live-box[data-live="on"] model-viewer { opacity: 1; }
.live-box[data-live="on"] picture { visibility: hidden; transition: visibility 0s 0.25s; }

/* The Color lab (/color-lab/; plan 2026-11-02, Task 12): a standalone page, linked from nothing, noindex. */
.lab-head { padding: 48px var(--side) 0; display: grid; gap: 24px; max-width: 1100px; }
.lab-title { font-family: var(--display); font-weight: var(--display-weight); font-size: 96px; line-height: 96px; letter-spacing: -1px; }
.lab-presets { padding: 64px var(--side) 0; display: grid; gap: 32px; }
.lab-set { display: grid; gap: 16px; }
.lab-dots { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 24px; }
.lab-dots li { display: grid; justify-items: center; gap: 8px; min-width: 56px; }
.lab-dots button { width: 32px; height: 32px; border-radius: 50%; background: var(--dot); box-shadow: 0 0 0 2px transparent; }
.lab-dots button[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--text); }
.lab-tools { padding: 64px var(--side) 0; display: grid; grid-template-columns: minmax(0, 360px) minmax(0, 1fr); gap: 64px; align-items: start; }
.lab-picker, .lab-readouts { display: grid; gap: 16px; }
.lab-field-wrap { position: relative; width: 100%; aspect-ratio: 1; touch-action: none; cursor: crosshair; border-radius: 4px; overflow: visible; }
.lab-field, .lab-lines { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 4px; }
.lab-field { border: 1px solid var(--border); }
.lab-lines { pointer-events: none; }
.lab-thumb { position: absolute; width: 20px; height: 20px; transform: translate(-50%, -50%); border-radius: 50%; border: 2px solid #fff; box-shadow: 0 0 0 1px #000, 0 0 0 3px rgba(0, 0, 0, 0.35); background: var(--accent); }
.lab-thumb:focus-visible { outline: 2px solid var(--focus); outline-offset: 4px; }
.lab-mirror { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.lab-axes { display: flex; justify-content: space-between; }
.lab-keys { list-style: none; padding: 0; margin: 0; display: grid; gap: 8px; }
.lab-keys li { display: flex; align-items: center; gap: 12px; }
.lab-keys i { width: 28px; height: 14px; border: 1px solid var(--border); flex: none; }
.key-night { background: repeating-linear-gradient(135deg, transparent 0 3px, var(--text) 3px 4px); }
.key-day { background: repeating-linear-gradient(45deg, transparent 0 3px, var(--text) 3px 4px); }
.key-text { border: 0 !important; height: 2px !important; background: var(--text); }
.lab-hexfield { display: grid; gap: 8px; }
.lab-hexfield input { height: 44px; padding: 0 12px; font: 400 16px/22px var(--sans); color: var(--text); background: var(--surface); border: 1px solid var(--border); border-radius: 0; }
.lab-hexfield input[aria-invalid="true"] { border-color: var(--text); outline: 2px dashed var(--text); }
.lab-used { display: grid; grid-template-columns: 48px 48px 1fr auto; align-items: center; gap: 16px; padding: 12px 0; border-top: 1px solid var(--border); }
.lab-swatch { width: 48px; height: 48px; border: 1px solid var(--border); }
.lab-chip { display: inline-grid; place-items: center; width: 48px; height: 48px; font-family: var(--display); font-weight: var(--display-weight); font-size: 20px; }
.lab-used code { font: 400 14px/18px var(--sans); }
.lab-ramp { list-style: none; padding: 0; margin: 16px 0 0; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 8px; counter-reset: none; }
.lab-ramp li { display: grid; place-items: center; height: 56px; font-size: 14px; font-weight: 700; border: 1px solid var(--border); }
.lab-preview { padding: 96px var(--side) 128px; display: grid; gap: 24px; }
.lab-preview-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 40px 32px; align-items: start; }
/* The preview shows the buttons as the hero does since Task 10: no shadow (Stefan: "I also said no shadow for the main cta on the hero section"). */
.lab-preview .btn-fill { box-shadow: none; }
.lab-card { max-width: 360px; }
.lab-card .card-name { font-size: 28px; line-height: 36px; }
.lab-rule { display: grid; gap: 8px; }
.lab-rule hr { border-top-color: var(--accent-border); }
.lab-band { padding: 32px; background: var(--accent); color: var(--accent-text); font-family: var(--display); font-weight: var(--display-weight); font-size: 28px; line-height: 36px; }
html:not(.js) .lab-tools .lab-picker, html:not(.js) .lab-presets { display: none; }
@media (max-width: 1023px) { .lab-title { font-size: 54px; line-height: 62px; } .lab-tools { grid-template-columns: minmax(0, 1fr); gap: 48px; } }
@media (max-width: 767px) { .lab-title { font-size: 40px; line-height: 46px; } .lab-head, .lab-presets, .lab-tools, .lab-preview { padding-left: 0; padding-right: 0; } .lab-used { grid-template-columns: 40px 40px 1fr; } .lab-used code { grid-column: 3; } }

/* The mini color picker (docs/design/2026-11-02-mini-color-picker.md): the Color control's panel and the footer's controls. */
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }

/* The panel keeps today's place, fill, border and hard shadow; 320 wide so six 44 px targets fit its 270 px measure. */
.panel.mini { width: 320px; gap: 16px; }
@media (max-width: 767px) { .panel.mini { width: auto; } }

/* 1. The color now: hex, what this theme uses, Reset. */
.mini-status { display: grid; grid-template-columns: auto 1fr auto; align-items: center; column-gap: 12px; margin: -6px 0 -4px; }
.mini-status > * { grid-row: 1; }
.mini-status .day-night { grid-column: 2; justify-self: start; min-height: 44px; align-items: center; }
@media (max-width: 479px) { .mini-status .day-night { grid-column: 1 / -1; grid-row: 2; } .mini-status .mini-used { grid-row: 3; } }
.mini-hex input { display: block; width: 76px; height: 32px; padding: 0; font: 400 14px/20px var(--sans); letter-spacing: 0.04em; text-transform: uppercase; color: var(--text); background: transparent; border: 0; border-bottom: 1px solid var(--text-dim); border-radius: 0; }
.mini-hex input:hover { border-bottom-color: var(--text); }
.mini-hex input[aria-invalid="true"] { border-bottom: 1px dashed var(--text); }
.mini-used { grid-column: 1 / -1; grid-row: 2; min-width: 0; min-height: 40px; margin: 0; display: flex; flex-wrap: wrap; align-content: flex-start; align-items: center; gap: 0 6px; font: 400 14px/20px var(--sans); letter-spacing: 0.04em; color: var(--text-dim); }
.mini-used i { flex: none; width: 12px; height: 12px; border-radius: 50%; background: var(--c); }
.mini-reset { white-space: nowrap; grid-column: 3; justify-self: end; min-width: 44px; min-height: 44px; padding: 0; font-size: 12px; line-height: 16px; letter-spacing: 0.25em; text-transform: uppercase; color: var(--accent-ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }

/* 2. The ready colors: the body as picked, the 4 px rim as this theme uses it. */
.mini-dots { display: flex; justify-content: space-between; margin: 0 -6px; }
.mini-dots button { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; }
.mini-dots button::before { content: ""; width: 32px; height: 32px; border-radius: 50%; background: var(--dot); box-shadow: inset 0 0 0 4px var(--used, var(--dot)); }
.mini-dots button[aria-pressed="true"]::before { box-shadow: inset 0 0 0 4px var(--used, var(--dot)), 0 0 0 2px var(--surface), 0 0 0 4px var(--text); }

/* 3. The picker: Tint across and Brightness up at the current hue, the hue strip under it at the same width. */
.mini-picker { display: grid; gap: 12px; }
.mini-field-wrap { position: relative; height: 136px; touch-action: none; cursor: crosshair; }
.mini-field, .mini-lines { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 4px; }
.mini-field { border: 1px solid var(--border); }
.mini-lines { pointer-events: none; }
.mini-thumb { position: absolute; width: 24px; height: 24px; transform: translate(-50%, -50%); border-radius: 50%; background: var(--picked); box-shadow: inset 0 0 0 4px var(--used), 0 0 0 2px #fff, 0 0 0 3px #000; }
.mini-hue input { -webkit-appearance: none; appearance: none; display: block; width: 100%; height: 24px; margin: 0; background: transparent; cursor: pointer; }
.mini-hue input::-webkit-slider-runnable-track { height: 8px; border-radius: 4px; background: var(--track, var(--border)); }
.mini-hue input::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 24px; height: 24px; margin-top: -8px; border: 0; border-radius: 50%; background: var(--picked); box-shadow: inset 0 0 0 4px var(--used), 0 0 0 2px #fff, 0 0 0 3px #000; }
.mini-hue input::-moz-range-track { height: 8px; border-radius: 4px; background: var(--track, var(--border)); }
.mini-hue input::-moz-range-thumb { width: 24px; height: 24px; border: 0; border-radius: 50%; background: var(--picked); box-shadow: inset 0 0 0 4px var(--used), 0 0 0 2px #fff, 0 0 0 3px #000; }

/* 4. The tab never moves: the full picker opens below it. */
.mini-foot { display: grid; gap: 8px; justify-items: start; }
.mini-tab { display: flex; justify-content: space-between; align-items: center; width: 100%; min-height: 44px; margin: 0 0 -12px; border-top: 1px solid var(--border); font-size: 12px; line-height: 16px; letter-spacing: 0.25em; text-transform: uppercase; color: var(--text); }
.mini-tab svg { width: 12px; height: 8px; transition: transform var(--dur-fill) var(--ease); }
.mini-tab[aria-expanded="true"] svg { transform: rotate(180deg); }

/* 5. The full picker: both themes' accents, the six steps, the key to the two lines. */
.mini-full { display: grid; gap: 16px; padding-top: 12px; }
.mini-themes { display: grid; gap: 8px; }
.mini-theme { display: grid; grid-template-columns: 48px minmax(0, 1fr); grid-template-rows: auto auto; column-gap: 12px; row-gap: 2px; align-content: center; }
.mini-theme .mini-tile { grid-row: 1 / span 2; }
.mini-theme .label { align-self: end; }
.mini-tile { display: grid; place-items: center; width: 48px; height: 48px; background: var(--fill); color: var(--on); font-family: var(--display); font-weight: var(--display-weight); font-size: 20px; line-height: 1; }
.mini-val { font: 400 14px/20px var(--sans); letter-spacing: 0.04em; color: var(--text); white-space: nowrap; }
.mini-val span { color: var(--text-dim); }
.mini-steps-block { display: grid; gap: 8px; }
.mini-steps { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 6px; }
.mini-steps li { height: 32px; background: var(--c); }
.mini-pick { flex: none; display: inline-flex; align-items: center; gap: 8px; min-height: 44px; font-size: 12px; line-height: 16px; letter-spacing: 0.25em; text-transform: uppercase; color: var(--text); text-align: left; }
.mini-pick::before { content: ""; flex: none; width: 14px; height: 14px; border: 1.5px solid currentColor; border-radius: 3px; }
.mini-pick[aria-pressed="true"]::before { background: var(--accent-ink); border-color: var(--accent-ink); box-shadow: inset 0 0 0 2px var(--surface); }
.mini-steps button, .footer-steps button { display: block; width: 100%; height: 100%; padding: 0; border: 0; background: transparent; }
.mini-edit { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; column-gap: 12px; }
.mini-edit .mini-pick { order: 0; }
.mini-edit .mini-reset { order: 1; grid-column: auto; margin-left: auto; padding: 0 4px; white-space: nowrap; }
.mini-edit p { order: 2; flex: 1 0 100%; margin: 0 0 4px; }
.mini-edit-row { display: contents; }
.mini-edit [data-mini-edit-actions] { order: 3; margin-left: auto; }
.mini-edit [data-mini-save]:disabled { color: var(--text-dim); text-decoration: none; }
.mini-dots [data-selected] { outline: 2px dashed var(--text); outline-offset: -2px; border-radius: 50%; }
[data-mini-step] { cursor: pointer; }
[data-mini-step]:hover { outline: 2px solid var(--text); outline-offset: 2px; }
.mini-tag { position: absolute; white-space: nowrap; left: 6px; transform: translateY(-50%); padding: 1px 6px; font-size: 12px; line-height: 16px; letter-spacing: 0.25em; text-transform: uppercase; color: var(--text); background: var(--surface); border-radius: 2px; pointer-events: none; }
/* The lines run close (Night, the text and Day sit 10 px apart at the least on a 120 px field): Night's tag hangs below its line, Day's stands on its own, the text's is centered. */
.mini-tag[data-mini-tag="dark"] { transform: none; }
.mini-tag[data-mini-tag="light"] { transform: translateY(-100%); }
.panel.mini:not([data-full]) .mini-lines, .panel.mini:not([data-full]) .mini-tag { display: none; }


/* What the band's picker shows follows its own width (it is the container): the Night and Day tiles side by side from 256 px; from 360 px the Day / Night control shares the color-now row's line (under it, its own);
   the note that says what a theme moved (the tiles already show both values) is a line of its own from 400 px, a screen-reader line before, and it keeps its line then so a pick that needs it does not move what is under it. */
@container (min-width: 256px) { .mini-themes { grid-template-columns: 1fr 1fr; gap: 16px; } }
@container (max-width: 359px) { .mini-status .day-night { grid-column: 1 / -1; grid-row: 2; } }
@container (max-width: 399px) { .mini-used { position: absolute; width: 1px; height: 1px; min-height: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } }
@container (min-width: 400px) { .mini-used { min-height: 20px; } }
@container (max-width: 259px) { .mini-tag { letter-spacing: 0.12em; } }
@container (max-width: 459px) { .mini-val span { display: block; } }  /* a theme that moves the color shows "#FFD600 →" over "#A48800" where the tile's half would not hold the one line */
@media (max-width: 767px) {
  .mini-field-wrap { height: 120px; }
  .mini-hue input { height: 44px; }
  /* Opened, the full picker can outgrow a phone's screen; the panel then scrolls inside itself, under the bar. */
  .panel.mini { max-height: calc(100vh - 96px); overflow-y: auto; overscroll-behavior: contain; }
}
@media (prefers-reduced-motion: no-preference) {
  .panel.mini:not([hidden]) { animation: mini-in var(--dur-slide-in) var(--ease-slide-in); }
  .mini-full:not([hidden]) { animation: mini-in var(--dur-slide-in) var(--ease-slide-in); }
}
@keyframes mini-in { from { opacity: 0; transform: translateY(-4px); } }

/* w2-1: Home (the approved R43 and R44 frames, Stefan, 2026-11-06). The masthead keeps 24 px under its role row; the role row is 14 px in the page text color; the glass card
   is 720 px at 1440 with a 32 px padding and a 20 px gap (24 and 16 on a phone), holds the hiring line under the sub and the retailer strip under the buttons, and sits 32 px
   (12 on a phone) under the stage's top, so "See the work" ends above the fold. */
.masthead { padding-bottom: 24px; }
.statement { align-items: start; padding-top: 32px; }
.statement-text { padding: 32px 48px; gap: 20px; }
.lead-sub { margin-top: 0; }
.lead-hire { font-size: 16px; line-height: 22px; }
.work-row .row-name { overflow-wrap: anywhere; }  /* "VacuumSealersUnlimited.com" is one word wider than a phone's name column: it breaks, as the frames' text box breaks it */
.cta { padding-top: 8px; }
@media (min-width: 1024px) and (max-width: 1599px) { .statement { grid-template-columns: minmax(0, 720px) minmax(0, 1fr); } }
@media (max-width: 767px) {
  .masthead { padding-bottom: 8px; }  /* merge fix 4 (2026-11-06): 16 px and 8 px less under the masthead on a phone, so "See the work" ends at 837 inside the 844 px first screen (it ended at 861; the frame draws it ending at 838); the 72 px nav clearance above the name stays */
  .statement { margin-top: 4px; padding-top: 12px; padding-bottom: 24px; min-height: 648px; align-content: start; }
  .statement-text { padding: 24px 24px 40px; gap: 16px; }
  .lead-sub { margin-top: 0; }
  .cta { padding-top: 0; }
}

/* w2-1: Resume (the approved R43 frames): the download is one filled button under the contact lines, flat, the width of its label (the full row on a phone, where the label wraps to two lines). */
.resume-download { padding: 32px var(--side) 0; }
.resume-download .btn { height: auto; min-height: 56px; padding: 16px 25.5px 16px 24px; box-shadow: none; text-align: left; }
@media (max-width: 767px) { .resume-download .btn { display: flex; justify-content: space-between; } }

/* w2-1: 404 (the approved R43 frames): the numerals in the accent sit on a rule (the line box under the digits is cut at 0.82 of the type size, so their feet meet it), the line and the sentence
   side by side at 636 : 604 from 1024 px with the buttons under the sentence, one column with stacked buttons under that. The numerals are half the old size at 1440 (370 px) and fill the width on a phone. */
.notfound { container-type: inline-size; padding: calc(var(--clear) + 16px) var(--side) 96px; }
.nf-numerals { font-family: var(--display); font-weight: var(--display-black); font-size: min(370px, 56.74cqw); line-height: 1; letter-spacing: -0.03em; height: 0.82em; overflow: hidden; color: var(--accent-ink); margin: 0; padding-top: 0; }
.nf-rule { margin: 0; border: 0; border-top: 1px solid var(--text-dim); }
.nf-cols { display: grid; grid-template-columns: minmax(0, 636fr) minmax(0, 604fr); gap: 64px; padding-top: 48px; }
.nf-heading { font-family: var(--display); font-weight: var(--display-weight); font-size: 54px; line-height: 62px; }
.nf-right { display: grid; gap: 32px; align-content: start; }
.nf-lead { font-size: 28px; line-height: 38px; }
.nf-buttons { display: flex; gap: 16px; flex-wrap: wrap; }
.nf-buttons .btn-fill { box-shadow: none; }
@media (max-width: 1023px) { .nf-cols { grid-template-columns: minmax(0, 1fr); gap: 24px; } }
@media (max-width: 767px) {
  .notfound { padding: calc(var(--clear) - 16px) var(--side) 64px; }
  .nf-numerals { padding-top: 16px; height: calc(0.82em + 16px); }
  .nf-cols { padding-top: 32px; }
  .nf-heading { font-size: 34px; line-height: 44px; }
  .nf-right { gap: 24px; }
  .nf-lead { font-size: 18px; line-height: 28px; }
  .nf-buttons { display: grid; justify-items: start; gap: 16px; padding-top: 8px; }
}
