:root {
    /* Warm paper set, sampled from origami-robotics.com's own custom
       properties (--cream #f3efe8, --paper #f7f4ee, --dark #1a1815).
       --mute is 62% and not 58%: on this ground 58% measures 4.18:1, under
       the 4.5:1 body-text floor. 62% measures 4.71:1. */
    --page: #F3EFE8;
    --bg: var(--page);
    --surface: #F7F4EE;
    --ink: #1A1815;
    --ink-soft: rgba(26, 24, 21, .74);
    --mute: rgba(26, 24, 21, .62);
    --line: rgba(26, 24, 21, .14);
    --rule: rgba(26, 24, 21, .32);
    --accent: #FF5A1F;
    /* The orange is a fill, never a text colour here: #FF5A1F on paper is
       2.72:1. Ink on the orange is 5.68:1, so the fill flips its own text. */
    --on-accent: #1A1815;
    /* the ring's reset arc, the bar's reset segment and their swatches: ink at
       32% over the sheet, pre-mixed and opaque, so the track under the arc
       does not show through as a second line */
    --reset: #B0AEA9;
    /* origami-robotics.com's pair: Source Serif 4 for anything that is a
       heading, IBM Plex Mono for everything else. Inter is kept for the
       wordmark only, so the brand does not change shape. */
    --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    --font: var(--mono);
    --serif: "Source Serif 4", ui-serif, "Iowan Old Style", Palatino, Georgia, serif;
    --brand: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
    --pad: clamp(16px, 3vw, 32px);
    --hero-gap: clamp(18px, 3.5vh, 40px);
    /* the headline and the blog button under it */
    --lede-space: clamp(150px, 26vh, 250px);
    --max: 1200px;
    --radius: 20px;
    --nav: 64px;
    /* how far the dark hero dissolves into the paper at each end */
    /* the one size both statements under the hero are set at */
    --say: clamp(26px, 3.6vw, 44px);
    --hero-fade: clamp(200px, 38vh, 400px);
    /* the closing block needs less ramp than the hero: no film to blend */
    --close-fade: clamp(140px, 22vh, 240px);

    /* Engraved headings. The letterform is a gradient clipped to the glyphs,
       with a light lip below and a dark lip above, so the type reads as cut
       into the paper rather than printed on it. Lit from above, which is why
       the highlight sits at +1px and the shadow at -1px. */
    --engrave-fill-paper: linear-gradient(165deg, rgba(70, 62, 48, .85) 0%, rgba(35, 28, 15, .95) 50%, rgba(55, 47, 33, .8) 100%);
    --engrave-fill: var(--engrave-fill-paper);
    /* origami-robotics.com's own cut. The soft 2px highlight covers most of
       the face, so the letters read as pale stone with a dark upper edge
       rather than as ink. It needs a serif at 400: on a bold sans the same lip
       glowed under every stroke and read as outlined. */
    --engrave-lip-paper: 0 1px 2px rgba(255, 250, 242, .9), 0 -1px 1px rgba(40, 30, 15, .35), 0 0 4px rgba(60, 50, 35, .15);
    --engrave-lip: var(--engrave-lip-paper);

    /* Sections below the hero are sheets laid over the page, a shade lighter,
       each casting a soft shadow up onto the one before. */
    --sheet: #F7F4EE;
    --sheet-shadow: 0 -6px 30px rgba(26, 24, 21, .05);
    /* Paper grain: a tile of dark noise at low alpha, laid under the content
       as a background layer. Not origami's fixed multiply overlay, which
       would be composited over the scroll-scrubbed film on every frame. */
    /* The tile is 512 device pixels either way: 256 CSS px on a 2x screen, 512
       on a 1x one. Squeezed to 256 device pixels it reads as speckle. */
    --grain-tile: 256px;
    --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' width='512' height='512'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .1 0 0 0 0 .09 0 0 0 0 .07 .4 0 0 0 -.15'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E") 0 0 / var(--grain-tile) var(--grain-tile);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body { background: var(--grain), var(--bg); color: var(--ink); font: 15px/1.55 var(--font); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }

/* The film is baked on rgb(11,16,21) and cannot be made transparent, so the
   hero keeps the dark set and reads as one deliberate cinematic band. Paper
   behind it would put a hard black rectangle on cream. Origami gets a light
   ground for free because their hero is a live <canvas>, not a movie.
   .dark carries the same set to the closing block, so the page opens and ends
   on the dark the way the deck alternates its slides. Everything inside is
   token-driven, so the form restyles itself with no extra rules. */
.hero, .dark {
    --bg: #020506;
    --surface: #0C1116;
    --ink: #EAE8E3;
    --ink-soft: rgba(234, 232, 227, .74);
    --mute: rgba(234, 232, 227, .58);
    --line: rgba(234, 232, 227, .14);
    --rule: rgba(234, 232, 227, .34);
    --on-accent: #EAE8E3;
    position: relative;
    background: var(--bg);
    color: var(--ink);
}
/* Starts 1px inside the hero: the hero height is a fractional svh value, so
   abutting exactly leaves an anti-aliased hairline at the seam. Stops are
   interpolated in linear light on a smoothstep, because a plain two-stop
   sRGB ramp from near-black to paper goes muddy through the middle. */
.hero::after { content: ""; position: absolute; left: 0; right: 0; top: calc(100% - 1px); height: calc(var(--hero-fade) + 1px); background: var(--grain), linear-gradient(to bottom, var(--bg) 0%, #070A0B 10%, #121415 20%, #212323 30%, #353636 40%, #4C4D4C 50%, #676765 60%, #858581 70%, #A7A5A1 80%, #CBC9C3 90%, var(--page) 100%); pointer-events: none; }
a { color: inherit; text-decoration: none; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
[hidden] { display: none !important; }
h1, h2, h3 { font-family: var(--serif); font-weight: 400; letter-spacing: -.01em; text-wrap: balance; }
section[id], h1[id], h2[id] { scroll-margin-top: calc(var(--nav) + 16px); }
.dot { color: var(--accent); }

/* Falls back to plain ink where background-clip:text is unsupported, because
   transparent text with no clip is invisible text. */
.engraved { color: var(--ink); }
@supports (background-clip: text) or (-webkit-background-clip: text) {
    .engraved {
        color: transparent;
        background-image: var(--engrave-fill);
        -webkit-background-clip: text;
                background-clip: text;
        text-shadow: var(--engrave-lip);
    }
}

/* Engraved on black with the same face as on paper. The heading is set twice.
   .cut__face is the paper engraving exactly as the section titles have it,
   on a patch of the page's own paper. .cut__mask is the same text in white on
   the dark ground, multiplied over it: outside the letters it leaves the dark
   ground, inside them it leaves the paper cut untouched. The mask is stroked
   a hair wider than the letters, so a sliver of paper rings each one and the
   dark cut edge shows against it, as it does on the page. */
.cut { position: relative; isolation: isolate; background: var(--grain), var(--page); }
.cut__face { display: block; --engrave-fill: var(--engrave-fill-paper); --engrave-lip: var(--engrave-lip-paper); }
.cut__mask { position: absolute; inset: 0; display: block; color: #fff; -webkit-text-stroke: .038em #fff; background: var(--bg); mix-blend-mode: multiply; pointer-events: none; user-select: none; }

/* The cut is what makes this read as engraved, and it is also what makes the
   letter faces dark: the lip covers the glyph, so the face measures 1.91:1
   against the ground and the type is legible mainly by its lit edge. Anyone
   who has asked their OS for more contrast should get the fill instead. */
@media (prefers-contrast: more) {
    .engraved { text-shadow: none; }
    /* without the cut, a dark heading is plain light type on the dark ground */
    .cut { background: none; }
    .cut__mask { display: none; }
    .cut .cut__face { color: var(--ink); background: none; }
}

.skip { position: absolute; left: 16px; top: -60px; z-index: 20; padding: 10px 14px; background: var(--ink); color: var(--bg); border-radius: 6px; }
.skip:focus { top: 12px; }

/* nav: aligned to the content column */
.topbar { position: sticky; top: 0; z-index: 10; height: var(--nav); display: flex; align-items: center; justify-content: space-between; padding-inline: max(var(--pad), calc((100% - var(--max)) / 2 + var(--pad))); background: var(--grain), var(--bg); box-shadow: inset 0 -1px 0 var(--line); }
/* Only the home page opens on the dark band, and it is the only page with a
   .hero, so match on that rather than threading a template flag through the
   shared partial. The nav then sits inside the dark instead of ruling a line
   across the top of it. Without :has() the nav simply stays paper. */
body:has(.hero) .topbar { transition: background .25s ease, color .25s ease, box-shadow .25s ease; --bg: #020506; --ink: #EAE8E3; --ink-soft: rgba(234, 232, 227, .74); --on-accent: #EAE8E3; --rule: rgba(234, 232, 227, .34); background: var(--bg); color: var(--ink); box-shadow: none; }
/* Restates background and color as well as the tokens. Not strictly needed,
   the token change alone repaints, but it keeps the flip readable next to
   the rule it overrides. */
.past-hero body:has(.hero) .topbar { --bg: var(--page); --ink: #1A1815; --ink-soft: rgba(26, 24, 21, .74); --on-accent: #1A1815; --rule: rgba(26, 24, 21, .32); background: var(--grain), var(--page); color: #1A1815; box-shadow: inset 0 -1px 0 rgba(26, 24, 21, .14); }
.brand { display: inline-flex; align-items: center; gap: 10px; font-family: var(--brand); font-size: 19px; font-weight: 600; letter-spacing: -.04em; line-height: 1; }
.brand svg { width: 9px; height: 29px; display: block; }
.brand--small { font-size: 16px; }
.topbar__end { display: flex; align-items: center; gap: clamp(14px, 2vw, 26px); }
.navlink { font: 400 11px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); transition: color .2s ease; }
.navlink:hover, .navlink[aria-current="page"] { color: var(--ink); }

.cta--quiet { min-height: 38px; padding: 0 18px; font-size: 10px; }
.cta { display: inline-flex; align-items: center; justify-content: center; min-height: 46px; padding: 0 34px; border: 1px solid var(--rule); border-radius: 0; background: none; color: var(--ink); font: 500 11px/1 var(--mono); letter-spacing: .18em; text-transform: uppercase; cursor: pointer; transition: border-color .2s, background .2s; }
.cta:hover { border-color: var(--ink); background: var(--surface); }
.cta:active { transform: scale(.99); }

/* Hero. Landscape pins the film full-bleed for the length of .hero and the
   scroll position drives the frame. Portrait does not pin at all: a 16:9 film
   is only ~265px tall on a phone, so pinning it inside a full viewport left it
   floating in dead space. There it sits in normal flow with the headline right
   under it, which fills the screen.
   Both get a masked top and bottom edge so the film dissolves into the page
   rather than cutting against it, whatever frame is on screen. */
.hero { position: relative; }
.hero__sticky { position: relative; display: grid; place-items: center; align-content: center; gap: var(--hero-gap); }
.hero__film { display: block; width: 100%; height: auto; margin-inline: auto; background: var(--bg);
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 26%, #000 76%, transparent 100%);
            mask-image: linear-gradient(to bottom, transparent 0, #000 26%, #000 76%, transparent 100%); }
.scroll-cue { display: none; }

.has-scroll-film .hero { height: 380svh; }
.has-scroll-film .hero__sticky { position: sticky; top: var(--nav); height: calc(100svh - var(--nav)); overflow: clip; }
.has-scroll-film .hero__film { width: min(100%, calc((100svh - var(--nav) - var(--lede-space)) * 16 / 9)); }
/* the headline now sits in the frame, so the cue moves out of its way */
/* The cue used to own the bottom-right corner. The a16z credit sits there
   now, on the button's row, and the two printed straight over each other,
   so the cue moves to the centre of the same edge. */
.has-scroll-film .scroll-cue { display: block; position: absolute; left: 50%; transform: translateX(-50%); bottom: 16px; margin: 0; font-size: 12px; color: var(--mute); opacity: var(--cue-opacity, 1); pointer-events: none; }
.scroll-cue span { display: inline-block; margin-left: 9px; }

.lede { width: 100%; padding-inline: max(var(--pad), calc((100% - var(--max)) / 2 + var(--pad))); }
/* Set like the section titles below (.sechead__t): one face, one italic
   word, the same size and the same stone cut. */
.lede h1 { max-width: 22ch; font-size: clamp(36px, 3.7vw, 54px); line-height: 1.06; letter-spacing: -.01em; }

/* Backed by, in the hero. It sits under the button because that is where a
   visitor's eye already is, and it is deliberately quiet: a small label and
   the mark, not a banner. The tile is dark crimson on a dark film, so it
   keeps its colour here rather than taking the greyed-back treatment the old
   row used, but it is small and wears no ring: at this size a ring and a
   shadow turn a quiet credit into a badge. 24px is the floor — the wordmark
   is set edge to edge inside the tile, so below that it stops being
   readable and is just a red square.
   It sits at the far end of the button's row, against the same gutter the
   nav and the scroll cue use, so the row reads button-left, credit-right. */
.lede__backed { display: flex; align-items: center; gap: 8px; margin: 0; }
.lede__backed-label { font: 500 9px/1 var(--mono); letter-spacing: .2em; text-transform: uppercase; color: var(--mute); opacity: .8; }
.lede__backed-mark { display: block; width: 24px; height: 24px; border-radius: 6px; opacity: .92; }
@media (max-width: 720px) {
    .lede__backed { gap: 8px; margin-left: 0; }
    .lede__backed-mark { width: 22px; height: 22px; border-radius: 5px; }
}

/* Hero support: the one line that says what the machine does, and the ask.
   These also fill the dead space under the headline on a phone, which is what
   made that screen read as half empty. */
/* One sentence, large, with air around it. The page needs a moment that is
   not a three-column list. */
.statement { max-width: var(--max); margin-inline: auto; padding: clamp(88px, 13vh, 144px) var(--pad) 0; }
.statement h2 { max-width: 19ch; font-family: var(--serif); font-size: var(--say); font-weight: 400; line-height: 1.12; letter-spacing: -.01em; }
.statement__lead { margin-top: 26px; max-width: 50ch; font: 400 15px/1.75 var(--font); color: var(--ink-soft); }

/* trailing note under a row band */

/* Why us: three claims as ruled rows, the way origami lists its roles. A
   number, the claim cut into the page, and the one sentence behind it. */
.features { margin-top: clamp(36px, 6vh, 64px); list-style: none; border-top: 1px solid var(--line); }
.feature { display: grid; grid-template-columns: 56px minmax(0, 1.05fr) minmax(0, 1fr); align-items: baseline; gap: clamp(18px, 3vw, 48px); padding: clamp(34px, 5.5vh, 56px) 8px; border-bottom: 1px solid var(--line); }
.feature__n { font: 400 11px/1 var(--mono); letter-spacing: .22em; color: var(--mute); }
.feature__t { max-width: 17ch; font-size: clamp(27px, 2.7vw, 38px); line-height: 1.12; }
.feature__d { max-width: 44ch; font: 400 13px/1.85 var(--mono); color: var(--ink-soft); }
.feature__cta { margin-top: 26px; }

.band__note { margin-top: 32px; font: 400 13px/1.7 var(--mono); color: var(--mute); }

/* The closing block runs full bleed so the dark reaches both edges; the column
   inside keeps the measure. The gradient is .hero::after mirrored, so the page
   dissolves into the dark rather than cutting against it. */
/* above the sheets, or the careers sheet would paint over the dissolve */
.contact.dark { max-width: none; padding-inline: 0; position: relative; z-index: 2; }

/* cal.com's booker in a panel of our own: a hairline, the page radius, and a
   small label in the corner. The booker draws its own card inside this, so the
   panel is only a frame around it and its branding. */
.booker { max-width: var(--max); margin-inline: auto; padding-inline: var(--pad); text-align: left; }
.booker__panel { border: 1px solid var(--line); border-radius: var(--radius); padding: clamp(12px, 1.6vh, 18px); }
.booker > .sechead { margin-bottom: clamp(28px, 4.5vh, 48px); }
/* No fixed height, and a width close to the card's own. cal.com's card has a
   max width and its iframe document is WHITE behind it, so any box wider or
   taller than the card shows white around it. The embed resizes the iframe to
   its content, so left alone it fits exactly. min-height only stops the page
   jumping before it mounts. */
.booker__frame { width: 100%; max-width: 1000px; margin-inline: auto; min-height: 560px; }
/* The white band under cal.com's branding. base.html declares color-scheme:
   dark; cal.com's document declares none, so it is light. When a frame's used
   colour scheme differs from its document's, Chrome paints the frame opaque with
   that document's canvas, which is white. Their embed injects
   `.cal-embed { color-scheme: unset !important }`, which makes the frame inherit
   our dark scheme and guarantees the mismatch, so this must be !important to
   win. Scoped to this iframe on purpose: dropping the meta also fixes it, but
   turns native form controls light across the whole site. */
.booker__frame iframe { color-scheme: light !important; background: transparent !important; border-radius: 12px; }
/* The note is the second path, for people who will not book a slot. Closed,
   it is one quiet line under the calendar; open, it is the form. */
.note { margin-top: clamp(30px, 4.5vh, 48px); }
.note__open { display: inline-flex; align-items: center; gap: 10px; list-style: none; cursor: pointer; padding-bottom: 3px; border-bottom: 1px solid var(--line); font: 400 12px/1.6 var(--mono); color: var(--ink-soft); transition: color .2s ease, border-color .2s ease; }
.note__open::-webkit-details-marker { display: none; }
.note__open::after { content: "+"; font-size: 14px; line-height: 1; color: var(--mute); }
.note[open] .note__open::after { content: "\2212"; }
.note__open:hover { color: var(--ink); border-color: var(--rule); }
.note__open:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.note .form { margin-top: 30px; }
.contact__inner { max-width: 560px; margin-inline: auto; padding-inline: var(--pad); }
.contact.dark::before { content: ""; position: absolute; left: 0; right: 0; bottom: calc(100% - 1px); height: calc(var(--close-fade) + 1px); background: var(--grain), linear-gradient(to top, var(--bg) 0%, #070A0B 10%, #121415 20%, #212323 30%, #353636 40%, #4C4D4C 50%, #676765 60%, #858581 70%, #A7A5A1 80%, #CBC9C3 90%, var(--sheet) 100%); pointer-events: none; }
/* .footer is a 1200px centred column, so a dark background on it left the
   cream page showing at both edges under the closing block. Full bleed, with
   the content still aligned to the column the way .topbar does it. */
.footer.dark { margin-top: 0; max-width: none; padding-inline: max(var(--pad), calc((100% - var(--max)) / 2 + var(--pad))); }

/* what we do */
.about { max-width: var(--max); margin-inline: auto; padding: calc(28px + var(--hero-fade)) var(--pad) 0; }
.kicker { display: flex; align-items: center; gap: 12px; font: 500 11px/1.4 var(--mono); letter-spacing: .22em; text-transform: uppercase; color: var(--mute); }
.kicker__dash { width: 20px; height: 2px; background: var(--accent); }
.rows { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 36px; margin-top: 36px; }
.rows__row { padding-top: 22px; border-top: 1px solid var(--line); }
.rows dt { display: flex; justify-content: space-between; align-items: baseline; font-size: clamp(21px, 2.4vw, 29px); letter-spacing: -.035em; }
.step-number { order: 1; font: 400 13px/1.4 var(--mono); color: var(--mute); letter-spacing: 0; }
.rows dd { margin-top: 20px; max-width: 29ch; font-size: 15px; line-height: 1.55; color: var(--ink-soft); }

/* A content band below the hero. Same container and rhythm as .careers, which
   was the only generic band on the page when careers was the only thing under
   the fold. Declared separately rather than by adding .careers to five more
   sections, so the markup says what each section is. Identical values: this
   introduces no new spacing, type or colour. */
.band { max-width: var(--max); margin-inline: auto; padding: clamp(80px, 12vh, 130px) var(--pad) 0; }
/* whatever comes first under the hero has to clear the dissolve */
.band--first { padding-top: calc(28px + var(--hero-fade)); }

.band__lead { margin-top: 18px; max-width: 56ch; font: 400 13px/1.8 var(--mono); color: var(--ink-soft); }

.careers { max-width: var(--max); margin-inline: auto; padding: clamp(80px, 12vh, 130px) var(--pad) 0; }
.careers__lead { margin-top: 18px; max-width: 56ch; font: 400 13px/1.8 var(--mono); color: var(--ink-soft); }
.rolecard { margin-top: clamp(36px, 6vh, 64px); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) auto; align-items: center; gap: clamp(18px, 3vw, 48px); padding: 28px 8px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); transition: background .35s ease, padding .35s ease; }
.rolecard:hover { background: rgba(255, 252, 245, .55); padding-inline: 20px; }
.rolecard__id { display: block; min-width: 0; }
.rolecard__title { display: block; font-family: var(--serif); font-size: clamp(22px, 2.6vw, 30px); font-weight: 400; line-height: 1.1; }
.rolecard__meta { display: block; margin-top: 10px; font: 400 11px/1.4 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--mute); }
.rolecard__pitch { font: 400 13px/1.7 var(--mono); color: var(--ink-soft); }
.rolecard__go { font: 500 10px/1 var(--mono); letter-spacing: .18em; text-transform: uppercase; color: var(--mute); white-space: nowrap; transition: color .3s ease, transform .35s ease; }
.rolecard:hover .rolecard__go { color: var(--ink); transform: translateX(5px); }
.careers__alt { margin-top: 26px; font: 400 12px/1.6 var(--mono); color: var(--mute); }
/* the last cream band has to clear the dissolve into the closing dark block.
   Declared here, after the .careers padding shorthand above, or it is lost. */
.careers { padding-bottom: var(--close-fade); }

/* A section's title, cut into the page, with its one line of context set
   against the far edge. */
.sechead { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 14px clamp(24px, 5vw, 64px); }
.sechead__t { font-size: clamp(36px, 3.7vw, 54px); line-height: 1.06; }
.sechead__sub { max-width: 44ch; text-align: right; font: 400 12.5px/1.8 var(--mono); color: var(--mute); }

/* The split between sections, from origami-robotics.com: each section is a
   sheet laid over the page, a shade lighter, casting a soft shadow up onto
   the one before it. Full bleed, with the content kept on the column. */
.sheet { position: relative; z-index: 1; max-width: none; padding-block: clamp(96px, 14vh, 150px); padding-inline: max(var(--pad), calc((100% - var(--max)) / 2 + var(--pad))); background: var(--grain), var(--sheet); box-shadow: var(--sheet-shadow); }
/* the last sheet has to clear the dissolve into the closing dark block */
.careers.sheet { padding-bottom: var(--close-fade); }

/* Scroll reveal, the way origami's sections arrive. Keyed on html.reveal,
   which only static/js/reveal.js sets, so without JS nothing is hidden. A
   heading sharpens out of a blur as it rises, as if it were being cut. */
.reveal [data-reveal] { opacity: 0; transform: translateY(22px); transition: opacity .9s cubic-bezier(.22, .61, .36, 1), transform .9s cubic-bezier(.22, .61, .36, 1), filter .9s ease; }
.reveal .engraved[data-reveal] { filter: blur(3px); }
.reveal [data-reveal].is-in { opacity: 1; transform: none; filter: none; }
.reveal .feature:nth-child(2) { transition-delay: .08s; }
.reveal .feature:nth-child(3) { transition-delay: .16s; }

/* careers page */
.page { max-width: var(--max); margin-inline: auto; padding-inline: var(--pad); }
.masthead { padding: clamp(56px, 10vh, 108px) 0 clamp(48px, 8vh, 86px); }
.eyebrow { font: 500 10px/1.4 var(--mono); letter-spacing: .22em; text-transform: uppercase; color: var(--mute); }
.masthead h1 { margin-top: 20px; max-width: 18ch; font-family: var(--serif); font-size: clamp(38px, 6vw, 68px); font-weight: 400; line-height: 1.04; letter-spacing: -.015em; }
.masthead__lead { margin-top: 26px; max-width: 64ch; font: 400 13px/1.8 var(--mono); color: var(--ink-soft); }
.group__head { display: flex; align-items: baseline; justify-content: space-between; gap: 20px; padding-bottom: 18px; }
.group__head h2 { font-family: var(--serif); font-size: clamp(24px, 3vw, 34px); font-weight: 400; letter-spacing: -.01em; }
.group__meta { font: 400 11px/1.4 var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--mute); }
.apply { padding: clamp(80px, 13vh, 150px) 0 clamp(64px, 10vh, 110px); }
.apply h2 { margin-top: 18px; font-family: var(--serif); font-size: clamp(30px, 4.4vw, 48px); font-weight: 400; line-height: 1.06; letter-spacing: -.01em; }
.apply__lead { margin-top: 16px; max-width: 52ch; font: 400 13px/1.8 var(--mono); color: var(--ink-soft); }
.form--apply { max-width: 620px; margin-top: 36px; }
.form--apply .cta { justify-self: start; margin-top: 12px; }
.field select { width: 100%; height: 48px; padding: 0 14px; border: 1px solid var(--rule); border-radius: 0; background: var(--surface); font: 16px/1.5 var(--font); color: var(--ink); letter-spacing: 0; text-transform: none; }
.apply__alt { margin-top: 24px; font: 400 12px/1.6 var(--mono); color: var(--mute); }

/* One disclosure per role. <details> gives the open/close behaviour, the
   keyboard handling and the accessible name for free, so this needs no JS. */
.role { border-top: 1px solid var(--line); }
.careers .role:last-of-type { border-bottom: 1px solid var(--line); }
.role__head { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) 28px; align-items: start; gap: clamp(18px, 3vw, 48px); padding: 30px 12px; margin-inline: -12px; cursor: pointer; list-style: none; transition: background .18s ease; }
.role__head::-webkit-details-marker { display: none; }
.role__head:hover, .role[open] .role__head { background: var(--surface); }
.role__head:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.role__id { min-width: 0; }
.role__cat { font: 500 10px/1.4 var(--mono); letter-spacing: .22em; text-transform: uppercase; color: var(--mute); }
.role__title { margin-top: 12px; font-family: var(--serif); font-size: clamp(25px, 3vw, 36px); font-weight: 400; line-height: 1.1; letter-spacing: -.01em; }
.role__tags { margin-top: 16px; display: flex; flex-wrap: wrap; gap: 8px; list-style: none; }
.role__tags li { padding: 5px 12px; border: 1px solid var(--rule); border-radius: 999px; font: 400 10px/1.4 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--mute); }
.role__pitch { font: 400 13px/1.7 var(--mono); color: var(--ink-soft); }
.role__toggle { justify-self: end; align-self: center; width: 22px; height: 22px; display: grid; place-items: center; font: 400 19px/1 var(--mono); color: var(--mute); }
.role__toggle::before { content: "+"; }
.role[open] .role__toggle::before { content: "\00d7"; }
.role__panel { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 340px); gap: clamp(28px, 5vw, 72px); padding: 8px 0 52px; }
.microlabel { font: 500 10px/1.4 var(--mono); letter-spacing: .22em; text-transform: uppercase; color: var(--ink); }
.role__main .microlabel { margin-top: 34px; }
.role__main .microlabel:first-child { margin-top: 0; }
.role__prose { margin-top: 16px; max-width: 74ch; font: 400 13px/1.8 var(--mono); color: var(--ink-soft); }
.role__list { margin-top: 16px; display: grid; gap: 11px; list-style: none; }
.role__list li { position: relative; padding-left: 20px; max-width: 80ch; font: 400 13px/1.7 var(--mono); color: var(--ink-soft); }
.role__list li::before { content: "\2022"; position: absolute; left: 2px; color: var(--mute); }
.role__aside { align-self: start; padding: 26px; border: 1px solid var(--rule); }
.role__include { margin-top: 16px; display: grid; gap: 12px; padding-left: 18px; }
.role__include li { font: 400 13px/1.7 var(--mono); color: var(--ink-soft); }
.role__aside .cta { width: 100%; margin-top: 14px; }

/* where it started: its own page, one line and the original clip */
.origin-page { min-height: calc(100svh - var(--nav) - 92px); display: grid; align-items: center; }
/* The copy sits at the top of the clip, not centred on it: the clip is a
   portrait, and centring left 230px of empty paper above the kicker. */
.origin { max-width: var(--max); margin-inline: auto; width: 100%; padding: clamp(48px, 8vh, 104px) var(--pad); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 380px); gap: clamp(28px, 5vw, 80px); align-items: start; }
.origin__copy { padding-top: clamp(12px, 3vh, 40px); }
.origin__copy p { margin-top: 22px; max-width: 26ch; font-family: var(--serif); font-size: clamp(24px, 2.9vw, 36px); line-height: 1.18; letter-spacing: -.01em; font-weight: 400; }
.origin__copy p.origin__note { max-width: 52ch; margin-top: 24px; font-family: var(--mono); font-size: 13px; line-height: 1.85; letter-spacing: 0; font-weight: 400; color: var(--ink-soft); }
.origin__film { position: relative; margin: 0; border-radius: var(--radius); overflow: hidden; background: var(--surface); }
.origin__video { display: block; width: 100%; height: auto; }
/* the same block on the home page, where it is the first thing under the hero
   and has to clear the dissolve */
.origin--home { padding-top: calc(28px + var(--hero-fade)); }
/* .engraved, not p: .origin__note is also a p in here and ties on specificity,
   so a bare p selector declared later swallows the small line too. */
.origin--home .origin__copy p.engraved { font-size: var(--say); line-height: 1.12; }

/* the whole frame is the play control; the sound chip sits above it */
.playpause { position: absolute; inset: 0; z-index: 1; width: 100%; padding: 0; border: 0; background: none; cursor: pointer; -webkit-appearance: none; appearance: none; }
.playpause:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; }
.flash { position: absolute; inset: 0; z-index: 2; margin: auto; width: 58px; height: 58px; display: grid; place-items: center; border-radius: 999px; background: rgba(9, 15, 21, .58); color: var(--ink); opacity: 0; pointer-events: none; -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); }
.flash svg { width: 22px; height: 22px; display: block; }
.flash.is-on { animation: flash .5s cubic-bezier(.22, .61, .36, 1) both; }
@keyframes flash {
      0% { opacity: 0; transform: scale(.78); }
     26% { opacity: 1; transform: scale(1); }
    100% { opacity: 0; transform: scale(1.16); }
}
.sound { position: absolute; z-index: 3; right: 12px; bottom: 12px; display: grid; place-items: center; width: 34px; height: 34px; padding: 0; border: 1px solid rgba(234, 232, 227, .18); border-radius: 999px; background: rgba(9, 15, 21, .62); color: var(--ink); cursor: pointer; -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); transition: background .2s ease, border-color .2s ease, transform .2s ease; }
.sound:hover { background: rgba(9, 15, 21, .85); border-color: rgba(234, 232, 227, .38); }
.sound:active { transform: scale(.94); }
.sound svg { width: 16px; height: 16px; display: block; }

