/* ------------------------------------------------------------------
   moritzlenhard.com

   Radius system: interactive elements are pills, the portrait is a
   circle, everything else is flat.
   Type system: Bricolage Grotesque for display, Instrument Sans for
   body, JetBrains Mono for the small uppercase labels.
   ------------------------------------------------------------------ */

/* Self-hosted so no visitor data reaches Google. All three are variable fonts, so
   one file per family covers every weight we use. Latin subset only; it includes
   the umlauts the German copy needs. */
@font-face {
    font-family: 'Bricolage Grotesque';
    src: url('fonts/bricolage-grotesque-latin.woff2') format('woff2');
    font-weight: 600 700;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Instrument Sans';
    src: url('fonts/instrument-sans-latin.woff2') format('woff2');
    font-weight: 400 600;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'JetBrains Mono';
    src: url('fonts/jetbrains-mono-latin.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

:root {
    --bg: #FAFAF7;
    --ink: #191C20;
    --muted: #6B7077;
    --border: #E4E2DB;
    --chip: #F1F0EA;
    /* Figure surfaces sit a shade above the page so diagrams read as insets. */
    --fig-bg: #FDFDFB;
    --fig-cell: #FFFFFF;
    --accent: #2E5175;
    --accent-dark: #21405E;
    /* --accent at 30%, for the understated link underline */
    --accent-soft: rgba(46, 81, 117, 0.3);

    --display: 'Bricolage Grotesque', 'Avenir Next', sans-serif;
    --body: 'Instrument Sans', 'Helvetica Neue', Helvetica, sans-serif;
    --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;
}

html {
    scroll-behavior: smooth;
    /* The project framing script computes its own targets; the browser's scroll
       anchoring would pull against them mid-transition. */
    overflow-anchor: none;
}

body {
    background: var(--bg);
    color: var(--ink);
    font-family: var(--body);
    font-size: 17px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
}

a {
    color: var(--accent);
}

a:hover {
    color: var(--accent-dark);
}

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
}

.wrap {
    max-width: 720px;
    margin: 0 auto;
    padding: 0 24px;
}

/* The small mono uppercase label used for section headings. */
.eyebrow {
    font-family: var(--mono);
    font-weight: 500;
    font-size: 0.72rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 34px;
}

/* ── Header ─────────────────────────────────────────────────────── */

header {
    padding: 28px 0;
}

header .wrap {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
}

#wordmark {
    font-family: var(--display);
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: -0.01em;
    color: var(--ink);
    text-decoration: none;
}

#lang-toggle {
    font-family: var(--mono);
    font-weight: 500;
    font-size: 0.72rem;
    letter-spacing: 0.1em;
    color: var(--muted);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 6px 14px;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s;
}

#lang-toggle:hover {
    color: var(--ink);
    border-color: var(--muted);
}

#lang-toggle:active {
    transform: translateY(1px);
}

/* ── Hero ───────────────────────────────────────────────────────── */

#hero {
    padding: 52px 0 76px;
}

/* wrap-reverse: side by side on wide screens, portrait on top once it
   breaks to two lines. */
#hero .wrap {
    display: flex;
    flex-wrap: wrap-reverse;
    align-items: center;
    gap: 40px;
}

.hero-copy {
    flex: 1 1 320px;
}

h1 {
    font-family: var(--display);
    font-weight: 700;
    font-size: clamp(2.1rem, 6vw, 3rem);
    letter-spacing: -0.025em;
    line-height: 1.1;
    margin-bottom: 18px;
    text-wrap: balance;
}

.intro {
    color: var(--muted);
    max-width: 46ch;
    margin-bottom: 16px;
    text-wrap: pretty;
}

.now {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    font-size: 0.95rem;
    color: var(--muted);
    margin-bottom: 10px;
}

/* The ask is the last thing before the buttons, so it carries the gap to them. */
.now-ask {
    margin-bottom: 30px;
}

.now-label {
    font-family: var(--mono);
    font-size: 0.68rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 3px 10px;
    white-space: nowrap;
}

/* Filled rather than outlined: the ask should be the loudest thing after the h1. */
.now-ask .now-label {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--bg);
}

.now-ask span:not(.now-label) {
    color: var(--ink);
}

.actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    font-weight: 600;
    font-size: 0.9rem;
    text-decoration: none;
    border-radius: 999px;
    /* asymmetric: the icon needs less breathing room than the label */
    padding: 10px 20px 10px 17px;
    border: 1px solid transparent;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.btn:active {
    transform: translateY(1px);
}

.btn svg {
    flex: none;
}

.btn-primary {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--bg);
}

.btn-primary:hover {
    background: var(--accent-dark);
    border-color: var(--accent-dark);
    color: var(--bg);
}

.btn-primary svg {
    opacity: 0.9;
}

.btn-ghost {
    border-color: var(--border);
    color: var(--ink);
}

.btn-ghost:hover {
    border-color: var(--muted);
    background: var(--chip);
    color: var(--ink);
}

.btn-ghost svg {
    opacity: 0.85;
}

/* Portrait: see the comment in index.html for adding a real photo.
   Until then the initials placeholder shows. */
.photo {
    flex: 0 0 auto;
    width: clamp(124px, 30vw, 168px);
    height: clamp(124px, 30vw, 168px);
    border-radius: 50%;
    background: var(--chip);
    border: 1px solid var(--border);
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.photo .initials {
    font-family: var(--display);
    font-weight: 700;
    font-size: clamp(2.2rem, 8vw, 3rem);
    color: var(--accent);
    opacity: 0.55;
}

.photo img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ── Sections ───────────────────────────────────────────────────── */

section {
    border-top: 1px solid var(--border);
    padding: 56px 0;
}

/* ── Projects ───────────────────────────────────────────────────── */

/* A numbered list of disclosure rows. Each row is a native <details>; `name`
   makes them exclusive, so expanding needs no JavaScript, works from the
   keyboard, and leaves the full text in the DOM for search engines. */
.projects {
    display: grid;
    gap: 0;
}

/* The browser's own scroll anchoring fights the framing script, which computes
   where a row will land and eases the page there in one move. */
.project-row {
    position: relative;
    overflow-anchor: none;
}

.project-row + .project-row {
    border-top: 1px solid var(--border);
}

.project-head {
    position: relative;
    display: block;
    padding: 20px;
    margin: 0 -20px;
    cursor: pointer;
    list-style: none;
}

.project-row:first-child .project-head {
    padding: 8px 20px 22px;
}

.project-head::-webkit-details-marker {
    display: none;
}

/* Hover wash, sitting behind the row content rather than tinting it. */
.row-wash {
    position: absolute;
    inset: 0;
    background: var(--chip);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.18s;
}

.project-head:hover .row-wash {
    opacity: 1;
}

/* Left rail: grows out of nothing on hover, stays up while the row is open. */
.row-rail {
    position: absolute;
    left: 0;
    top: 16px;
    bottom: 16px;
    width: 2px;
    background: var(--border);
    transform: scaleY(0);
    transform-origin: 50% 50%;
    transition: transform 0.24s cubic-bezier(0.16, 1, 0.3, 1), background 0.18s;
}

.project-row:first-child .row-rail {
    top: 12px;
    bottom: 18px;
}

.project-head:hover .row-rail,
.project-row:has(.project[open]) .row-rail {
    transform: scaleY(1);
    background: var(--accent);
}

.row-grid {
    position: relative;
    display: grid;
    grid-template-columns: 34px 1fr auto;
    column-gap: 14px;
    row-gap: 7px;
    align-items: start;
}

.project-row:first-child .row-grid {
    row-gap: 9px;
}

.row-num {
    font-family: var(--mono);
    font-size: 0.68rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    padding-top: 5px;
    color: var(--muted);
    transition: color 0.18s;
}

.project-row:first-child .row-num {
    padding-top: 7px;
}

.project-head:hover .row-num,
.project-row:has(.project[open]) .row-num {
    color: var(--accent);
}

.row-title {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
}

.row-toggle {
    width: 28px;
    height: 28px;
    border-radius: 999px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--muted);
    border: 1px solid var(--border);
    transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.18s, color 0.18s;
}

.project-row:first-child .row-toggle {
    margin-top: 3px;
}

.project-head:hover .row-toggle {
    border-color: var(--accent);
    color: var(--accent);
}

.project-row:has(.project[open]) .row-toggle {
    transform: rotate(180deg);
    border-color: var(--accent);
    color: var(--accent);
}

.project-hook {
    grid-column: 2 / -1;
    color: var(--muted);
    font-size: 0.92rem;
    line-height: 1.5;
    max-width: 54ch;
    text-wrap: pretty;
}

.project-row:first-child .project-hook {
    font-size: 0.95rem;
    line-height: 1.55;
}

.project h3 {
    font-family: var(--display);
    font-weight: 600;
    font-size: 1.16rem;
    line-height: 1.25;
    letter-spacing: -0.015em;
}

/* The lead row carries the flagship, so it gets the larger setting. */
.project-row:first-child h3 {
    font-weight: 700;
    font-size: 1.42rem;
    line-height: 1.2;
    letter-spacing: -0.02em;
}

.chip {
    font-family: var(--mono);
    font-size: 0.63rem;
    font-weight: 500;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--muted);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 3px 9px;
    white-space: nowrap;
}

.chip-accent {
    color: var(--accent);
    border-color: var(--accent-soft);
}

/* Indented to clear the number column, so body copy lines up under the title. */
.project-body {
    display: grid;
    gap: 12px;
    justify-items: start;
    margin-top: 2px;
    padding: 0 0 22px 48px;
}

.project-body p {
    color: var(--muted);
    max-width: 56ch;
    text-wrap: pretty;
}

.project-link {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--accent);
    text-decoration: none;
    border-bottom: 1px solid var(--accent-soft);
    padding-bottom: 1px;
}

.project-link:hover {
    color: var(--accent-dark);
    border-bottom-color: var(--accent-dark);
}

.projects-footer {
    display: grid;
    gap: 10px;
    justify-items: start;
    margin-top: 34px;
}

.projects-footer p {
    color: var(--muted);
    max-width: 56ch;
    text-wrap: pretty;
}

/* ── Figures ────────────────────────────────────────────────────── */

/* Diagrams of what each project actually found, drawn in CSS so they cost no
   image weight and stay legible at any width. The loop is long and slow on
   purpose: it should read as an explanation, not as decoration demanding
   attention. */
.fig {
    --om-accent: var(--accent);
    --om-second: var(--muted);
    --om-loop: 12s;
    --om-play: running;
    display: grid;
    gap: 10px;
    width: 100%;
    margin-top: 10px;
}

.fig-card {
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--fig-bg);
    padding: 18px;
}

.fig-label {
    font-family: var(--mono);
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--muted);
}

.fig-cap {
    font-family: var(--mono);
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
}

/* Figure 1: two modalities meeting at an intensity gate. */
.fig-ser {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0;
}

.ser-in {
    flex: 1 1 200px;
    display: grid;
    gap: 9px;
    align-content: center;
}

/* Sits above the dashed alignment ticks, so it needs to mask them. */
.ser-in > .fig-label {
    position: relative;
    z-index: 1;
    background: var(--fig-bg);
}

.ser-stack {
    position: relative;
    display: grid;
    gap: 11px;
}

.ser-tick {
    position: absolute;
    top: -3px;
    bottom: -3px;
    border-left: 1px dashed rgba(25, 28, 32, 0.16);
}

.ser-tick-a { left: 25%; }
.ser-tick-b { left: 55%; }

.ser-words {
    display: grid;
    grid-template-columns: 5fr 6fr 9fr;
    gap: 4px;
}

.ser-word {
    font-size: 12.5px;
    font-weight: 500;
    text-align: center;
    padding: 5px 4px;
    border-radius: 4px;
    background: var(--fig-cell);
    border: 1px solid var(--border);
    color: var(--ink);
}

.ser-wave {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 56px;
}

.ser-bar {
    flex: 1;
    background: var(--om-accent);
    opacity: 0.6;
    border-radius: 1px;
    transform-origin: bottom;
    animation-duration: var(--om-loop);
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    animation-play-state: var(--om-play);
}

.ser-join {
    flex: 0 0 54px;
    position: relative;
    align-self: stretch;
    min-height: 140px;
}

.join-line {
    position: absolute;
    border-color: rgba(25, 28, 32, 0.18);
}

.join-h-top { left: 0; top: 30%; width: 52%; border-top: 1px solid rgba(25, 28, 32, 0.18); }
.join-v-top { left: 52%; top: 30%; height: 20%; border-left: 1px solid rgba(25, 28, 32, 0.18); }
.join-h-bot { left: 0; top: 79%; width: 52%; border-top: 1px solid rgba(25, 28, 32, 0.18); }
.join-v-bot { left: 52%; top: 50%; height: 29%; border-left: 1px solid rgba(25, 28, 32, 0.18); }
.join-h-out { left: 52%; top: 50%; right: 6px; border-top: 1px solid rgba(25, 28, 32, 0.18); }

.join-dot {
    position: absolute;
    left: 52%;
    top: 50%;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--om-second);
    transform: translate(-50%, -50%);
    animation: om-flow var(--om-loop) cubic-bezier(0.4, 0, 0.2, 1) infinite;
    animation-play-state: var(--om-play);
}

.join-arrow {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 0;
    height: 0;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    border-left: 6px solid rgba(25, 28, 32, 0.28);
}

.ser-out {
    flex: 1 1 205px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--fig-cell);
    padding: 14px 15px 15px;
    display: grid;
    gap: 13px;
    align-content: center;
}

.gate-track {
    position: relative;
    height: 9px;
    background: var(--chip);
    border-radius: 5px;
}

.gate-fill {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 16%;
    background: var(--om-second);
    opacity: 0.75;
    border-radius: 5px;
    animation: om-gate var(--om-loop) cubic-bezier(0.4, 0, 0.2, 1) infinite;
    animation-play-state: var(--om-play);
}

.gate-thresh {
    position: absolute;
    left: 46%;
    top: -7px;
    bottom: -7px;
    border-left: 1px dashed var(--om-second);
    opacity: 0.32;
    animation: om-thresh var(--om-loop) ease-in-out infinite;
    animation-play-state: var(--om-play);
}

/* The two verdicts occupy the same line and cross-fade, so the row never jumps. */
.gate-states {
    position: relative;
    height: 15px;
}

.gate-state {
    position: absolute;
    left: 0;
    top: 0;
    font-family: var(--mono);
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--ink);
    white-space: nowrap;
    animation-duration: var(--om-loop);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
    animation-play-state: var(--om-play);
}

.gate-state-lo { animation-name: om-state-lo; }
.gate-state-hi { animation-name: om-state-hi; }

.gate-bars {
    display: grid;
    gap: 9px;
    border-top: 1px solid var(--border);
    padding-top: 12px;
}

.gate-row {
    display: grid;
    gap: 5px;
    animation-duration: var(--om-loop);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
    animation-play-state: var(--om-play);
}

.gate-row-off { animation-name: om-off; }
.gate-row-on { animation-name: om-on; }

.gate-name {
    font-family: var(--mono);
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ink);
}

.bar-track {
    height: 6px;
    background: var(--chip);
    border-radius: 3px;
    overflow: hidden;
}

/* Its parent is a plain block, so this needs blockifying by hand: an inline box
   ignores width and height, and the bar collapses to nothing. */
.bar-fill {
    display: block;
    height: 100%;
    background: var(--om-accent);
    border-radius: 3px;
    animation-duration: var(--om-loop);
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    animation-iteration-count: infinite;
    animation-play-state: var(--om-play);
}

.bar-fill-dn { width: 72%; animation-name: om-bar-dn; }
.bar-fill-up { width: 24%; animation-name: om-bar-up; }

/* Figure 2: how far apart two groups sound, across a conversation. */
.fig-adhd {
    display: grid;
    gap: 16px;
}

.adhd-grid {
    display: grid;
    grid-template-columns: 62px 1fr 92px;
    column-gap: 12px;
    row-gap: 20px;
    align-items: center;
}

.adhd-track {
    grid-column: 2;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    height: 58px;
}

.adhd-seg {
    position: relative;
}

.adhd-seg:not(:last-child) {
    border-right: 1px dashed var(--border);
}

.adhd-band,
.adhd-up,
.adhd-dn {
    position: absolute;
    left: 10%;
    right: 10%;
    top: 50%;
    animation-duration: var(--om-loop);
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    animation-iteration-count: infinite;
    animation-play-state: var(--om-play);
}

.adhd-band {
    transform: translateY(-50%);
    height: 2.5px;
    opacity: 0.22;
}

.adhd-dn {
    opacity: 0.5;
}

.adhd-seg:nth-child(1) .adhd-band { animation-name: om-band-1; }
.adhd-seg:nth-child(1) .adhd-up   { animation-name: om-up-1; }
.adhd-seg:nth-child(1) .adhd-dn   { animation-name: om-dn-1; }
.adhd-seg:nth-child(2) .adhd-band { animation-name: om-band-2; }
.adhd-seg:nth-child(2) .adhd-up   { animation-name: om-up-2; }
.adhd-seg:nth-child(2) .adhd-dn   { animation-name: om-dn-2; }
.adhd-seg:nth-child(3) .adhd-band { animation-name: om-band-3; }
.adhd-seg:nth-child(3) .adhd-up   { animation-name: om-up-3; }
.adhd-seg:nth-child(3) .adhd-dn   { animation-name: om-dn-3; }