/* contact */
.contact { max-width: 560px; margin-inline: auto; padding: clamp(110px, 17vh, 180px) var(--pad) clamp(96px, 14vh, 150px); text-align: center; }
.contact h2 { font-family: var(--serif); font-size: clamp(38px, 5.4vw, 58px); font-weight: 400; line-height: 1.06; letter-spacing: -.01em; }
.contact__lead { margin-top: 18px; font: 400 12px/1.7 var(--mono); color: var(--mute); }
/* a visitor should know what they are agreeing to before they hand over a
   part number, not after somebody replies */
.contact__next { margin-top: 26px; font: 400 12px/1.7 var(--mono); color: var(--ink-soft); }
.contact__alt { margin-top: 28px; font: 400 12px/1.6 var(--mono); color: var(--mute); }
.link { border-bottom: 1px solid var(--line); transition: color .2s, border-color .2s; }
.link:hover { color: var(--accent); border-color: var(--accent); }

.talk { margin-top: 40px; }
.talk > summary { display: inline-flex; list-style: none; }
.talk > summary::-webkit-details-marker { display: none; }
.form { display: grid; gap: 16px; margin-top: 40px; text-align: left; }
.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.field { display: grid; gap: 8px; font: 500 10.5px/1.4 var(--mono); letter-spacing: .16em; text-transform: uppercase; color: var(--mute); }
.field input, .field textarea { width: 100%; padding: 0 14px; border: 1px solid var(--rule); border-radius: 0; background: var(--surface); font: 16px/1.5 var(--font); color: var(--ink); letter-spacing: 0; text-transform: none; transition: border-color .15s; }
.field input { height: 48px; }
.field textarea { padding: 12px 14px; resize: vertical; min-height: 96px; }
.field input:focus, .field textarea:focus { outline: none; border-color: var(--ink); }
.field ::placeholder { color: var(--mute); }
.form__trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form .cta { justify-self: center; margin-top: 12px; }
.form__flash { padding: 12px 14px; border-radius: 12px; font-size: 14px; background: var(--surface); border: 1px solid var(--line); }
.form__flash--error { border-color: var(--accent); }

/* footer */
.footer { max-width: var(--max); margin-inline: auto; margin-top: clamp(56px, 9vh, 92px); padding: 26px var(--pad) 40px; display: flex; align-items: center; justify-content: space-between; gap: 20px; border-top: 1px solid var(--line); }
.footer__line { font: 400 12px/1.6 var(--mono); color: var(--mute); }
.footer__fine { font: 400 11px/1.6 var(--mono); color: var(--mute); }

/* Portrait keeps the pin. Letting the film sit in normal flow here was a bug:
   a 16:9 film is only ~265px tall on a phone, so it cleared the top of the
   screen after ~320px of scroll, which is 27% of the way through the scrub.
   The film's first second is a near-still hold, so all anyone ever saw was a
   frozen frame before it scrolled away, and the other six seconds ran off
   screen. Pinned, the film stays put for the whole eight seconds. */
@media (max-aspect-ratio: 13/10) {
    .has-scroll-film .hero { height: 300svh; }
    /* A 16:9 film is a 221px strip on a phone. Cropping to 5:4 makes it 314px.
       Centred: the robot is centred in frame and the crop keeps it there. This
       was 63% for the previous film, which carried a baked "ultra inspection"
       title out to 89% of frame width and had to be framed around it. That
       title is gone, and 63% pushed the robot visibly left of centre on the
       opening and closing shots, which are the two most-seen frames. */
    .has-scroll-film .hero__film { width: 100%; margin-left: 0; aspect-ratio: 5 / 4; object-fit: cover; object-position: 50% center; }
    /* Centred, not top-aligned. A 16:9 film is only 312px tall on a 390x844
       phone, so film plus headline is about 500px of an 788px box. Pinned to
       the top, the remaining 343px all pooled into one black void under the
       headline and the screen read as half-empty. Centred it splits into
       154px above and 188px below and the composition reads as framed. */
    .has-scroll-film .hero__sticky { align-content: center; }
}