/* The widening separation is the whole point, so it is data, not decoration. */
.adhd-children .adhd-seg:nth-child(1) { --sep: 5px; }
.adhd-children .adhd-seg:nth-child(2) { --sep: 13px; }
.adhd-children .adhd-seg:nth-child(3) { --sep: 21px; }
.adhd-parents .adhd-seg:nth-child(1) { --sep: 4px; }
.adhd-parents .adhd-seg:nth-child(2) { --sep: 5px; }
.adhd-parents .adhd-seg:nth-child(3) { --sep: 6.5px; }

.adhd-children .adhd-band { background: var(--om-accent); }
.adhd-children .adhd-up { border-top: 2px solid var(--om-accent); }
.adhd-children .adhd-dn { border-top: 2px dotted var(--om-accent); }
.adhd-parents .adhd-band { background: var(--om-second); }
.adhd-parents .adhd-up { border-top: 2px solid var(--om-second); }
.adhd-parents .adhd-dn { border-top: 2px dotted var(--om-second); }

.adhd-note {
    grid-column: 3;
    font-size: 12.5px;
    line-height: 1.3;
    font-weight: 600;
}

.adhd-note-grow { color: var(--om-accent); }
.adhd-note-flat { color: var(--om-second); }

/* A playhead tying both rows to the same moment in the conversation. */
.adhd-sweep {
    grid-column: 2;
    grid-row: 1 / span 2;
    position: relative;
    pointer-events: none;
    align-self: stretch;
}

.sweep-line {
    position: absolute;
    top: -6px;
    bottom: -6px;
    width: 1px;
    background: var(--ink);
    opacity: 0;
    animation: om-sweep var(--om-loop) linear infinite;
    animation-play-state: var(--om-play);
}

.adhd-axis {
    display: grid;
    grid-template-columns: 62px 1fr 92px;
    column-gap: 12px;
    align-items: center;
}

.adhd-axis-labels {
    display: flex;
    justify-content: space-between;
    font-family: var(--mono);
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
}

.adhd-legend {
    display: flex;
    gap: 18px;
    flex-wrap: wrap;
    align-items: center;
    border-top: 1px solid var(--border);
    padding-top: 14px;
}

.legend-item {
    display: flex;
    gap: 8px;
    align-items: center;
    font-size: 12.5px;
    color: var(--ink);
}

.legend-solid { width: 22px; border-top: 2px solid var(--muted); }
.legend-dotted { width: 22px; border-top: 2px dotted var(--muted); opacity: 0.7; }
.legend-band { width: 22px; height: 10px; border-radius: 2px; background: var(--muted); opacity: 0.28; }

/* ── mockframe: screenshot in, device image out ─────────────────── */

.fig-card > .mf-flow {
    margin-top: 0;
}

.mf-flow {
    display: grid;
    grid-template-columns: auto auto minmax(0, 1fr) auto auto;
    column-gap: 16px;
    row-gap: 10px;
    align-items: center;
    width: 100%;
    margin-top: 8px;
}

.mf-shot {
    display: block;
    width: 92px;
    height: 200px;
    border: 1px solid var(--border);
}

.mf-out {
    display: block;
    width: 116px;
    height: 200px;
}

.mf-arrow {
    font-family: var(--mono);
    font-size: 0.85rem;
    color: var(--muted);
}

.mf-cmd {
    background: var(--chip);
    border: 1px solid var(--border);
    padding: 11px 13px;
    display: grid;
    gap: 8px;
    min-width: 0;
}

/* Wrap between arguments, never inside one: breaking at the hyphen in
   `--auto-device` turns a copyable command into a typo. */
.mf-cmd code {
    font-family: var(--mono);
    font-size: 0.67rem;
    line-height: 1.65;
    color: var(--ink);
    word-break: normal;
    overflow-wrap: break-word;
}

.mf-flag,
.mf-cmd code > span {
    white-space: nowrap;
}

.mf-prompt {
    color: var(--accent);
}

.mf-dollar {
    color: var(--muted);
}

.mf-flag {
    color: var(--accent);
}

.mf-or {
    display: flex;
    align-items: center;
    gap: 9px;
}

.mf-or::before,
.mf-or::after {
    content: '';
    height: 1px;
    flex: 1 1 auto;
    background: var(--border);
}

.mf-or span {
    font-family: var(--mono);
    font-size: 0.62rem;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted);
    white-space: nowrap;
}

.mf-cap {
    font-family: var(--mono);
    font-size: 0.62rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
    line-height: 1.4;
}

.mf-cap-in { grid-column: 1; }
.mf-cap-cmd { grid-column: 3; }
.mf-cap-out { grid-column: 5; }

.klar-figure {
    display: grid;
    gap: 9px;
    justify-items: start;
    margin-top: 8px;
}

/* No width cap: the render is the visual proof of the project, so it uses the
   full column the body copy does. */
.klar-shot {
    display: block;
    width: 100%;
    aspect-ratio: 1248 / 1228;
    height: auto;
}

.klar-figure figcaption {
    font-family: var(--mono);
    font-size: 0.62rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
}

/* Bar heights sample a real envelope; the delays walk the phase along it. */
.ser-bar:nth-child(1) { height: 18%; animation-name: om-b0; animation-delay: 0.000s; }
.ser-bar:nth-child(2) { height: 24%; animation-name: om-b1; animation-delay: 0.012s; }
.ser-bar:nth-child(3) { height: 20%; animation-name: om-b2; animation-delay: 0.024s; }
.ser-bar:nth-child(4) { height: 26%; animation-name: om-b3; animation-delay: 0.036s; }
.ser-bar:nth-child(5) { height: 22%; animation-name: om-b4; animation-delay: 0.048s; }
.ser-bar:nth-child(6) { height: 52%; animation-name: om-b5; animation-delay: 0.060s; }
.ser-bar:nth-child(7) { height: 68%; animation-name: om-b6; animation-delay: 0.072s; }
.ser-bar:nth-child(8) { height: 80%; animation-name: om-b7; animation-delay: 0.084s; }
.ser-bar:nth-child(9) { height: 74%; animation-name: om-b8; animation-delay: 0.096s; }
.ser-bar:nth-child(10) { height: 58%; animation-name: om-b9; animation-delay: 0.108s; }
.ser-bar:nth-child(11) { height: 44%; animation-name: om-b10; animation-delay: 0.120s; }
.ser-bar:nth-child(12) { height: 46%; animation-name: om-b11; animation-delay: 0.132s; }
.ser-bar:nth-child(13) { height: 62%; animation-name: om-b12; animation-delay: 0.144s; }
.ser-bar:nth-child(14) { height: 78%; animation-name: om-b13; animation-delay: 0.156s; }
.ser-bar:nth-child(15) { height: 92%; animation-name: om-b14; animation-delay: 0.168s; }
.ser-bar:nth-child(16) { height: 100%; animation-name: om-b15; animation-delay: 0.180s; }
.ser-bar:nth-child(17) { height: 88%; animation-name: om-b16; animation-delay: 0.192s; }
.ser-bar:nth-child(18) { height: 70%; animation-name: om-b17; animation-delay: 0.204s; }
.ser-bar:nth-child(19) { height: 48%; animation-name: om-b18; animation-delay: 0.216s; }
.ser-bar:nth-child(20) { height: 28%; animation-name: om-b19; animation-delay: 0.228s; }

/* ── Background timeline ────────────────────────────────────────── */

.timeline {
    border-left: 1px solid var(--border);
    padding-left: 28px;
    display: grid;
    gap: 34px;
}

.timeline-item {
    position: relative;
}

/* Sits centred on the rail; the bg-coloured ring masks the line behind it. */
.timeline-item::before {
    content: '';
    position: absolute;
    left: -33px;
    top: 8px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--bg);
    border: 1px solid var(--muted);
    box-shadow: 0 0 0 4px var(--bg);
}

.timeline-item.is-current::before {
    background: var(--accent);
    border-color: var(--accent);
}

.timeline-date {
    font-family: var(--mono);
    font-size: 0.7rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 5px;
}

.is-current .timeline-date {
    color: var(--accent);
}

.timeline-role {
    font-weight: 600;
    line-height: 1.4;
}

.timeline-org {
    color: var(--muted);
    font-size: 0.95rem;
}

/* Optional detail line. Only entries that need explaining carry one, so it sits a
   step down from .timeline-org rather than reading as another label. */
.timeline-note {
    color: var(--muted);
    font-size: 0.9rem;
    line-height: 1.6;
    max-width: 54ch;
    margin-top: 9px;
    text-wrap: pretty;
}

/* ── Legal page ─────────────────────────────────────────────────── */