@media (max-width: 900px) {
    .origin { grid-template-columns: 1fr; gap: 28px; justify-items: start; }
    .origin__film { width: 100%; max-width: 340px; }
    .origin-page { min-height: 0; }
}

@media (max-width: 720px) {
    :root { --radius: 12px; --nav: 56px; --pad: 22px; }
    /* the headline sits under the film on a phone rather than over it, so the
       film gets the space back and runs ~20% taller. */
    :root { --lede-space: 0px; }
    .brand { font-size: 17px; }
    /* mark + 3 items needs 361px at the previous spacing, which overflows a
       360px Android by a pixel. This buys it back. */
    .topbar__end { gap: 12px; }
    .navlink { font-size: 10px; letter-spacing: .06em; }
    .lede h1 { font-size: clamp(32px, 8.6vw, 42px); max-width: 18ch; line-height: 1.1; letter-spacing: -.01em; }
    .rows { grid-template-columns: 1fr; gap: 26px; margin-top: 28px; }
    .rows__row { display: grid; grid-template-columns: 1fr 1.3fr; gap: 24px; padding-top: 22px; }
    /* the row is a two-column grid on a phone; the picture spans both */
    .rows dt { display: block; font-size: 21px; }
    .step-number { display: block; margin-bottom: 14px; }
    .rows dd { margin-top: 26px; font-size: 15px; }
    /* 38vh of dissolve is 321px on a phone, and the section under it only
       cleared 40px, so the first heading sat inside the dark end of the ramp
       and was invisible. Shorter ramp here, and real clearance for it. */
:root { --hero-fade: clamp(120px, 20vh, 200px); }
    .about, .band--first, .origin--home { padding-top: calc(24px + var(--hero-fade)); }
    /* stacked on a phone, so it needs more room before it mounts */
    .booker__frame { min-height: 1080px; }
    .contact { padding-top: 80px; padding-bottom: 80px; }
    .contact h2 { font-size: clamp(32px, 9vw, 40px); }
    .form__row { grid-template-columns: 1fr; }
    .field input { height: 48px; }
    .form .cta { width: 100%; }
    .rolecard { grid-template-columns: minmax(0, 1fr); gap: 16px; }
    .rolecard:hover { padding-inline: 14px; }
    .feature { grid-template-columns: minmax(0, 1fr); gap: 14px; padding: 30px 0; }
    .sechead__sub { text-align: left; }
    .group__head { flex-direction: column; align-items: flex-start; gap: 8px; }
    .footer { flex-direction: column; align-items: flex-start; gap: 12px; }
    .role__head { grid-template-columns: minmax(0, 1fr) 22px; gap: 16px; padding: 24px 10px; }
    .role__pitch { grid-column: 1 / -1; }
    .role__toggle { grid-row: 1; grid-column: 2; }
    .role__panel { grid-template-columns: 1fr; gap: 32px; padding-bottom: 40px; }
}
@media (max-resolution: 1.5dppx) {
    :root { --grain-tile: 512px; }
}
@media (max-height: 540px) and (min-width: 721px) {
    .lede h1 { font-size: 28px; }
    .lede h1 br { display: none; }
}
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    .hero__film { -webkit-mask-image: none; mask-image: none; }
    .link, .field input, .field textarea, .sound, .navlink { transition: none; }
    .reveal [data-reveal] { opacity: 1; transform: none; filter: none; transition: none; }
    .flash.is-on { animation-duration: .5s; }
}
@media (forced-colors: active) {
    /* backgrounds and blending are overridden here, so the mask would show as a second copy */
    .cut { background: none; }
    .cut__mask { display: none; }
}

/* ------------------------------------------------------------------------
   Blog. origami-robotics.com sets its posts in the same pair this site uses,
   Plex Mono for the text and Source Serif 4 for the titles, so the article
   keeps the site's type and only adds a reading measure: one 600px column,
   with figures allowed out to 940px. Every figure below is drawn from
   numbers or sentences that are already in the text. */

/* the index: the careers masthead, then one ruled row per post */
.posts { margin-bottom: clamp(64px, 10vh, 110px); }
.postrow { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr) auto; align-items: baseline; gap: 14px clamp(18px, 3vw, 48px); padding: 30px 0; border-bottom: 1px solid var(--line); transition: background .35s ease; }
.postrow:hover { background: rgba(255, 252, 245, .55); }
.postrow__meta { grid-column: 1 / -1; font: 400 11px/1.4 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--mute); }
.postrow__title { font-family: var(--serif); font-size: clamp(24px, 2.8vw, 34px); line-height: 1.1; letter-spacing: -.01em; }
.postrow__dek { font: 400 13px/1.75 var(--mono); color: var(--ink-soft); }
.postrow__go { font: 500 10px/1 var(--mono); letter-spacing: .18em; text-transform: uppercase; color: var(--mute); white-space: nowrap; transition: color .3s ease, transform .35s ease; }
.postrow:hover .postrow__go { color: var(--ink); transform: translateX(5px); }

/* the label has a space in it, and the nav must never wrap */
.navlink--origin { white-space: nowrap; }

/* The site's pill buttons: easemize's glass button from 21st.dev, ported
   from its stylesheet as it ships. A clear pill with a blurred backdrop, a
   rim lit at two opposite points that swings round on hover, a sheen that
   slides across the face, and a soft shadow below that lifts on hover and
   tilts the pill back when pressed. The component's --foreground and
   --background are the site's ink and ground, so the same button reads on
   the dark hero and on paper, and flips with the nav as it leaves the hero.
   The label is the site's mono CTA type. em sizes are the component's, off
   a 16px wrap, so its shadows and rim keep their proportions. */
@property --angle-1 { syntax: "<angle>"; inherits: false; initial-value: -75deg; }
@property --angle-2 { syntax: "<angle>"; inherits: false; initial-value: -45deg; }
.lede__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin-top: clamp(18px, 3vh, 28px); }
/* The link is the outer element and never moves: the hover scale and the
   press tilt sit on layers inside it. While the link itself moved, a press
   that ended a pixel outside its box was dropped and the button read as
   hard to click. Nothing about the painting changes. */