.legal {
    padding: 24px 0 72px;
}

.legal h1 {
    font-size: clamp(1.8rem, 5vw, 2.3rem);
    margin-bottom: 6px;
}

/* sits directly under the h1, so it carries no trailing space of its own */
.legal-sub {
    margin-bottom: 0;
}

.legal h2 {
    font-family: var(--display);
    font-weight: 600;
    font-size: 1.15rem;
    letter-spacing: -0.01em;
    margin: 40px 0 12px;
}

.legal p {
    color: var(--muted);
    max-width: 62ch;
    text-wrap: pretty;
}

.legal p + p {
    margin-top: 12px;
}

/* ── Footer ─────────────────────────────────────────────────────── */

footer {
    border-top: 1px solid var(--border);
    padding: 32px 0 48px;
    font-size: 0.85rem;
    color: var(--muted);
}

footer .wrap {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}

footer a {
    color: var(--muted);
    text-decoration: none;
}

footer a:hover {
    color: var(--ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* ── Entrance motion (load only, gated) ─────────────────────────── */

@media (prefers-reduced-motion: no-preference) {
    #hero .wrap {
        animation: om-rise 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
    }

    @keyframes om-rise {
        from {
            opacity: 0;
            transform: translateY(12px);
        }
        to {
            opacity: 1;
            transform: none;
        }
    }
}

/* ── Reveal on scroll ───────────────────────────────────────────── */

/* Nothing is hidden by CSS alone. The script adds .reveal-pending only to
   elements still below the fold, so a page without JavaScript, or one whose
   observer never reports, shows everything, and content already on screen at
   load never blinks out and back. */
@media (prefers-reduced-motion: no-preference) {
    .reveal-pending {
        opacity: 0;
        transform: translateY(16px);
    }

    .reveal-pending.is-visible {
        opacity: 1;
        transform: none;
        transition: opacity 0.55s cubic-bezier(0.16, 1, 0.3, 1),
                    transform 0.55s cubic-bezier(0.16, 1, 0.3, 1);
    }
}

/* ── Disclosure motion ─────────────────────────────────────────── */

/* interpolate-size lets the row grow from 0 to its natural height. The framing
   script computes where the row will settle before the transition starts, so
   the page travels on the same curve and beat instead of correcting afterwards.
   Browsers without ::details-content support simply snap open. */
@media (prefers-reduced-motion: no-preference) {
    html {
        interpolate-size: allow-keywords;
    }

    .project::details-content {
        block-size: 0;
        overflow: clip;
        transition: block-size 0.46s cubic-bezier(0.22, 1, 0.36, 1),
                    content-visibility 0.46s allow-discrete;
    }

    /* Chromium can interpolate straight to the natural height. */
    @supports (interpolate-size: allow-keywords) {
        .project[open]::details-content {
            block-size: auto;
        }
    }

    /* Safari and Firefox have ::details-content but not interpolate-size, so
       `auto` is not an interpolable end point and the row would snap open. The
       script measures the body and hands the same transition a concrete pixel
       height instead, which both ends can animate between. */
    @supports not (interpolate-size: allow-keywords) {
        .project[open]::details-content {
            block-size: var(--body-h, auto);
        }
    }

    .project[open] > .project-body > * {
        animation: om-disclose 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
    }

    .project[open] > .project-body > *:nth-child(2) {
        animation-delay: 60ms;
    }

    .project[open] > .project-body > *:nth-child(3) {
        animation-delay: 120ms;
    }

    @keyframes om-disclose {
        from {
            opacity: 0;
            transform: translateY(-4px);
        }
        to {
            opacity: 1;
            transform: none;
        }
    }
}

/* ── Figure animation ───────────────────────────────────────────── */

@keyframes om-gate{0%,33%{width:16%}45%,86%{width:80%}96%,100%{width:16%}}
@keyframes om-flow{0%,31%{left:52%;opacity:0}35%{opacity:1}43%{left:95%;opacity:1}47%,100%{left:95%;opacity:0}}
@keyframes om-thresh{0%,34%{opacity:.32}46%,86%{opacity:1}96%,100%{opacity:.32}}
@keyframes om-bar-up{0%,34%{width:24%}46%,86%{width:84%}96%,100%{width:24%}}
@keyframes om-bar-dn{0%,34%{width:72%}46%,86%{width:22%}96%,100%{width:72%}}
@keyframes om-on{0%,35%{opacity:.32}47%,86%{opacity:1}96%,100%{opacity:.32}}
@keyframes om-off{0%,35%{opacity:1}47%,86%{opacity:.32}96%,100%{opacity:1}}
@keyframes om-state-lo{0%,34%{opacity:1}40%,95%{opacity:0}99%,100%{opacity:1}}
@keyframes om-state-hi{0%,40%{opacity:0}47%,88%{opacity:1}94%,100%{opacity:0}}
@keyframes om-b0{0%{transform:scaleY(0.400)}2.5%{transform:scaleY(0.416)}5%{transform:scaleY(0.427)}7.5%{transform:scaleY(0.427)}10%{transform:scaleY(0.416)}12.5%{transform:scaleY(0.400)}15%{transform:scaleY(0.384)}17.5%{transform:scaleY(0.373)}20%{transform:scaleY(0.373)}22.5%{transform:scaleY(0.384)}25%{transform:scaleY(0.400)}27.5%{transform:scaleY(0.416)}30%{transform:scaleY(0.427)}32.5%{transform:scaleY(0.427)}35%{transform:scaleY(0.454)}37.5%{transform:scaleY(0.555)}40%{transform:scaleY(0.676)}42.5%{transform:scaleY(0.779)}45%{transform:scaleY(0.830)}47.5%{transform:scaleY(0.852)}50%{transform:scaleY(0.889)}52.5%{transform:scaleY(0.925)}55%{transform:scaleY(0.948)}57.5%{transform:scaleY(0.948)}60%{transform:scaleY(0.925)}62.5%{transform:scaleY(0.889)}65%{transform:scaleY(0.852)}67.5%{transform:scaleY(0.830)}70%{transform:scaleY(0.830)}72.5%{transform:scaleY(0.852)}75%{transform:scaleY(0.889)}77.5%{transform:scaleY(0.925)}80%{transform:scaleY(0.948)}82.5%{transform:scaleY(0.948)}85%{transform:scaleY(0.925)}87.5%{transform:scaleY(0.859)}90%{transform:scaleY(0.687)}92.5%{transform:scaleY(0.502)}95%{transform:scaleY(0.386)}97.5%{transform:scaleY(0.384)}100%{transform:scaleY(0.400)}}
@keyframes om-b1{0%{transform:scaleY(0.426)}2.5%{transform:scaleY(0.415)}5%{transform:scaleY(0.398)}7.5%{transform:scaleY(0.382)}10%{transform:scaleY(0.373)}12.5%{transform:scaleY(0.374)}15%{transform:scaleY(0.385)}17.5%{transform:scaleY(0.402)}20%{transform:scaleY(0.418)}22.5%{transform:scaleY(0.427)}25%{transform:scaleY(0.426)}27.5%{transform:scaleY(0.415)}30%{transform:scaleY(0.398)}32.5%{transform:scaleY(0.382)}35%{transform:scaleY(0.409)}37.5%{transform:scaleY(0.527)}40%{transform:scaleY(0.695)}42.5%{transform:scaleY(0.863)}45%{transform:scaleY(0.958)}47.5%{transform:scaleY(0.979)}50%{transform:scaleY(0.976)}52.5%{transform:scaleY(0.951)}55%{transform:scaleY(0.913)}57.5%{transform:scaleY(0.876)}60%{transform:scaleY(0.855)}62.5%{transform:scaleY(0.857)}65%{transform:scaleY(0.882)}67.5%{transform:scaleY(0.921)}70%{transform:scaleY(0.958)}72.5%{transform:scaleY(0.979)}75%{transform:scaleY(0.976)}77.5%{transform:scaleY(0.951)}80%{transform:scaleY(0.913)}82.5%{transform:scaleY(0.876)}85%{transform:scaleY(0.855)}87.5%{transform:scaleY(0.828)}90%{transform:scaleY(0.707)}92.5%{transform:scaleY(0.548)}95%{transform:scaleY(0.433)}97.5%{transform:scaleY(0.427)}100%{transform:scaleY(0.426)}}
@keyframes om-b2{0%{transform:scaleY(0.381)}2.5%{transform:scaleY(0.372)}5%{transform:scaleY(0.375)}7.5%{transform:scaleY(0.387)}10%{transform:scaleY(0.404)}12.5%{transform:scaleY(0.419)}15%{transform:scaleY(0.428)}17.5%{transform:scaleY(0.425)}20%{transform:scaleY(0.413)}22.5%{transform:scaleY(0.396)}25%{transform:scaleY(0.381)}27.5%{transform:scaleY(0.372)}30%{transform:scaleY(0.375)}32.5%{transform:scaleY(0.387)}35%{transform:scaleY(0.445)}37.5%{transform:scaleY(0.602)}40%{transform:scaleY(0.794)}42.5%{transform:scaleY(0.945)}45%{transform:scaleY(0.982)}47.5%{transform:scaleY(0.942)}50%{transform:scaleY(0.904)}52.5%{transform:scaleY(0.885)}55%{transform:scaleY(0.890)}57.5%{transform:scaleY(0.918)}60%{transform:scaleY(0.958)}62.5%{transform:scaleY(0.996)}65%{transform:scaleY(1.015)}67.5%{transform:scaleY(1.010)}70%{transform:scaleY(0.982)}72.5%{transform:scaleY(0.942)}75%{transform:scaleY(0.904)}77.5%{transform:scaleY(0.885)}80%{transform:scaleY(0.890)}82.5%{transform:scaleY(0.918)}85%{transform:scaleY(0.958)}87.5%{transform:scaleY(0.961)}90%{transform:scaleY(0.808)}92.5%{transform:scaleY(0.590)}95%{transform:scaleY(0.429)}97.5%{transform:scaleY(0.396)}100%{transform:scaleY(0.381)}}
@keyframes om-b3{0%{transform:scaleY(0.388)}2.5%{transform:scaleY(0.405)}5%{transform:scaleY(0.420)}7.5%{transform:scaleY(0.428)}10%{transform:scaleY(0.425)}12.5%{transform:scaleY(0.412)}15%{transform:scaleY(0.395)}17.5%{transform:scaleY(0.380)}20%{transform:scaleY(0.372)}22.5%{transform:scaleY(0.375)}25%{transform:scaleY(0.388)}27.5%{transform:scaleY(0.405)}30%{transform:scaleY(0.420)}32.5%{transform:scaleY(0.428)}35%{transform:scaleY(0.466)}37.5%{transform:scaleY(0.582)}40%{transform:scaleY(0.717)}42.5%{transform:scaleY(0.820)}45%{transform:scaleY(0.859)}47.5%{transform:scaleY(0.866)}50%{transform:scaleY(0.896)}52.5%{transform:scaleY(0.935)}55%{transform:scaleY(0.970)}57.5%{transform:scaleY(0.987)}60%{transform:scaleY(0.980)}62.5%{transform:scaleY(0.951)}65%{transform:scaleY(0.911)}67.5%{transform:scaleY(0.876)}70%{transform:scaleY(0.859)}72.5%{transform:scaleY(0.866)}75%{transform:scaleY(0.896)}77.5%{transform:scaleY(0.935)}80%{transform:scaleY(0.970)}82.5%{transform:scaleY(0.987)}85%{transform:scaleY(0.980)}87.5%{transform:scaleY(0.918)}90%{transform:scaleY(0.729)}92.5%{transform:scaleY(0.519)}95%{transform:scaleY(0.386)}97.5%{transform:scaleY(0.375)}100%{transform:scaleY(0.388)}}
@keyframes om-b4{0%{transform:scaleY(0.428)}2.5%{transform:scaleY(0.424)}5%{transform:scaleY(0.410)}7.5%{transform:scaleY(0.393)}10%{transform:scaleY(0.378)}12.5%{transform:scaleY(0.372)}15%{transform:scaleY(0.376)}17.5%{transform:scaleY(0.390)}20%{transform:scaleY(0.407)}22.5%{transform:scaleY(0.422)}25%{transform:scaleY(0.428)}27.5%{transform:scaleY(0.424)}30%{transform:scaleY(0.410)}32.5%{transform:scaleY(0.393)}35%{transform:scaleY(0.408)}37.5%{transform:scaleY(0.495)}40%{transform:scaleY(0.622)}42.5%{transform:scaleY(0.751)}45%{transform:scaleY(0.832)}47.5%{transform:scaleY(0.862)}50%{transform:scaleY(0.875)}52.5%{transform:scaleY(0.867)}55%{transform:scaleY(0.839)}57.5%{transform:scaleY(0.804)}60%{transform:scaleY(0.774)}62.5%{transform:scaleY(0.761)}65%{transform:scaleY(0.770)}67.5%{transform:scaleY(0.797)}70%{transform:scaleY(0.832)}72.5%{transform:scaleY(0.862)}75%{transform:scaleY(0.875)}77.5%{transform:scaleY(0.867)}80%{transform:scaleY(0.839)}82.5%{transform:scaleY(0.804)}85%{transform:scaleY(0.774)}87.5%{transform:scaleY(0.737)}90%{transform:scaleY(0.631)}92.5%{transform:scaleY(0.504)}95%{transform:scaleY(0.419)}97.5%{transform:scaleY(0.422)}100%{transform:scaleY(0.428)}}
@keyframes om-b5{0%{transform:scaleY(0.391)}2.5%{transform:scaleY(0.377)}5%{transform:scaleY(0.372)}7.5%{transform:scaleY(0.377)}10%{transform:scaleY(0.391)}12.5%{transform:scaleY(0.409)}15%{transform:scaleY(0.423)}17.5%{transform:scaleY(0.428)}20%{transform:scaleY(0.423)}22.5%{transform:scaleY(0.409)}25%{transform:scaleY(0.391)}27.5%{transform:scaleY(0.377)}30%{transform:scaleY(0.372)}32.5%{transform:scaleY(0.377)}35%{transform:scaleY(0.399)}37.5%{transform:scaleY(0.441)}40%{transform:scaleY(0.489)}42.5%{transform:scaleY(0.523)}45%{transform:scaleY(0.528)}47.5%{transform:scaleY(0.511)}50%{transform:scaleY(0.489)}52.5%{transform:scaleY(0.472)}55%{transform:scaleY(0.465)}57.5%{transform:scaleY(0.472)}60%{transform:scaleY(0.489)}62.5%{transform:scaleY(0.511)}65%{transform:scaleY(0.528)}67.5%{transform:scaleY(0.535)}70%{transform:scaleY(0.528)}72.5%{transform:scaleY(0.511)}75%{transform:scaleY(0.489)}77.5%{transform:scaleY(0.472)}80%{transform:scaleY(0.465)}82.5%{transform:scaleY(0.472)}85%{transform:scaleY(0.489)}87.5%{transform:scaleY(0.505)}90%{transform:scaleY(0.491)}92.5%{transform:scaleY(0.458)}95%{transform:scaleY(0.426)}97.5%{transform:scaleY(0.409)}100%{transform:scaleY(0.391)}}
@keyframes om-b6{0%{transform:scaleY(0.378)}2.5%{transform:scaleY(0.393)}5%{transform:scaleY(0.410)}7.5%{transform:scaleY(0.424)}10%{transform:scaleY(0.428)}12.5%{transform:scaleY(0.422)}15%{transform:scaleY(0.407)}17.5%{transform:scaleY(0.390)}20%{transform:scaleY(0.376)}22.5%{transform:scaleY(0.372)}25%{transform:scaleY(0.378)}27.5%{transform:scaleY(0.393)}30%{transform:scaleY(0.410)}32.5%{transform:scaleY(0.424)}35%{transform:scaleY(0.431)}37.5%{transform:scaleY(0.435)}40%{transform:scaleY(0.433)}42.5%{transform:scaleY(0.425)}45%{transform:scaleY(0.415)}47.5%{transform:scaleY(0.410)}50%{transform:scaleY(0.417)}52.5%{transform:scaleY(0.433)}55%{transform:scaleY(0.453)}57.5%{transform:scaleY(0.467)}60%{transform:scaleY(0.472)}62.5%{transform:scaleY(0.465)}65%{transform:scaleY(0.449)}67.5%{transform:scaleY(0.430)}70%{transform:scaleY(0.415)}72.5%{transform:scaleY(0.410)}75%{transform:scaleY(0.417)}77.5%{transform:scaleY(0.433)}80%{transform:scaleY(0.453)}82.5%{transform:scaleY(0.467)}85%{transform:scaleY(0.472)}87.5%{transform:scaleY(0.462)}90%{transform:scaleY(0.434)}92.5%{transform:scaleY(0.401)}95%{transform:scaleY(0.377)}97.5%{transform:scaleY(0.372)}100%{transform:scaleY(0.378)}}
@keyframes om-b7{0%{transform:scaleY(0.425)}2.5%{transform:scaleY(0.428)}5%{transform:scaleY(0.420)}7.5%{transform:scaleY(0.405)}10%{transform:scaleY(0.388)}12.5%{transform:scaleY(0.375)}15%{transform:scaleY(0.372)}17.5%{transform:scaleY(0.380)}20%{transform:scaleY(0.395)}22.5%{transform:scaleY(0.412)}25%{transform:scaleY(0.425)}27.5%{transform:scaleY(0.428)}30%{transform:scaleY(0.420)}32.5%{transform:scaleY(0.405)}35%{transform:scaleY(0.382)}37.5%{transform:scaleY(0.349)}40%{transform:scaleY(0.321)}42.5%{transform:scaleY(0.306)}45%{transform:scaleY(0.308)}47.5%{transform:scaleY(0.322)}50%{transform:scaleY(0.332)}52.5%{transform:scaleY(0.334)}55%{transform:scaleY(0.328)}57.5%{transform:scaleY(0.317)}60%{transform:scaleY(0.303)}62.5%{transform:scaleY(0.293)}65%{transform:scaleY(0.291)}67.5%{transform:scaleY(0.297)}70%{transform:scaleY(0.308)}72.5%{transform:scaleY(0.322)}75%{transform:scaleY(0.332)}77.5%{transform:scaleY(0.334)}80%{transform:scaleY(0.328)}82.5%{transform:scaleY(0.317)}85%{transform:scaleY(0.303)}87.5%{transform:scaleY(0.298)}90%{transform:scaleY(0.319)}92.5%{transform:scaleY(0.356)}95%{transform:scaleY(0.392)}97.5%{transform:scaleY(0.412)}100%{transform:scaleY(0.425)}}
@keyframes om-b8{0%{transform:scaleY(0.404)}2.5%{transform:scaleY(0.387)}5%{transform:scaleY(0.375)}7.5%{transform:scaleY(0.372)}10%{transform:scaleY(0.381)}12.5%{transform:scaleY(0.396)}15%{transform:scaleY(0.413)}17.5%{transform:scaleY(0.425)}20%{transform:scaleY(0.428)}22.5%{transform:scaleY(0.419)}25%{transform:scaleY(0.404)}27.5%{transform:scaleY(0.387)}30%{transform:scaleY(0.375)}32.5%{transform:scaleY(0.372)}35%{transform:scaleY(0.383)}37.5%{transform:scaleY(0.407)}40%{transform:scaleY(0.434)}42.5%{transform:scaleY(0.456)}45%{transform:scaleY(0.462)}47.5%{transform:scaleY(0.453)}50%{transform:scaleY(0.436)}52.5%{transform:scaleY(0.418)}55%{transform:scaleY(0.405)}57.5%{transform:scaleY(0.403)}60%{transform:scaleY(0.412)}62.5%{transform:scaleY(0.429)}65%{transform:scaleY(0.447)}67.5%{transform:scaleY(0.460)}70%{transform:scaleY(0.462)}72.5%{transform:scaleY(0.453)}75%{transform:scaleY(0.436)}77.5%{transform:scaleY(0.418)}80%{transform:scaleY(0.405)}82.5%{transform:scaleY(0.403)}85%{transform:scaleY(0.412)}87.5%{transform:scaleY(0.427)}90%{transform:scaleY(0.435)}92.5%{transform:scaleY(0.435)}95%{transform:scaleY(0.428)}97.5%{transform:scaleY(0.419)}100%{transform:scaleY(0.404)}}
@keyframes om-b9{0%{transform:scaleY(0.373)}2.5%{transform:scaleY(0.382)}5%{transform:scaleY(0.398)}7.5%{transform:scaleY(0.415)}10%{transform:scaleY(0.426)}12.5%{transform:scaleY(0.427)}15%{transform:scaleY(0.418)}17.5%{transform:scaleY(0.402)}20%{transform:scaleY(0.385)}22.5%{transform:scaleY(0.374)}25%{transform:scaleY(0.373)}27.5%{transform:scaleY(0.382)}30%{transform:scaleY(0.398)}32.5%{transform:scaleY(0.415)}35%{transform:scaleY(0.433)}37.5%{transform:scaleY(0.455)}40%{transform:scaleY(0.472)}42.5%{transform:scaleY(0.476)}45%{transform:scaleY(0.465)}47.5%{transform:scaleY(0.451)}50%{transform:scaleY(0.450)}52.5%{transform:scaleY(0.461)}55%{transform:scaleY(0.481)}57.5%{transform:scaleY(0.501)}60%{transform:scaleY(0.514)}62.5%{transform:scaleY(0.515)}65%{transform:scaleY(0.504)}67.5%{transform:scaleY(0.485)}70%{transform:scaleY(0.465)}72.5%{transform:scaleY(0.451)}75%{transform:scaleY(0.450)}77.5%{transform:scaleY(0.461)}80%{transform:scaleY(0.481)}82.5%{transform:scaleY(0.501)}85%{transform:scaleY(0.514)}87.5%{transform:scaleY(0.510)}90%{transform:scaleY(0.474)}92.5%{transform:scaleY(0.425)}95%{transform:scaleY(0.387)}97.5%{transform:scaleY(0.374)}100%{transform:scaleY(0.373)}}
@keyframes om-b10{0%{transform:scaleY(0.416)}2.5%{transform:scaleY(0.427)}5%{transform:scaleY(0.427)}7.5%{transform:scaleY(0.416)}10%{transform:scaleY(0.400)}12.5%{transform:scaleY(0.384)}15%{transform:scaleY(0.373)}17.5%{transform:scaleY(0.373)}20%{transform:scaleY(0.384)}22.5%{transform:scaleY(0.400)}25%{transform:scaleY(0.416)}27.5%{transform:scaleY(0.427)}30%{transform:scaleY(0.427)}32.5%{transform:scaleY(0.416)}35%{transform:scaleY(0.407)}37.5%{transform:scaleY(0.414)}40%{transform:scaleY(0.432)}42.5%{transform:scaleY(0.456)}45%{transform:scaleY(0.479)}47.5%{transform:scaleY(0.500)}50%{transform:scaleY(0.521)}52.5%{transform:scaleY(0.533)}55%{transform:scaleY(0.533)}57.5%{transform:scaleY(0.521)}60%{transform:scaleY(0.500)}62.5%{transform:scaleY(0.479)}65%{transform:scaleY(0.467)}67.5%{transform:scaleY(0.467)}70%{transform:scaleY(0.479)}72.5%{transform:scaleY(0.500)}75%{transform:scaleY(0.521)}77.5%{transform:scaleY(0.533)}80%{transform:scaleY(0.533)}82.5%{transform:scaleY(0.521)}85%{transform:scaleY(0.500)}87.5%{transform:scaleY(0.474)}90%{transform:scaleY(0.434)}92.5%{transform:scaleY(0.400)}95%{transform:scaleY(0.386)}97.5%{transform:scaleY(0.400)}100%{transform:scaleY(0.416)}}
@keyframes om-b11{0%{transform:scaleY(0.271)}2.5%{transform:scaleY(0.260)}5%{transform:scaleY(0.249)}7.5%{transform:scaleY(0.243)}10%{transform:scaleY(0.244)}12.5%{transform:scaleY(0.251)}15%{transform:scaleY(0.262)}17.5%{transform:scaleY(0.273)}20%{transform:scaleY(0.279)}22.5%{transform:scaleY(0.278)}25%{transform:scaleY(0.271)}27.5%{transform:scaleY(0.260)}30%{transform:scaleY(0.249)}32.5%{transform:scaleY(0.243)}35%{transform:scaleY(0.295)}37.5%{transform:scaleY(0.476)}40%{transform:scaleY(0.725)}42.5%{transform:scaleY(0.958)}45%{transform:scaleY(1.068)}47.5%{transform:scaleY(1.065)}50%{transform:scaleY(1.038)}52.5%{transform:scaleY(0.996)}55%{transform:scaleY(0.955)}57.5%{transform:scaleY(0.932)}60%{transform:scaleY(0.935)}62.5%{transform:scaleY(0.962)}65%{transform:scaleY(1.004)}67.5%{transform:scaleY(1.045)}70%{transform:scaleY(1.068)}72.5%{transform:scaleY(1.065)}75%{transform:scaleY(1.038)}77.5%{transform:scaleY(0.996)}80%{transform:scaleY(0.955)}82.5%{transform:scaleY(0.932)}85%{transform:scaleY(0.935)}87.5%{transform:scaleY(0.919)}90%{transform:scaleY(0.743)}92.5%{transform:scaleY(0.490)}95%{transform:scaleY(0.301)}97.5%{transform:scaleY(0.278)}100%{transform:scaleY(0.271)}}
@keyframes om-b12{0%{transform:scaleY(0.156)}2.5%{transform:scaleY(0.157)}5%{transform:scaleY(0.162)}7.5%{transform:scaleY(0.169)}10%{transform:scaleY(0.176)}12.5%{transform:scaleY(0.179)}15%{transform:scaleY(0.178)}17.5%{transform:scaleY(0.173)}20%{transform:scaleY(0.166)}22.5%{transform:scaleY(0.160)}25%{transform:scaleY(0.156)}27.5%{transform:scaleY(0.157)}30%{transform:scaleY(0.162)}32.5%{transform:scaleY(0.169)}35%{transform:scaleY(0.240)}37.5%{transform:scaleY(0.461)}40%{transform:scaleY(0.730)}42.5%{transform:scaleY(0.937)}45%{transform:scaleY(0.991)}47.5%{transform:scaleY(0.952)}50%{transform:scaleY(0.931)}52.5%{transform:scaleY(0.937)}55%{transform:scaleY(0.966)}57.5%{transform:scaleY(1.009)}60%{transform:scaleY(1.048)}62.5%{transform:scaleY(1.069)}65%{transform:scaleY(1.063)}67.5%{transform:scaleY(1.034)}70%{transform:scaleY(0.991)}72.5%{transform:scaleY(0.952)}75%{transform:scaleY(0.931)}77.5%{transform:scaleY(0.937)}80%{transform:scaleY(0.966)}82.5%{transform:scaleY(1.009)}85%{transform:scaleY(1.048)}87.5%{transform:scaleY(1.015)}90%{transform:scaleY(0.752)}92.5%{transform:scaleY(0.416)}95%{transform:scaleY(0.189)}97.5%{transform:scaleY(0.160)}100%{transform:scaleY(0.156)}}
@keyframes om-b13{0%{transform:scaleY(0.114)}2.5%{transform:scaleY(0.119)}5%{transform:scaleY(0.121)}7.5%{transform:scaleY(0.120)}10%{transform:scaleY(0.116)}12.5%{transform:scaleY(0.111)}15%{transform:scaleY(0.107)}17.5%{transform:scaleY(0.105)}20%{transform:scaleY(0.106)}22.5%{transform:scaleY(0.109)}25%{transform:scaleY(0.114)}27.5%{transform:scaleY(0.119)}30%{transform:scaleY(0.121)}32.5%{transform:scaleY(0.120)}35%{transform:scaleY(0.184)}37.5%{transform:scaleY(0.388)}40%{transform:scaleY(0.632)}42.5%{transform:scaleY(0.838)}45%{transform:scaleY(0.939)}47.5%{transform:scaleY(0.970)}50%{transform:scaleY(1.013)}52.5%{transform:scaleY(1.051)}55%{transform:scaleY(1.069)}57.5%{transform:scaleY(1.061)}60%{transform:scaleY(1.030)}62.5%{transform:scaleY(0.987)}65%{transform:scaleY(0.949)}67.5%{transform:scaleY(0.931)}70%{transform:scaleY(0.939)}72.5%{transform:scaleY(0.970)}75%{transform:scaleY(1.013)}77.5%{transform:scaleY(1.051)}80%{transform:scaleY(1.069)}82.5%{transform:scaleY(1.061)}85%{transform:scaleY(1.030)}87.5%{transform:scaleY(0.934)}90%{transform:scaleY(0.653)}92.5%{transform:scaleY(0.338)}95%{transform:scaleY(0.129)}97.5%{transform:scaleY(0.109)}100%{transform:scaleY(0.114)}}
@keyframes om-b14{0%{transform:scaleY(0.120)}2.5%{transform:scaleY(0.116)}5%{transform:scaleY(0.111)}7.5%{transform:scaleY(0.107)}10%{transform:scaleY(0.105)}12.5%{transform:scaleY(0.106)}15%{transform:scaleY(0.110)}17.5%{transform:scaleY(0.115)}20%{transform:scaleY(0.119)}22.5%{transform:scaleY(0.121)}25%{transform:scaleY(0.120)}27.5%{transform:scaleY(0.116)}30%{transform:scaleY(0.111)}32.5%{transform:scaleY(0.107)}35%{transform:scaleY(0.166)}37.5%{transform:scaleY(0.370)}40%{transform:scaleY(0.649)}42.5%{transform:scaleY(0.916)}45%{transform:scaleY(1.054)}47.5%{transform:scaleY(1.070)}50%{transform:scaleY(1.059)}52.5%{transform:scaleY(1.026)}55%{transform:scaleY(0.983)}57.5%{transform:scaleY(0.946)}60%{transform:scaleY(0.930)}62.5%{transform:scaleY(0.941)}65%{transform:scaleY(0.974)}67.5%{transform:scaleY(1.017)}70%{transform:scaleY(1.054)}72.5%{transform:scaleY(1.070)}75%{transform:scaleY(1.059)}77.5%{transform:scaleY(1.026)}80%{transform:scaleY(0.983)}82.5%{transform:scaleY(0.946)}85%{transform:scaleY(0.930)}87.5%{transform:scaleY(0.890)}90%{transform:scaleY(0.670)}92.5%{transform:scaleY(0.369)}95%{transform:scaleY(0.145)}97.5%{transform:scaleY(0.121)}100%{transform:scaleY(0.120)}}
@keyframes om-b15{0%{transform:scaleY(0.075)}2.5%{transform:scaleY(0.074)}5%{transform:scaleY(0.075)}7.5%{transform:scaleY(0.078)}10%{transform:scaleY(0.082)}12.5%{transform:scaleY(0.085)}15%{transform:scaleY(0.086)}17.5%{transform:scaleY(0.085)}20%{transform:scaleY(0.082)}22.5%{transform:scaleY(0.078)}25%{transform:scaleY(0.075)}27.5%{transform:scaleY(0.074)}30%{transform:scaleY(0.075)}32.5%{transform:scaleY(0.078)}35%{transform:scaleY(0.151)}37.5%{transform:scaleY(0.392)}40%{transform:scaleY(0.700)}42.5%{transform:scaleY(0.948)}45%{transform:scaleY(1.022)}47.5%{transform:scaleY(0.978)}50%{transform:scaleY(0.943)}52.5%{transform:scaleY(0.930)}55%{transform:scaleY(0.943)}57.5%{transform:scaleY(0.978)}60%{transform:scaleY(1.022)}62.5%{transform:scaleY(1.057)}65%{transform:scaleY(1.070)}67.5%{transform:scaleY(1.057)}70%{transform:scaleY(1.022)}72.5%{transform:scaleY(0.978)}75%{transform:scaleY(0.943)}77.5%{transform:scaleY(0.930)}80%{transform:scaleY(0.943)}82.5%{transform:scaleY(0.978)}85%{transform:scaleY(1.022)}87.5%{transform:scaleY(0.998)}90%{transform:scaleY(0.723)}92.5%{transform:scaleY(0.358)}95%{transform:scaleY(0.108)}97.5%{transform:scaleY(0.078)}100%{transform:scaleY(0.075)}}
@keyframes om-b16{0%{transform:scaleY(0.107)}2.5%{transform:scaleY(0.112)}5%{transform:scaleY(0.116)}7.5%{transform:scaleY(0.117)}10%{transform:scaleY(0.115)}12.5%{transform:scaleY(0.111)}15%{transform:scaleY(0.106)}17.5%{transform:scaleY(0.103)}20%{transform:scaleY(0.101)}22.5%{transform:scaleY(0.103)}25%{transform:scaleY(0.107)}27.5%{transform:scaleY(0.112)}30%{transform:scaleY(0.116)}32.5%{transform:scaleY(0.117)}35%{transform:scaleY(0.185)}37.5%{transform:scaleY(0.398)}40%{transform:scaleY(0.648)}42.5%{transform:scaleY(0.847)}45%{transform:scaleY(0.930)}47.5%{transform:scaleY(0.946)}50%{transform:scaleY(0.983)}52.5%{transform:scaleY(1.026)}55%{transform:scaleY(1.059)}57.5%{transform:scaleY(1.070)}60%{transform:scaleY(1.054)}62.5%{transform:scaleY(1.017)}65%{transform:scaleY(0.974)}67.5%{transform:scaleY(0.941)}70%{transform:scaleY(0.930)}72.5%{transform:scaleY(0.946)}75%{transform:scaleY(0.983)}77.5%{transform:scaleY(1.026)}80%{transform:scaleY(1.059)}82.5%{transform:scaleY(1.070)}85%{transform:scaleY(1.054)}87.5%{transform:scaleY(0.962)}90%{transform:scaleY(0.669)}92.5%{transform:scaleY(0.339)}95%{transform:scaleY(0.125)}97.5%{transform:scaleY(0.103)}100%{transform:scaleY(0.107)}}
@keyframes om-b17{0%{transform:scaleY(0.110)}2.5%{transform:scaleY(0.108)}5%{transform:scaleY(0.104)}7.5%{transform:scaleY(0.100)}10%{transform:scaleY(0.097)}12.5%{transform:scaleY(0.096)}15%{transform:scaleY(0.098)}17.5%{transform:scaleY(0.102)}20%{transform:scaleY(0.106)}22.5%{transform:scaleY(0.109)}25%{transform:scaleY(0.110)}27.5%{transform:scaleY(0.108)}30%{transform:scaleY(0.104)}32.5%{transform:scaleY(0.100)}35%{transform:scaleY(0.159)}37.5%{transform:scaleY(0.360)}40%{transform:scaleY(0.629)}42.5%{transform:scaleY(0.888)}45%{transform:scaleY(1.030)}47.5%{transform:scaleY(1.061)}50%{transform:scaleY(1.069)}52.5%{transform:scaleY(1.051)}55%{transform:scaleY(1.013)}57.5%{transform:scaleY(0.970)}60%{transform:scaleY(0.939)}62.5%{transform:scaleY(0.931)}65%{transform:scaleY(0.949)}67.5%{transform:scaleY(0.987)}70%{transform:scaleY(1.030)}72.5%{transform:scaleY(1.061)}75%{transform:scaleY(1.069)}77.5%{transform:scaleY(1.051)}80%{transform:scaleY(1.013)}82.5%{transform:scaleY(0.970)}85%{transform:scaleY(0.939)}87.5%{transform:scaleY(0.880)}90%{transform:scaleY(0.649)}92.5%{transform:scaleY(0.351)}95%{transform:scaleY(0.132)}97.5%{transform:scaleY(0.109)}100%{transform:scaleY(0.110)}}
@keyframes om-b18{0%{transform:scaleY(0.177)}2.5%{transform:scaleY(0.172)}5%{transform:scaleY(0.171)}7.5%{transform:scaleY(0.175)}10%{transform:scaleY(0.182)}12.5%{transform:scaleY(0.190)}15%{transform:scaleY(0.195)}17.5%{transform:scaleY(0.196)}20%{transform:scaleY(0.192)}22.5%{transform:scaleY(0.185)}25%{transform:scaleY(0.177)}27.5%{transform:scaleY(0.172)}30%{transform:scaleY(0.171)}32.5%{transform:scaleY(0.175)}35%{transform:scaleY(0.242)}37.5%{transform:scaleY(0.457)}40%{transform:scaleY(0.737)}42.5%{transform:scaleY(0.971)}45%{transform:scaleY(1.048)}47.5%{transform:scaleY(1.009)}50%{transform:scaleY(0.966)}52.5%{transform:scaleY(0.937)}55%{transform:scaleY(0.931)}57.5%{transform:scaleY(0.952)}60%{transform:scaleY(0.991)}62.5%{transform:scaleY(1.034)}65%{transform:scaleY(1.063)}67.5%{transform:scaleY(1.069)}70%{transform:scaleY(1.048)}72.5%{transform:scaleY(1.009)}75%{transform:scaleY(0.966)}77.5%{transform:scaleY(0.937)}80%{transform:scaleY(0.931)}82.5%{transform:scaleY(0.952)}85%{transform:scaleY(0.991)}87.5%{transform:scaleY(0.982)}90%{transform:scaleY(0.758)}92.5%{transform:scaleY(0.442)}95%{transform:scaleY(0.216)}97.5%{transform:scaleY(0.185)}100%{transform:scaleY(0.177)}}
@keyframes om-b19{0%{transform:scaleY(0.218)}2.5%{transform:scaleY(0.228)}5%{transform:scaleY(0.237)}7.5%{transform:scaleY(0.243)}10%{transform:scaleY(0.244)}12.5%{transform:scaleY(0.239)}15%{transform:scaleY(0.230)}17.5%{transform:scaleY(0.220)}20%{transform:scaleY(0.214)}22.5%{transform:scaleY(0.213)}25%{transform:scaleY(0.218)}27.5%{transform:scaleY(0.228)}30%{transform:scaleY(0.237)}32.5%{transform:scaleY(0.243)}35%{transform:scaleY(0.305)}37.5%{transform:scaleY(0.494)}40%{transform:scaleY(0.713)}42.5%{transform:scaleY(0.879)}45%{transform:scaleY(0.935)}47.5%{transform:scaleY(0.932)}50%{transform:scaleY(0.955)}52.5%{transform:scaleY(0.996)}55%{transform:scaleY(1.038)}57.5%{transform:scaleY(1.065)}60%{transform:scaleY(1.068)}62.5%{transform:scaleY(1.045)}65%{transform:scaleY(1.004)}67.5%{transform:scaleY(0.962)}70%{transform:scaleY(0.935)}72.5%{transform:scaleY(0.932)}75%{transform:scaleY(0.955)}77.5%{transform:scaleY(0.996)}80%{transform:scaleY(1.038)}82.5%{transform:scaleY(1.065)}85%{transform:scaleY(1.068)}87.5%{transform:scaleY(0.996)}90%{transform:scaleY(0.732)}92.5%{transform:scaleY(0.429)}95%{transform:scaleY(0.234)}97.5%{transform:scaleY(0.213)}100%{transform:scaleY(0.218)}}
@keyframes om-up-1{0%,6%{transform:translateY(0)}14%,78%{transform:translateY(calc(-1 * var(--sep)))}88%,100%{transform:translateY(0)}}
@keyframes om-dn-1{0%,6%{transform:translateY(0)}14%,78%{transform:translateY(var(--sep))}88%,100%{transform:translateY(0)}}
@keyframes om-band-1{0%,6%{height:calc(var(--sep) * .4)}14%,78%{height:calc(var(--sep) * 2)}88%,100%{height:calc(var(--sep) * .4)}}
@keyframes om-up-2{0%,27%{transform:translateY(0)}35%,78%{transform:translateY(calc(-1 * var(--sep)))}88%,100%{transform:translateY(0)}}
@keyframes om-dn-2{0%,27%{transform:translateY(0)}35%,78%{transform:translateY(var(--sep))}88%,100%{transform:translateY(0)}}
@keyframes om-band-2{0%,27%{height:calc(var(--sep) * .4)}35%,78%{height:calc(var(--sep) * 2)}88%,100%{height:calc(var(--sep) * .4)}}
@keyframes om-up-3{0%,49%{transform:translateY(0)}57%,78%{transform:translateY(calc(-1 * var(--sep)))}88%,100%{transform:translateY(0)}}
@keyframes om-dn-3{0%,49%{transform:translateY(0)}57%,78%{transform:translateY(var(--sep))}88%,100%{transform:translateY(0)}}
@keyframes om-band-3{0%,49%{height:calc(var(--sep) * .4)}57%,78%{height:calc(var(--sep) * 2)}88%,100%{height:calc(var(--sep) * .4)}}
@keyframes om-sweep{0%{left:0;opacity:0}6%{opacity:.75}66%{left:100%;opacity:.75}74%{left:100%;opacity:0}75%,100%{left:0;opacity:0}}

/* Reduced motion freezes each figure mid-loop rather than at frame zero, so it
   still shows the state it is explaining instead of an empty starting pose. */
@media (prefers-reduced-motion: reduce) {
    .fig * {
        animation-duration: 12s !important;
        animation-delay: -8.4s !important;
        animation-play-state: paused !important;
    }
}

/* ── Mobile ─────────────────────────────────────────────────────── */

@media (max-width: 640px) {
    /* the portrait wraps above the copy here, so the top needs less air */
    #hero {
        padding: 32px 0 60px;
    }

    /* Aligning body copy under the title costs 48px of a phone's width, which the
       figures need more than the indent is worth. */
    .project-body {
        padding-left: 0;
    }

    .project-head,
    .project-row:first-child .project-head {
        padding-left: 14px;
        padding-right: 14px;
        margin: 0 -14px;
    }

    .row-grid {
        grid-template-columns: 24px 1fr auto;
        column-gap: 10px;
    }

    /* A squeezed diagram is an unreadable diagram. These keep their proportions
       and scroll inside their own box, so the page itself never moves sideways
       and ::details-content never clips them. */
    .fig,
    .mf-flow {
        overflow-x: auto;
        overscroll-behavior-x: contain;
    }

    .fig-card {
        min-width: 296px;
    }

    .mf-flow {
        grid-template-columns: auto auto minmax(190px, 1fr) auto auto;
    }

    .adhd-grid,
    .adhd-axis {
        grid-template-columns: 50px 1fr 74px;
        column-gap: 8px;
    }
}

/* Explicit placement: with some cells pinned to a column, auto-placement puts the
   remaining labels in the wrong row. */
.adhd-label-children { grid-column: 1; grid-row: 1; }
.adhd-children { grid-row: 1; }
.adhd-note-grow { grid-row: 1; }
.adhd-label-parents { grid-column: 1; grid-row: 2; }
.adhd-parents { grid-row: 2; }
.adhd-note-flat { grid-row: 2; }