.glass-button-wrap { --fg: var(--ink); --bgc: var(--bg); --anim-time: 400ms; --anim-ease: cubic-bezier(.25, 1, .5, 1); --border-width: clamp(1px, .0625em, 4px); position: relative; z-index: 2; display: inline-block; font-size: 16px; border-radius: 9999px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.glass-button-wrap:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.glass-button-tilt { display: block; position: relative; transform-style: preserve-3d; transition: transform var(--anim-time) var(--anim-ease); }
.glass-button-wrap:active .glass-button-tilt { transform: rotateX(25deg); }
.glass-button-shadow { --shadow-cutoff-fix: 2em; position: absolute; z-index: 0; width: calc(100% + var(--shadow-cutoff-fix)); height: calc(100% + var(--shadow-cutoff-fix)); top: calc(0% - var(--shadow-cutoff-fix) / 2); left: calc(0% - var(--shadow-cutoff-fix) / 2); filter: blur(clamp(2px, .125em, 12px)); transition: filter var(--anim-time) var(--anim-ease); pointer-events: none; }
.glass-button-shadow::after { content: ""; position: absolute; inset: 0; border-radius: 9999px; background: linear-gradient(180deg, color-mix(in oklch, var(--fg) 20%, transparent), color-mix(in oklch, var(--fg) 10%, transparent)); width: calc(100% - var(--shadow-cutoff-fix) - .25em); height: calc(100% - var(--shadow-cutoff-fix) - .25em); top: calc(var(--shadow-cutoff-fix) - .5em); left: calc(var(--shadow-cutoff-fix) - .875em); padding: .125em; box-sizing: border-box; -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude; transition: all var(--anim-time) var(--anim-ease); opacity: 1; }
.glass-button { all: unset; position: relative; z-index: 1; isolation: isolate; display: block; border-radius: 9999px; cursor: pointer; -webkit-tap-highlight-color: transparent; -webkit-backdrop-filter: blur(clamp(1px, .125em, 4px)); backdrop-filter: blur(clamp(1px, .125em, 4px)); transition: all var(--anim-time) var(--anim-ease); background: linear-gradient(-75deg, color-mix(in oklch, var(--bgc) 5%, transparent), color-mix(in oklch, var(--bgc) 20%, transparent), color-mix(in oklch, var(--bgc) 5%, transparent)); box-shadow: inset 0 .125em .125em color-mix(in oklch, var(--fg) 5%, transparent), inset 0 -.125em .125em color-mix(in oklch, var(--bgc) 50%, transparent), 0 .25em .125em -.125em color-mix(in oklch, var(--fg) 20%, transparent), 0 0 .1em .25em inset color-mix(in oklch, var(--bgc) 20%, transparent), 0 0 0 0 var(--bgc); }
.glass-button-wrap:hover .glass-button { transform: scale(.975); -webkit-backdrop-filter: blur(.01em); backdrop-filter: blur(.01em); box-shadow: inset 0 .125em .125em color-mix(in oklch, var(--fg) 5%, transparent), inset 0 -.125em .125em color-mix(in oklch, var(--bgc) 50%, transparent), 0 .15em .05em -.1em color-mix(in oklch, var(--fg) 25%, transparent), 0 0 .05em .1em inset color-mix(in oklch, var(--bgc) 50%, transparent), 0 0 0 0 var(--bgc); }
.glass-button-text { position: relative; display: flex; align-items: center; gap: 9px; min-height: 44px; padding: 0 26px; font: 500 11px/1 var(--mono); letter-spacing: .18em; text-transform: uppercase; white-space: nowrap; user-select: none; color: color-mix(in oklch, var(--fg) 90%, transparent); text-shadow: 0 .25em .05em color-mix(in oklch, var(--fg) 10%, transparent); transition: all var(--anim-time) var(--anim-ease); }
.glass-button-wrap:hover .glass-button-text { text-shadow: .025em .025em .025em color-mix(in oklch, var(--fg) 12%, transparent); }
.glass-button-text::after { content: ""; display: block; position: absolute; width: calc(100% - var(--border-width)); height: calc(100% - var(--border-width)); top: calc(0% + var(--border-width) / 2); left: calc(0% + var(--border-width) / 2); box-sizing: border-box; border-radius: 9999px; overflow: clip; background: linear-gradient(var(--angle-2), transparent 0%, color-mix(in oklch, var(--bgc) 50%, transparent) 40% 50%, transparent 55%); z-index: 3; mix-blend-mode: screen; pointer-events: none; background-size: 200% 200%; background-position: 0% 50%; transition: background-position calc(var(--anim-time) * 1.25) var(--anim-ease), --angle-2 calc(var(--anim-time) * 1.25) var(--anim-ease); }
.glass-button-wrap:hover .glass-button-text::after { background-position: 25% 50%; }
.glass-button-wrap:active .glass-button-text::after { background-position: 50% 15%; --angle-2: -15deg; }
.glass-button::after { content: ""; position: absolute; z-index: 1; inset: 0; border-radius: 9999px; width: calc(100% + var(--border-width)); height: calc(100% + var(--border-width)); top: calc(0% - var(--border-width) / 2); left: calc(0% - var(--border-width) / 2); padding: var(--border-width); box-sizing: border-box; background: conic-gradient(from var(--angle-1) at 50% 50%, color-mix(in oklch, var(--fg) 50%, transparent) 0%, transparent 5% 40%, color-mix(in oklch, var(--fg) 50%, transparent) 50%, transparent 60% 95%, color-mix(in oklch, var(--fg) 50%, transparent) 100%), linear-gradient(180deg, color-mix(in oklch, var(--bgc) 50%, transparent), color-mix(in oklch, var(--bgc) 50%, transparent)); -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude; transition: all var(--anim-time) var(--anim-ease), --angle-1 500ms ease; box-shadow: inset 0 0 0 calc(var(--border-width) / 2) color-mix(in oklch, var(--bgc) 50%, transparent); pointer-events: none; }
.glass-button-wrap:hover .glass-button::after { --angle-1: -125deg; }
.glass-button-wrap:active .glass-button::after { --angle-1: -75deg; }
.glass-button-wrap:hover .glass-button-shadow { filter: blur(clamp(2px, .0625em, 6px)); }
.glass-button-wrap:hover .glass-button-shadow::after { top: calc(var(--shadow-cutoff-fix) - .875em); opacity: 1; }
.glass-button-wrap:active .glass-button-shadow { filter: blur(clamp(2px, .125em, 12px)); }
.glass-button-wrap:active .glass-button-shadow::after { top: calc(var(--shadow-cutoff-fix) - .5em); opacity: .75; }
.glass-button-wrap:active .glass-button-text { text-shadow: .025em .25em .05em color-mix(in oklch, var(--fg) 12%, transparent); }
.glass-button-wrap:active .glass-button { box-shadow: inset 0 .125em .125em color-mix(in oklch, var(--fg) 5%, transparent), inset 0 -.125em .125em color-mix(in oklch, var(--bgc) 50%, transparent), 0 .125em .125em -.125em color-mix(in oklch, var(--fg) 20%, transparent), 0 0 .1em .25em inset color-mix(in oklch, var(--bgc) 20%, transparent), 0 .225em .05em 0 color-mix(in oklch, var(--fg) 5%, transparent), 0 .25em 0 0 color-mix(in oklch, var(--bgc) 75%, transparent), inset 0 .25em .05em 0 color-mix(in oklch, var(--fg) 15%, transparent); }
@media (hover: none) and (pointer: coarse) {
    .glass-button::after, .glass-button-wrap:hover .glass-button::after, .glass-button-wrap:active .glass-button::after { --angle-1: -75deg; }
    .glass-button .glass-button-text::after, .glass-button-wrap:active .glass-button-text::after { --angle-2: -45deg; }
}
.glass-button-arrow { flex: none; width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform var(--anim-time) var(--anim-ease); }
.glass-button-wrap:hover .glass-button-arrow { transform: translateX(2px); }
/* The same button in the nav, at the nav's size, as the product's way in on
   every page. */
.glass-button-wrap--nav { flex-shrink: 0; }
.glass-button-wrap--nav .glass-button-text { min-height: 36px; padding: 0 18px; gap: 8px; font-size: 10.5px; letter-spacing: .16em; }
.glass-button-wrap--nav .glass-button-arrow { width: 12px; height: 12px; }
/* Phone sizes, declared after the button's own rules so they win. */
@media (max-width: 720px) {
    .glass-button-wrap--nav .glass-button-text { min-height: 40px; padding: 0 14px; letter-spacing: .1em; }
}
/* The mark, both links and this pill need about 350px and a 360px phone has
   316 inside its gutters: the label wrapped onto two lines and the links ran
   into the mark. The origin story is the first thing under the hero on the
   home page, so its link is the one a narrow phone gives up. */
@media (max-width: 480px) {
    .navlink--origin { display: none; }
}
.footer__blog { font: 400 12px/1.6 var(--mono); color: var(--mute); }

/* Reading progress: a hairline of the accent along the top edge, above the
   nav. post.js sets --progress on the bar; without JS it stays at zero. */
.progress { position: fixed; top: 0; left: 0; right: 0; z-index: 30; height: 2px; pointer-events: none; }
.progress__bar { display: block; height: 100%; background: var(--accent); transform: scaleX(var(--progress, 0)); transform-origin: left; }

/* The section strip sits under the nav for the length of the post, full
   bleed like the nav and on the same column. The section on screen carries
   an ink underline that slides between labels; on a phone the labels scroll
   sideways and the active one is kept in view. */
.sections { position: sticky; top: var(--nav); z-index: 9; padding-inline: max(var(--pad), calc((100% - var(--max)) / 2 + var(--pad))); background: var(--grain), var(--bg); box-shadow: inset 0 -1px 0 var(--line); }
.sections__track { display: flex; gap: clamp(16px, 2.4vw, 32px); overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
/* where the strip scrolls sideways (under 900px) labels leaving the edge
   dissolve rather than being chopped mid-word: the track is padded by the
   fade width and pulled out by the same, so at rest the first label sits
   clear of the fade and only what slides under the edge dissolves */
.sections__track--fade { scroll-behavior: smooth; }
.sections__track::-webkit-scrollbar { display: none; }
.sections__link { position: relative; flex: none; padding: 15px 0 14px; font: 400 10px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--mute); white-space: nowrap; transition: color .2s ease; }
.sections__link:hover, .sections__link[aria-current="true"] { color: var(--ink); }
.sections__link::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: var(--ink); transform: scaleX(0); transform-origin: left; transition: transform .35s cubic-bezier(.22, .61, .36, 1); }
.sections__link[aria-current="true"]::after { transform: none; }

.post { max-width: var(--max); margin-inline: auto; padding: 0 var(--pad) 0; }
.post__head { max-width: 600px; margin-inline: auto; padding-top: clamp(48px, 8vh, 96px); }
.eyebrow__link { transition: color .2s ease; }
.eyebrow__text { padding-bottom: 2px; border-bottom: 1px solid var(--line); transition: border-color .2s ease; }
.eyebrow__link:hover { color: var(--ink); }
.eyebrow__link:hover .eyebrow__text { border-color: var(--rule); }
/* The title cut into the paper like every other title on the site; no
   italic phrase, which read as literary rather than technical. */
.post__title { margin-top: 18px; max-width: 14ch; font-size: clamp(38px, 5.4vw, 64px); line-height: 1.04; letter-spacing: -.015em; }
/* the summary as a standfirst under the title, in the mono like an abstract:
   a size up from the body, softer, no label and no bar */
.standfirst { margin-top: clamp(18px, 3vh, 26px); max-width: 66ch; font: 400 15px/1.75 var(--mono); color: var(--ink-soft); }
.post__meta { margin-top: 22px; font: 400 11px/1.6 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--mute); }
.post__source { margin-top: 9px; font: 400 11.5px/1.65 var(--mono); color: var(--mute); }

/* One measure for the text, with lanes either side for figures to grow into.
   Everything in the article is a grid item, so margins do not collapse and
   the rhythm below is exactly what is written. */
.prose { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 600px) minmax(0, 1fr); margin-top: clamp(28px, 4vh, 44px); font: 400 14px/1.8 var(--mono); color: var(--ink); }
.prose > * { grid-column: 2; min-width: 0; }
.prose > .figure--wide { grid-column: 1 / -1; width: min(100%, 940px); justify-self: center; }
.prose > p { margin-top: 18px; }
.prose > h2 { margin-top: clamp(56px, 8vh, 88px); font-size: clamp(28px, 3.2vw, 40px); line-height: 1.1; }
/* at 28-40px the 4px glow in the lip reads as blur, not light; the cut keeps
   its two edges and loses the glow. The h1s, at 60px+, keep the full lip. */
.prose > h2 { --engrave-lip: 0 1px 1px rgba(255, 250, 242, .9), 0 -1px 1px rgba(40, 30, 15, .4); }
/* the nav and the strip together cover about 104px of the top of the screen */
.prose > h2[id] { scroll-margin-top: calc(var(--nav) + 56px); }
.prose > h2 + p { margin-top: 22px; }
.prose > h3 { margin-top: clamp(38px, 6vh, 58px); font-family: var(--serif); font-size: clamp(21px, 2.4vw, 28px); font-weight: 400; line-height: 1.2; letter-spacing: -.01em; }
.prose > h3[id] { scroll-margin-top: calc(var(--nav) + 56px); }
.prose > h3 + p { margin-top: 18px; }
.prose a.link { border-bottom-color: var(--rule); }
.prose__list { margin-top: 18px; display: grid; gap: 10px; list-style: none; }
.prose__list li { position: relative; padding-left: 20px; }
.prose__list li::before { content: "\2022"; position: absolute; left: 2px; color: var(--mute); }


/* Figures sit on the paper itself, between two hairlines, like the site's
   ruled rows: no box, no shadow. */
.figure { margin: clamp(36px, 5vh, 52px) 0 0; }
.figure__cap { margin-top: 14px; max-width: 68ch; font: 400 11.5px/1.7 var(--mono); color: var(--mute); }
/* under a wide figure the caption starts where the text does, not at the panel's edge */
.figure--wide .figure__cap { margin-left: max(0px, calc((100% - 600px) / 2)); }
.panel { position: relative; padding: clamp(24px, 3vw, 40px) 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.article-image { isolation: isolate; }
.article-image__panel { padding: 0; overflow: hidden; background: #121417; }
.article-image__panel img { display: block; width: 100%; height: auto; max-height: min(72vh, 720px); object-fit: contain; }
.article-image__credit { display: block; margin-top: 5px; color: var(--ink-soft); }

/* the swatches: shared by the bench's controls and its bar */
.swatch { display: inline-block; flex: none; width: 12px; height: 12px; border-radius: 2px; background: var(--ink); }
.swatch--action { background: var(--accent); }
.swatch--check { background: var(--ink); }
.swatch--reset { background: var(--reset); }
.swatch--recovery { background: repeating-linear-gradient(135deg, var(--rule) 0 2px, transparent 2px 5px); }

/* Figure 2: the insertion. The plug approaches, adjusts, pushes home; the
   lamps for contact, force and position come on in the push; the latch
   clicks last, then the carrier withdraws and it starts again. The resting
   styles are the frame with three lamps lit and the latch open, which is
   what a reduced-motion visitor sees, and it is the point of the figure. */
#latch { --latch: 11s; }
.latch__svg { display: block; width: 100%; height: auto; }
.latch__housing { fill: none; stroke: var(--ink); stroke-width: 2; }
.latch__catch { fill: var(--ink); }
.latch__pad { fill: var(--mute); }
.latch__plug { transform: translate(140px, 0); animation: latch-plug var(--latch) infinite; }
.latch__body { fill: var(--page); stroke: var(--ink); stroke-width: 2; }
.latch__tab { fill: var(--accent); animation: latch-tab var(--latch) infinite; }
.latch__pin { stroke: var(--ink); stroke-width: 4; stroke-linecap: round; }
.latch__cable { fill: none; stroke: var(--rule); stroke-width: 3; stroke-linecap: round; }
/* the lamps: a ring each, and an orange fill that comes on with the plug's
   own keyframes. Resting state = contact, force and position lit, latch
   open, which is what Reduce Motion shows. */
.lamps { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px clamp(20px, 4vw, 48px); margin-top: clamp(16px, 2.5vw, 26px); list-style: none; }
.lamps__i { position: relative; padding-left: 22px; font: 400 11px/1.4 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--mute); }
.lamps__i::before { content: ""; position: absolute; left: 0; top: 50%; width: 10px; height: 10px; margin-top: -6.5px; border: 1.5px solid var(--rule); border-radius: 50%; }
.lamps__i::after { content: ""; position: absolute; left: 0; top: 50%; width: 13px; height: 13px; margin-top: -6.5px; border-radius: 50%; background: var(--accent); opacity: 0; }
.lamps__i--contact::after { opacity: 1; animation: latch-on-47 var(--latch) infinite; }
.lamps__i--force::after { opacity: 1; animation: latch-on-50 var(--latch) infinite; }
.lamps__i--position::after { opacity: 1; animation: latch-on-54 var(--latch) infinite; }
.lamps__i--latched::after { animation: latch-on-76 var(--latch) infinite; }
@keyframes latch-plug {
    0%, 8% { transform: translate(0, 0); animation-timing-function: cubic-bezier(.22, .61, .36, 1); }
    36% { transform: translate(90px, 0); animation-timing-function: ease-in-out; }
    39% { transform: translate(90px, -3px); animation-timing-function: ease-in-out; }
    42% { transform: translate(90px, 0); animation-timing-function: cubic-bezier(.55, 0, .85, .45); }
    54%, 90% { transform: translate(140px, 0); animation-timing-function: cubic-bezier(.22, .61, .36, 1); }
    100% { transform: translate(0, 0); }
}
@keyframes latch-tab { 0%, 75% { transform: translateY(0); } 77%, 90% { transform: translateY(4px); } 100% { transform: translateY(0); } }
@keyframes latch-on-47 { 0%, 46% { opacity: 0; } 47%, 90% { opacity: 1; } 91%, 100% { opacity: 0; } }
@keyframes latch-on-50 { 0%, 49% { opacity: 0; } 50%, 90% { opacity: 1; } 91%, 100% { opacity: 0; } }
@keyframes latch-on-54 { 0%, 53% { opacity: 0; } 54%, 90% { opacity: 1; } 91%, 100% { opacity: 0; } }
@keyframes latch-on-76 { 0%, 75% { opacity: 0; } 76%, 90% { opacity: 1; } 91%, 100% { opacity: 0; } }

/* The one equation, set as a fraction in the serif; no maths library for a
   single line. The role and label read it out in words. */
.formula { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px 18px; margin-top: 26px; padding: 26px 16px; border-block: 1px solid var(--line); font-family: var(--serif); font-size: clamp(17px, 2.2vw, 22px); line-height: 1.3; }
.formula__lhs { white-space: nowrap; }
.formula__eq { color: var(--mute); }
.formula__frac { display: inline-grid; justify-items: center; text-align: center; }
.formula__num { padding: 0 12px 6px; border-bottom: 1px solid var(--ink); }
.formula__den { padding: 6px 12px 0; white-space: nowrap; }
.formula var { font-style: italic; }
.formula sub { font: 400 .58em/1 var(--mono); letter-spacing: .04em; vertical-align: -.35em; }

/* Figure 3: the formula with handles. Chips for the worked examples, a
   slider per term, the rate in the serif, and one trial as a bar with the
   terms to scale. The playhead crosses it once per trial at the ring's 20x. */
.bench__panel { --lap: 6s; }
.bench__presets { display: flex; flex-wrap: wrap; gap: 8px; }
.chip { display: inline-flex; align-items: center; justify-content: center; min-height: 34px; padding: 0 14px; border: 1px solid var(--rule); border-radius: 0; background: none; color: var(--ink-soft); font: 500 10px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase; cursor: pointer; transition: background .2s ease, border-color .2s ease, color .2s ease; }
.chip:hover { color: var(--ink); border-color: var(--ink); }
.chip.is-on { background: var(--ink); border-color: var(--ink); color: var(--page); }
.bench__grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: center; gap: clamp(20px, 4vw, 56px); margin-top: clamp(20px, 3vh, 30px); }
.bench__controls { display: grid; gap: 16px; }
.bench__ctl { display: grid; grid-template-columns: 112px minmax(0, 1fr) 48px; align-items: center; gap: 14px; }
.bench__name { display: flex; align-items: center; gap: 10px; font: 400 11px/1.4 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-soft); }
.bench__ctl output { font: 400 15px/1 var(--serif); text-align: right; color: var(--ink); font-variant-numeric: tabular-nums; }
.bench__ctl input[type="range"] { width: 100%; height: 2px; margin: 0; -webkit-appearance: none; appearance: none; background: var(--rule); outline: none; }
.bench__ctl input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; border: 0; border-radius: 50%; background: var(--ink); cursor: pointer; }
.bench__ctl input[type="range"]::-moz-range-thumb { width: 16px; height: 16px; border: 0; border-radius: 50%; background: var(--ink); cursor: pointer; }
.bench__ctl input[type="range"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; }
.bench__out { min-width: 0; }
.bench__big { display: flex; flex-wrap: wrap; align-items: baseline; gap: 14px; }
.bench__n { font-family: var(--serif); font-size: clamp(56px, 7vw, 92px); line-height: 1; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.bench__unit { font: 400 10px/1.4 var(--mono); letter-spacing: .22em; text-transform: uppercase; color: var(--mute); }
.bench__small { margin-top: 12px; font: 400 12px/1.75 var(--mono); color: var(--ink-soft); }
.bench__bar { position: relative; display: flex; height: 22px; margin-top: clamp(22px, 3vh, 32px); overflow: hidden; background: var(--line); }
.bench__seg { flex: 1 1 0px; min-width: 0; height: 100%; transition: flex-grow .5s cubic-bezier(.22, .61, .36, 1); }
.bench__seg--action { background: var(--accent); }
.bench__seg--check { background: var(--ink); }
.bench__seg--reset { background: var(--reset); }
.bench__seg--recovery { background: repeating-linear-gradient(135deg, var(--rule) 0 3px, transparent 3px 8px); }
/* a full-width element whose right edge is the head, moved with transform
   so it never touches layout */
.bench__head { position: absolute; inset: 0; border-right: 2px solid var(--page); box-shadow: 1px 0 0 var(--ink); transform: translateX(-100%); animation: bench-sweep var(--lap) linear infinite; }
@keyframes bench-sweep { to { transform: translateX(0); } }

/* the table from the text, as ruled rows: the question in the serif, the
   evidence in the mono */
#measurements { margin-top: 24px; }
.evidence__table { width: 100%; margin-top: 0; border-collapse: collapse; }
.evidence__table th { padding: 0 14px 12px 0; text-align: left; font: 500 10px/1.4 var(--mono); letter-spacing: .22em; text-transform: uppercase; color: var(--mute); border-bottom: 1px solid var(--rule); }
.evidence__table td { padding: 16px 14px 16px 0; vertical-align: top; border-bottom: 1px solid var(--line); font: 400 13px/1.75 var(--mono); color: var(--ink-soft); }
.evidence__table td:first-child { width: 42%; font-family: var(--serif); font-size: 18px; line-height: 1.3; color: var(--ink); }

/* the way out: pass it on, or argue */
.post__end { max-width: 600px; margin: clamp(56px, 9vh, 96px) auto 0; padding-top: 28px; border-top: 1px solid var(--line); }
.share { max-width: 60ch; }
.share__lead { font: 400 12px/1.7 var(--mono); color: var(--mute); }
.share__row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.share__row [data-copy-link] { min-width: 112px; }
/* who wrote it: a name and two lines, the last thing on the page */
.author { margin-top: clamp(32px, 5vh, 48px); padding-top: 22px; border-top: 1px solid var(--line); }
.author__name { font: 500 11px/1.6 var(--mono); letter-spacing: .12em; text-transform: uppercase; }
.author__bio { margin-top: 6px; max-width: 56ch; font: 400 12.5px/1.75 var(--mono); color: var(--ink-soft); }

@media (max-width: 900px) {
    .bench__grid { grid-template-columns: minmax(0, 1fr); }
    .postrow { grid-template-columns: minmax(0, 1fr); gap: 12px; }
}
@media (max-width: 720px) {
    .sections__link { font-size: 9px; letter-spacing: .1em; }
    .lamps { display: grid; grid-template-columns: repeat(2, max-content); gap: 10px 32px; }
    .post__title { font-size: clamp(32px, 9vw, 42px); }
    .prose > h2 { font-size: clamp(24px, 7vw, 30px); }
    .formula { font-size: 15px; padding-inline: 0; flex-direction: column; gap: 8px; }
    .formula__den { white-space: normal; }
    .bench__ctl { grid-template-columns: 96px minmax(0, 1fr) 44px; gap: 10px; }
    .bench__presets .chip { flex: 1 1 auto; }
    /* the two columns squeeze to 24 characters here: stack the question over its evidence */
    .evidence__table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
    .evidence__table tr, .evidence__table td { display: block; }
    .evidence__table td { padding: 0; border: 0; }
    .evidence__table td:first-child { width: auto; padding-top: 18px; font-size: 18px; }
    .evidence__table tr:first-child td:first-child { border-top: 1px solid var(--rule); }
    .evidence__table td:last-child { padding: 8px 0 18px; border-bottom: 1px solid var(--line); }
}
@media (prefers-reduced-motion: reduce) {
    .latch__plug, .latch__tab, .lamps__i::after, .spline__loader i { animation: none; }
    .bench__head { display: none; }
    .bench__seg, .sections__link, .sections__link::after, .chip, .postrow, .postrow__go, .eyebrow__link { transition: none; }
}

/* ------------------------------------------------------------------------
   Two pieces after React components Husan chose, rebuilt as SVG + CSS so
   the site keeps zero dependencies.

   The scan-text mark, from Lucide Animated (MIT, @pqoqubbw): four corners
   and three lines. On hover of whatever carries it, and once as its carrier
   is revealed (html.reveal + [data-scan], see reveal.js), the lines wipe
   right-to-left and redraw left-to-right, .1 s apart, the way the original
   does with pathLength. pathLength="1" on each line makes the dash maths
   unit-free: "1 1" is the whole line, "0 1" is none of it. */
.scan { display: inline-block; flex: none; width: 1em; height: 1em; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; vertical-align: -.12em; }
.scan__line { stroke-dasharray: 1 1; }
.is-scanning .scan__line, .postrow:hover .scan__line, .eyebrow--scan:hover .scan__line { animation: scan-line .8s cubic-bezier(.4, 0, .2, 1) both; animation-delay: calc(var(--i) * .1s); }
/* erase for .3 s, hold, redraw for .3 s: the original awaits all three
   erasures before any line redraws, which is what the hold reproduces */
@keyframes scan-line {
    0% { stroke-dasharray: 1 1; opacity: 1; }
    37.5% { stroke-dasharray: 0 1; opacity: 0; }
    62.5% { stroke-dasharray: 0 1; opacity: 0; }
    100% { stroke-dasharray: 1 1; opacity: 1; }
}
.eyebrow--scan { display: inline-flex; align-items: center; gap: 9px; }
.eyebrow--scan .scan { font-size: 15px; }
.postrow__go { display: inline-flex; align-items: center; gap: 8px; }
.postrow__go .scan { font-size: 14px; }

/* The blog hero: full bleed like the sheets, the copy on the left of the
   column, the robot on the right. Replaces the careers masthead on this
   page only. */
.bloghero { --hero-pad-b: clamp(64px, 10vh, 120px); position: relative; overflow: hidden; box-shadow: inset 0 -1px 0 var(--line); min-height: clamp(380px, 54svh, 560px); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 520px); align-items: center; gap: clamp(24px, 4vw, 72px); padding-block: clamp(64px, 10vh, 120px) var(--hero-pad-b); padding-inline: max(var(--pad), calc((100% - var(--max)) / 2 + var(--pad))); }
.bloghero__copy { position: relative; z-index: 1; }
/* The robot: a square on the right of the copy, Spline's canvas over the
   page's paper. The scene frames the robot to the knees, so the square
   stands on the hero's bottom edge and the last stretch of it dissolves
   into the paper: the legs fade out rather than ending in a line. The
   mark's three dots hold the space while the runtime and the scene arrive,
   then the canvas fades in; if nothing arrives, paper. */
.spline { position: relative; margin: 0 0 calc(-1 * var(--hero-pad-b)); width: min(100%, 520px); aspect-ratio: 1; justify-self: end; align-self: end; }
.spline__canvas { position: absolute; inset: 0; width: 100%; height: 100%; touch-action: pan-y; opacity: 0; transition: opacity .45s ease; -webkit-mask-image: linear-gradient(to bottom, #000 76%, transparent 97%); mask-image: linear-gradient(to bottom, #000 76%, transparent 97%); }
.spline.is-ready .spline__canvas { opacity: 1; }
.spline__loader { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 9px; opacity: 0; transition: opacity .4s ease; }
.spline.is-loading .spline__loader { opacity: 1; }
.spline__loader i { width: 9px; height: 9px; border-radius: 50%; background: var(--ink); animation: spline-wait 1.2s ease-in-out infinite; }
.spline__loader i:nth-child(2) { background: var(--accent); animation-delay: .15s; }
.spline__loader i:nth-child(3) { animation-delay: .3s; }
@keyframes spline-wait { 0%, 100% { opacity: .35; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-4px); } }
.bloghero__t { margin-top: 20px; max-width: 18ch; font-size: clamp(38px, 6vw, 68px); line-height: 1.04; letter-spacing: -.015em; }
.bloghero .masthead__lead { max-width: 56ch; }
/* .post is full bleed, with the text kept on the column by the same padding
   the nav and the sheets use; everything on top of it is lifted a layer. */
.post { max-width: none; margin: 0; padding-inline: max(var(--pad), calc((100% - var(--max)) / 2 + var(--pad))); position: relative; }
.post__head, .prose, .post__end { position: relative; z-index: 1; }

@media (max-width: 899px) {
    .bloghero { grid-template-columns: minmax(0, 1fr); }
    .spline { justify-self: center; width: min(100%, 360px); }
    .sections__track--fade { margin-inline: -28px; padding-inline: 28px; scroll-padding-inline: 28px; -webkit-mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent); }
}
@media (max-width: 720px) {
    /* the copy sits at the top and the ribbons take a band under it, where
       nothing is written, whatever height the copy wraps to */
    .bloghero { --hero-pad-b: clamp(40px, 6vh, 64px); min-height: 0; align-content: start; }
    .spline { width: min(100%, 320px); }
    .bloghero__t { font-size: clamp(34px, 10vw, 44px); }
}
@media (prefers-reduced-motion: reduce) {
    .glass-button-wrap, .glass-button-tilt, .glass-button, .glass-button-text, .glass-button-text::after, .glass-button::after, .glass-button-shadow, .glass-button-shadow::after, .glass-button-arrow { transition: none; }
    .glass-button-wrap:active .glass-button-tilt { transform: none; }
    .is-scanning .scan__line, .postrow:hover .scan__line, .eyebrow--scan:hover .scan__line { animation: none; }
}

/* Set by post.js on a figure that has left the screen. Last in the file on
   purpose: the figures' own animation shorthands would otherwise win the tie
   and set play-state back to running. */
.is-off *, .is-off *::before, .is-off *::after { animation-play-state: paused; }
