/* Two Wheel Time Traveler, home comp v4
   Their system, our voice. Layout, spacing, chrome and motion follow good-fella.com's
   shipped code (research/goodfella-code-transplant.md, read verbatim 2026-09-13); type is
   Lettera + Geist and the palette is ink, paper and one scarlet primary (blue out, red in,
   on Chase's call 2026-09-13). */

:root {
  --ink: #0A0605;
  --ink-2: #14100E;
  --ink-3: #1B1613;        /* a card on ink: one step lighter than the header bar, so the panel reads without a rule (2026-09-16) */
  --paper: #F2EFE9;
  --paper-2: #E4E0D8;      /* the header bar on paper chapters, their surface role */
  --paper-bright: #FAF8F3;
  --primary: #E0281B;        /* scarlet, Chase's pick 2026-09-13 out of six reds; the one color on top of ink and paper */
  --on-primary: var(--paper-bright);
  /* Chase, 2026-09-14: the scarlet stays for marks and tiles. Where red is text, or text sits on red, one of these two
     takes its place so small type passes AA. No single red passes on both ink and paper. */
  --primary-deep: #CE2519;   /* red text on paper, and every red fill that carries paper text: 5.07 to 1 under paper text, 4.69 on paper */
  --primary-bright: #E5362A; /* red text on ink: 4.70 to 1 */
  --red-text: var(--primary-bright);
  --t-ink-2: rgba(232, 228, 220, 0.62);
  --t-ink-3: rgba(232, 228, 220, 0.58);   /* lifted from 0.42 so 13px text passes AA on ink (review 2026-09-13, major 12) */
  --t-paper-2: rgba(10, 6, 5, 0.62);
  --t-paper-3: rgba(10, 6, 5, 0.62);       /* lifted from 0.42 for AA on paper */
  --rule-ink: rgba(232, 228, 220, 0.14);
  --rule-paper: rgba(10, 6, 5, 0.14);
  --mono: 'OlivettiLettera-Regular', 'Courier Prime', monospace;
  --sans: 'Geist', -apple-system, system-ui, sans-serif;
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out-quart: cubic-bezier(0.76, 0, 0.24, 1);
  --ease-in-out-quint: cubic-bezier(0.83, 0, 0.17, 1);
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-out-cubic: cubic-bezier(0.33, 1, 0.68, 1);
  --ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-underline: cubic-bezier(0.625, 0.05, 0, 1);
  --gutter: 32px;
  --sq: 16px;
  --head-h: 72px;
  --chapter-pad: 128px;
  --square-extend-left: 0px;
}
@media (orientation: portrait) { :root { --square-extend-left: 100vw; } }

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scrollbar-gutter: stable; }
/* Their scroll lock, verbatim in effect. */
html.scroll-locked { overflow: hidden; }
html.scroll-locked body { overscroll-behavior: none; width: 100%; position: fixed; left: 0; right: 0; overflow: hidden; }
html.scroll-stopped { overflow: hidden; }
body { background: var(--ink); color: var(--paper); font-family: var(--sans); font-size: 16px; line-height: 1.5; -webkit-font-smoothing: antialiased; overflow-x: hidden; }
::selection { background: var(--primary-deep); color: var(--on-primary); }
.ground-paper ::selection { background: var(--primary-deep); color: var(--on-primary); }
:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }
section:focus-visible, main:focus-visible { outline: none; }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
.defs { position: absolute; }
.dim { opacity: 0.45; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

/* Grounds. A chapter sets its own colors; everything inside reads the ground's tokens. */
.ground-ink { --red-text: var(--primary-bright); --fg: var(--paper); --fg-2: var(--t-ink-2); --fg-3: var(--t-ink-3); --bg: var(--ink); --rule: var(--rule-ink); --surface: var(--ink-2); background: var(--bg); color: var(--fg); }
.ground-paper { --red-text: var(--primary-deep); --fg: var(--ink); --fg-2: var(--t-paper-2); --fg-3: var(--t-paper-3); --bg: var(--paper); --rule: var(--rule-paper); --surface: var(--paper-2); background: var(--bg); color: var(--fg); }

/* Type roles. Lettera keeps its own open tracking by law; no negative tracking anywhere. */
.mono { font-family: var(--mono); font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase; line-height: 1.4; }
.display { font-family: var(--mono); font-weight: 400; font-synthesis: none; text-transform: uppercase; font-size: clamp(52px, 6.6vw, 128px); line-height: 1.02; letter-spacing: 0.005em; max-width: 12ch; text-wrap: balance; }
.h2 { font-family: var(--mono); font-weight: 400; font-synthesis: none; text-transform: uppercase; font-size: clamp(36px, 3.4vw, 64px); line-height: 1.08; letter-spacing: 0.01em; text-wrap: balance; }
.h2-lg { font-size: clamp(40px, 4.4vw, 84px); max-width: 10ch; }
.h3 { font-family: var(--mono); font-weight: 400; font-synthesis: none; text-transform: uppercase; font-size: clamp(22px, 1.9vw, 34px); line-height: 1.15; letter-spacing: 0.01em; }
.lead { font-size: clamp(17px, 1.15vw, 20px); line-height: 1.5; color: var(--fg-2); max-width: 36em; text-wrap: pretty; }
.lead-ink { color: var(--fg); }

.wrap { padding: 0 var(--gutter); }

/* ===== Headline reveal: their AnimatedHeadline. Each line is inline-block with two rectangles overhanging it by 0.1em. ===== */
.line { position: relative; display: inline-block; }
.line-inner { display: block; white-space: nowrap; }
.rect { position: absolute; inset: -0.1em; }
.rect-brand { background: var(--primary); }
.rect-fg { background: var(--fg); }
/* Paragraph reveal: their AnimatedText. Hidden until the masked lines rise. */
.js [data-text] { visibility: hidden; }

/* ===== Scramble labels (their three-span ScrambleText) ===== */
.sc { position: relative; display: inline-block; white-space: nowrap; }
.sc-ghost { visibility: hidden; white-space: nowrap; }
.sc-live { position: absolute; top: 0; left: 0; white-space: nowrap; }
.sc-1 { color: var(--red-text); }
.btn-ink, .head { --red-text: var(--primary-bright); }
.head.on-paper { --red-text: var(--primary-deep); }
.sc-1-on { color: var(--ink); }
.sc-2 { color: inherit; }

/* ===== Loader: ours. On ink (Chase, 2026-09-17, third note): the logo large in the center, the trip odometer under it rolling
   to a hundred while the file opens, then the first iteration's opening text one line at a time, and a dated Received stamp
   last. It leaves through demo 6's tiles. ===== */
.loader { position: fixed; inset: 0; z-index: 10000; background: var(--ink); color: var(--paper); display: flex; align-items: center; justify-content: center; padding: clamp(16px, 3vh, 40px) var(--gutter); }
/* The opening belongs to the script. With no script there is none, and the escape in the head restores this state. */
html:not(.js) .loader { display: none; }
/* Everything on the opening starts unseen and is brought in by the script, the logo first (Chase, 2026-09-17: it was sitting there before the timeline began). */
.js .loader-logo, .js .loader-odo, .js .loader [data-boot] { opacity: 0; }
.loader-inner { position: relative; display: flex; flex-direction: column; align-items: center; gap: clamp(18px, 3vh, 36px); width: 100%; }
.loader-id { display: flex; flex-direction: column; align-items: center; gap: clamp(14px, 2.4vh, 28px); }
/* Justin's logo, large, its black ground keyed out so it sits on the ink. */
/* The logo sits in a picture so a phone gets the smaller copy; the picture wraps it exactly and adds no space. */
.loader picture { display: block; line-height: 0; }
.loader-logo { display: block; width: auto; height: auto; max-width: min(560px, 72vw); max-height: 34vh; }
/* The odometer: the header's reels, larger. It rolls from 000.0 to 100.0 (the script) and the page jumps when it lands. */
.loader-odo { gap: 4px; }
.loader-odo .trip-digit { width: 1.35ch; height: 44px; line-height: 44px; font-size: 30px; background: var(--ink-2); border-color: var(--rule-ink); }
.loader-odo .trip-dot { font-size: 30px; line-height: 44px; }
/* The opening text, the first iteration's, a little bigger (12px there, 14px here). */
.loader-file { width: min(520px, 100%); }
.loader-head, .loader-rows, .loader-line { font-size: 14px; letter-spacing: 0.09em; }
.loader-head { display: flex; justify-content: space-between; gap: 16px; padding-bottom: 10px; border-bottom: 1px solid var(--rule-ink); color: var(--t-ink-3); }
.loader-rows { list-style: none; }
.loader-rows li { display: flex; align-items: baseline; gap: 14px; padding: 9px 0; border-bottom: 1px solid var(--rule-ink); color: var(--t-ink-2); }
.loader-rows li:last-child { border-bottom: 0; }
.loader-rows li span:last-child { margin-left: auto; color: var(--paper); min-height: 1.4em; }
.loader-line { display: flex; align-items: center; margin-top: 12px; color: var(--t-ink-3); min-height: 1.4em; }
/* The typed cursor after Opening file, the first iteration's. */
.type-caret { display: inline-block; width: 0.5em; height: 0.8em; background: var(--t-ink-2); margin-left: 0.15em; transform: translateY(0.08em); animation: caret 1.05s steps(1) infinite; }
@keyframes caret { 50% { opacity: 0; } }
/* The Received stamp: the events' Next stamp, with today's date, slammed on last (the script tilts and slams it). */
.loader-stamp { margin-left: auto; font-size: 12px; letter-spacing: 0.1em; white-space: nowrap; }
@media (max-width: 820px) {
  .loader-logo { max-height: 26vh; }
  .loader-odo .trip-digit { height: 36px; line-height: 36px; font-size: 24px; }
  .loader-odo .trip-dot { font-size: 24px; line-height: 36px; }
  .loader-head, .loader-rows, .loader-line { font-size: 13px; }
  .loader-rows li { padding: 8px 0; }
  .loader-head { padding-bottom: 8px; }
}
/* A short window (a phone on its side): the logo and the reels sit beside the text so it all fits. */
@media (max-height: 620px) {
  .loader-inner { flex-direction: row; justify-content: center; gap: clamp(24px, 4vw, 48px); }
  .loader-logo { max-height: 30vh; max-width: 36vw; }
  .loader-id { gap: 10px; }
  .loader-odo .trip-digit { height: 32px; line-height: 32px; font-size: 22px; }
  .loader-odo .trip-dot { font-size: 22px; line-height: 32px; }
  .loader-file { width: min(440px, 52vw); }
  .loader-head, .loader-rows, .loader-line { font-size: 12px; }
  .loader-rows li { padding: 5px 0; }
  .loader-head { padding-bottom: 6px; }
  .loader-line { margin-top: 8px; }
}
.px-overlay { position: fixed; inset: 0; z-index: 10001; display: grid; grid-template-columns: repeat(var(--columns), 1fr); grid-template-rows: repeat(var(--rows), 1fr); pointer-events: none; opacity: 0; }
/* Demo 6's tiles are a shade off its background. On our ink that shade would not be seen, so the tiles are scarlet for now. */
.px-overlay div { background: var(--primary); }

/* ===== Header: theirs. Transparent at the top, a padded bar after 50px, hidden only near the footer. ===== */
.head { --header-y: 0%; position: fixed; top: 0; left: 0; right: 0; z-index: 9990; padding: 16px var(--gutter) 0; display: flex; flex-direction: column; gap: 8px; transform: translateY(var(--header-y)); transition: transform 0.4s var(--ease-out-back); will-change: transform; }
.js .head.header-hidden { --header-y: -100%; transition: transform 0.4s var(--ease-in-out-quart); }
.head-bar { display: grid; grid-template-columns: 1fr auto 1fr; column-gap: 12px; align-items: center; height: var(--head-h); padding: 0; background: transparent; color: var(--paper); transition: padding 0.5s ease-out, background-color 0.5s ease-out, color 0.5s ease-out; }
.head.is-scrolled .head-bar { padding: 0 16px; background: var(--ink-2); }
.head.on-paper .head-bar { color: var(--ink); }
.head.on-paper.is-scrolled .head-bar { background: var(--paper-2); }
/* Lettera ships one weight, so the wordmark sets in Regular. The double-strike bold came out on Chase's review, 2026-09-14. */
.wordmark::after, .menu-btn::after { content: ""; position: absolute; inset: -14px -8px; }
.head-left { justify-self: start; display: flex; align-items: center; gap: 28px; }
.wordmark { position: relative; font-size: 15px; letter-spacing: 0.1em; white-space: nowrap; }
/* The trip odometer: the first iteration's, back on Chase's call 2026-09-17. Book 1 ch29, the odometer flipping by as a clock. Three
   whole-mile reels and a boxed tenths reel, Trip A before and mi after; miles by scroll, the reels easing after the scrollbar. */
.odo-read { display: inline-flex; align-items: center; gap: 12px; color: var(--paper); }
.trip-label, .trip-unit { font-size: 12px; letter-spacing: 0.06em; color: var(--t-ink-2); }
.head.on-paper .trip-label, .head.on-paper .trip-unit { color: var(--t-paper-2); }
.trip-odo { display: inline-flex; gap: 3px; }
/* A reel: a window one step lighter than its ground, ten digits stacked behind it (an eleventh, 0, is added by the script so 9 rolls on). */
.trip-digit { display: block; width: 1.35ch; height: 30px; overflow: hidden; border: 1px solid var(--rule-ink); font-size: 20px; line-height: 30px; text-align: center; color: var(--paper-bright); background: var(--ink-2); }
.head.is-scrolled .trip-digit { background: var(--ink-3); }
.head.on-paper .trip-digit { border-color: transparent; background: var(--ink); } /* on the paper chapter the reels stay ink, an odometer window in a paper dash */
.trip-tenths { border-color: rgba(232, 228, 220, 0.3); color: var(--paper); }
.trip-reel { display: block; will-change: transform; }
.trip-dot { font-size: 20px; line-height: 30px; color: var(--t-ink-3); align-self: flex-end; }
.head.on-paper .trip-dot { color: var(--t-paper-3); }
.head-center { grid-column: 2; grid-row: 1; justify-self: center; }
.head-right { grid-column: 3; grid-row: 1; justify-self: end; display: flex; align-items: center; gap: 12px; }
.menu-btn { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; background: var(--primary-deep); color: var(--on-primary); border: 0; border-radius: 2px; cursor: pointer; }

.menu-words { position: relative; display: block; height: 1em; width: 3.6em; overflow: hidden; line-height: 1; }
.menu-word-slot { display: flex; flex-direction: column; gap: 2px; transition: transform 0.3s ease-out; }
.menu-word-slot span { display: block; height: 1em; line-height: 1; text-align: left; }
.menu-btn.is-open .menu-word-slot { transform: translateY(calc(-1em - 2px)); }
.menu-glyph { position: relative; display: flex; width: 16px; height: 16px; flex-direction: column; align-items: center; justify-content: center; }
.menu-glyph i { position: absolute; display: block; height: 2px; width: 100%; background: currentColor; transform-origin: center; transition: transform 250ms ease-out; }
.menu-glyph i:first-child { transform: rotate(0deg) translateY(-3px); }
.menu-glyph i:last-child { transform: rotate(0deg) translateY(3px); }
.menu-btn.is-open .menu-glyph i:first-child { transform: rotate(45deg) translateY(0); }
.menu-btn.is-open .menu-glyph i:last-child { transform: rotate(-45deg) translateY(0); }
.head-left { grid-column: 1; grid-row: 1; }
/* The menu panel lives in the header's column, like theirs, and opens on a grid track. */
.menu { display: grid; grid-template-rows: 0fr; background: var(--ink); color: var(--paper); pointer-events: none; }
.menu.is-open { pointer-events: auto; }
.menu-clip { overflow: hidden; }
.menu-inner { padding: 48px 64px 64px; }
.menu-file { display: flex; justify-content: space-between; gap: 24px; color: var(--t-ink-3); padding-bottom: 14px; margin-bottom: 40px; border-bottom: 1px solid var(--rule-ink); }
.menu-num.tab { font-size: 12px; line-height: 1.3; padding: 5px 9px 4px; margin-top: 0.16em; color: var(--ink); background: var(--paper); border-radius: 2px 2px 0 0; }
.menu-tiles { position: relative; }
.menu-slip { position: absolute; left: 20px; bottom: 20px; }
.menu-grid { display: grid; grid-template-columns: 4fr 3fr 5fr; gap: 32px 48px; align-items: start; }
.menu-contact { display: flex; flex-direction: column; gap: 6px; font-size: 16px; line-height: 1.5; padding-top: 8px; }
.menu-contact p { overflow: hidden; }
.menu-contact [data-menu-line] { display: block; }
.menu-contact a { transition: color 0.3s; }
.menu-contact a:hover { color: var(--primary-bright); }
.menu-label { color: var(--t-ink-3); }
.menu-gap { margin-top: 16px; }
/* The tile fills the row's height, so its gaps to the panel's top, right and bottom edges are all the panel's padding. */
/* The tile is a 4:3 mask whose height is set to the nav's height when the menu opens (JS), so it scales with the words as the window widens. */
.menu-tiles { justify-self: end; align-self: start; width: auto; max-width: 100%; aspect-ratio: 4 / 3; overflow: hidden; background: var(--ink-2); opacity: 0; }
.menu-tiles video { width: 100%; height: 100%; object-fit: cover; display: block; }
.menu-nav { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 16px; }
.menu-row { overflow-y: clip; overflow-x: visible; display: grid; grid-template-columns: 3ch 1fr; column-gap: 18px; align-items: start; }
.menu-num-clip { grid-column: 1; grid-row: 1; overflow: hidden; margin-top: 14px; font-size: 12px; line-height: 1.3; } /* the number is a tab now, so the clip is tab-sized and sits at the top of the word (2026-09-16) */
.menu-num-clip .menu-num.tab { display: inline-block; margin-top: 0; }
.menu-num { display: block; color: var(--t-ink-3); }
.menu-row .menu-link { grid-column: 2; grid-row: 1; }
.menu-sub-clip { grid-column: 2; grid-row: 2; overflow: hidden; margin: -2px 0 6px; }
.menu-sub { display: block; color: var(--t-ink-3); }
.menu-link { display: block; padding: 4px 0; font-family: var(--mono); text-transform: uppercase; font-size: clamp(40px, 4.6vw, 76px); line-height: 1.05; transition: color 0.3s; will-change: transform; }
.menu-link:hover { color: var(--primary-bright); }
.scrim { position: fixed; inset: 0; z-index: 9989; background: rgba(0, 0, 0, 0.3); backdrop-filter: blur(4px); opacity: 0; pointer-events: none; transition: opacity 0.5s ease-out; }
.scrim.is-on { opacity: 1; pointer-events: auto; }

/* ===== Button: label block; the decode plays on the absolute layer so the width never moves (the squares came out 2026-09-12 on Chase's call). ===== */
/* Chase, 2026-09-14: a 2px radius on every hard edge: buttons, tags, chips, cards, covers, stills, video frames, the header bar, the menu panel, the odometer cells. */
.card, .shop-band, .card-cover, .fw-media, .video-frame, .menu-tiles, .menu, .head-bar, .trip-digit { border-radius: 2px; }
/* 42px since 2026-09-21 (Chase): Shopify's Shop Pay button sets its own height at 42, and every button on the site
   matches it rather than sitting 2px short beside it. The newsletter field and the pointer label follow. */
.btn { position: relative; display: inline-flex; align-items: stretch; height: 42px; cursor: pointer; border: 0; font: inherit; border-radius: 2px; }
.btn-label { display: inline-flex; align-items: center; padding: 0 20px; font-size: 14px; letter-spacing: 0.06em; position: relative; white-space: nowrap; }
.btn-label .sc-live { left: 20px; top: 50%; transform: translateY(-50%); }
/* The hover effect redraws a label's letters many times a second. A press that lands on a letter loses it before the
   release, and the browser then never reports a click; a click that does land is on a letter that is gone by the time
   the page asks where it was. The button itself takes the pointer instead, and it never goes anywhere. */
.btn .btn-label { pointer-events: none; }
.btn-paper { background: var(--primary-deep); color: var(--on-primary); }
.btn-ink { background: var(--ink); color: var(--paper); }
.btn-outline { background: transparent; color: inherit; box-shadow: inset 0 0 0 1px currentColor; } /* the header's Shop: outlined, so the Menu square is the one filled block in the chrome (Chase, 2026-09-14, decision 4) */

/* Text link: two rules. On hover the first leaves right at once, the second arrives from the left 300 ms later; on leave the order swaps. */
.link { position: relative; display: inline-block; font-size: 16px; padding-bottom: 3px; }
.link span { position: relative; }
.link::before, .link::after { content: ""; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background: currentColor; transition: transform 0.7s var(--ease-underline); }
.link::before { transform: scaleX(1); transform-origin: left; transition-delay: 0.3s; }
.link::after { transform: scaleX(0); transform-origin: right; transition-delay: 0s; background: var(--red-text); } /* the arriving rule is the indexer's red pencil (2026-09-16) */
.link:hover::before, .link:focus-visible::before { transform: scaleX(0); transform-origin: right; transition-delay: 0s; }
.link:hover::after, .link:focus-visible::after { transform: scaleX(1); transform-origin: left; transition-delay: 0.3s; }

/* ===== 01 · Title card ===== */
.hero { position: relative; min-height: 100svh; display: flex; flex-direction: column; justify-content: flex-end; overflow: hidden; padding: calc(16px + var(--head-h) + 40px) 0 40px; }
.hero-art { position: absolute; top: 0; right: 0; bottom: 0; width: 58%; overflow: hidden; will-change: transform; }
.hero-art-img { position: absolute; inset: -6%; background: url('assets/ydbh-hero.webp') 58% 26% / 150% no-repeat; filter: saturate(1.06) contrast(1.06); will-change: transform; }
.js .hero-art-img { opacity: 0; }
/* DistortedPixels demo 2, full bleed: their #canvasContainer, sized to the hero instead of the window. The veil on top is our
   ink fade so the copy reads; the right-hand art box below is the fallback where there is no pointer or no WebGL. */
.hero-gl { position: absolute; inset: 0; z-index: 0; display: none; overflow: hidden; }
.hero-gl img { visibility: hidden; pointer-events: none; position: absolute; }
.hero-gl canvas { position: absolute; inset: 0; display: block; }
.hero-gl::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: linear-gradient(90deg, var(--ink) 0%, rgba(10,6,5,0.78) 34%, rgba(10,6,5,0.12) 62%, rgba(10,6,5,0.3) 100%), linear-gradient(0deg, var(--ink) 4%, transparent 40%), linear-gradient(180deg, rgba(10,6,5,0.7) 0%, transparent 30%); }
.hero.is-gl .hero-gl { display: block; }
.hero.is-gl .hero-art { display: none; }
.hero.is-gl.is-gl-in .hero-art { display: block; } /* the still stays under the effect while it fades in late (major 18) */
.hero-grid, .hero-proof { position: relative; z-index: 1; }
.hero-art::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, var(--ink) 0%, rgba(10,6,5,0.55) 30%, rgba(10,6,5,0.08) 70%, rgba(10,6,5,0.35) 100%), linear-gradient(0deg, var(--ink) 4%, transparent 40%), linear-gradient(180deg, rgba(10,6,5,0.7) 0%, transparent 30%); }
.hero-grid { position: relative; z-index: 2; padding: 0 var(--gutter); flex: 1; display: flex; align-items: center; }
/* The case file's frame (first iteration): a hairline inside the hero with a mark at each corner, and the coordinates up the right edge. */
.hero-frame { position: absolute; inset: calc(16px + var(--head-h) + 8px) 16px 16px; z-index: 1; border: 1px solid rgba(232, 228, 220, 0.09); pointer-events: none; }
.mark { position: absolute; font-family: var(--mono); font-size: 14px; color: var(--t-ink-3); line-height: 1; }
.mark-tl { top: -7px; left: -5px; } .mark-tr { top: -7px; right: -5px; } .mark-bl { bottom: -7px; left: -5px; } .mark-br { bottom: -7px; right: -5px; }
.hero-side { position: absolute; z-index: 1; right: 22px; top: 50%; transform: translateY(-50%); writing-mode: vertical-rl; color: var(--t-ink-3); white-space: nowrap; pointer-events: none; }
.hero-slip { margin-left: auto; }
.hero-copy { max-width: 62%; }
/* The mark: Justin's own, in color, above the headline (2026-09-15). Sized so the distortion still reads as a bike. */
.hero-mark { display: block; width: clamp(128px, 12.5vw, 184px); height: auto; margin-bottom: 28px; }
.eyebrow { margin-bottom: 36px; }
.hero .eyebrow.slip { color: var(--ink); }
@media (max-width: 600px) { .hero .eyebrow.slip { white-space: normal; max-width: 100%; } .hero .eyebrow.slip .slip-line { display: block; } } /* The genre slip is too long for one line on a phone: it breaks after "thriller", and wraps further only on the narrowest phones. */
.hero .display { margin-bottom: 36px; }
.hero .lead { margin-bottom: 40px; }
.cta-row { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; }
.hero-proof { position: relative; z-index: 2; display: flex; gap: 18px; flex-wrap: wrap; padding: 0 var(--gutter); margin-top: 96px; color: var(--t-ink-3); }

/* ===== Case art from the first iteration: typed paper slips, ghost numerals, the film strip, file notes ===== */
/* A typed paper slip: paper, ink, the typewriter face, pinned over whatever it labels. */
.slip { display: inline-block; background: var(--paper); color: var(--ink); padding: 8px 14px; font-family: var(--mono); font-size: 12px; letter-spacing: 0.09em; text-transform: uppercase; line-height: 1.4; border-radius: 2px; box-shadow: 0 10px 24px rgba(0, 0, 0, 0.45); white-space: nowrap; }
.slip .dim { opacity: 0.45; }
.slip-tilt { transform: rotate(-1.6deg); }
.still-slip { position: absolute; left: 16px; top: 16px; }
.ride-slip { position: absolute; left: 24px; bottom: 24px; }
/* The ghost numeral: the chapter's number, huge and faint, bleeding off the left edge behind its head. */
.ghost-num { position: absolute; top: 34px; left: -0.35ch; z-index: 0; font-size: clamp(180px, 22vw, 320px); line-height: 0.8; letter-spacing: -0.02em; color: rgba(232, 228, 220, 0.045); pointer-events: none; }
.ground-paper .ghost-num { color: rgba(10, 6, 5, 0.05); }
.chapter > .wrap, .foot-in > .wrap { position: relative; z-index: 1; }
/* The film strip: the perforated band that framed the show in the first iteration, top and bottom of the shows chapter. */
.filmstrip { position: absolute; left: 0; right: 0; height: 16px; background-image: repeating-linear-gradient(90deg, rgba(232, 228, 220, 0.22) 0 12px, transparent 12px 28px); background-position: center; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
.filmstrip-top { top: 0; } .filmstrip-bottom { bottom: 0; }
.strip-band { background: var(--ink-2); }
/* The folder tab: the chapter's number on a small paper tab, the way a file is tabbed. Ink tab on the paper chapter. */
.ch-num.tab { display: inline-block; padding: 5px 10px 4px; background: var(--paper); color: var(--ink); border-radius: 2px 2px 0 0; font-size: 12px; letter-spacing: 0.1em; margin-bottom: 0; }
.ground-paper .ch-num.tab { background: var(--ink); color: var(--paper); }
.foot .ch-num.tab { background: var(--paper); color: var(--ink); }
/* The sheet number: every chapter is a numbered sheet of the file, the way pages are Bates-stamped. Top right of the chapter. */
.sheet { position: absolute; right: var(--gutter); top: 0; color: var(--fg-3); font-size: 12px; }
.chapter > .wrap:first-of-type, .foot-top { position: relative; }
/* The block stamp: a reviewer's rubber stamp, tilted, double-ruled, in the ground's dim ink. */
.rubber { display: inline-block; margin-left: 14px; padding: 3px 8px; border: 1px solid currentColor; box-shadow: inset 0 0 0 2px var(--bg), inset 0 0 0 3px currentColor; color: var(--primary-bright); font-size: 11px; letter-spacing: 0.14em; line-height: 1.3; transform: rotate(-5deg); vertical-align: middle; opacity: 0.85; }
/* Chase, 2026-09-17: the photo corners are gone from every cover, still, tile and thumbnail. */
/* A file note: one typed line under a list, the way the first iteration annotated its ledger. */
.file-note { color: var(--fg-3); margin-top: 24px; }

/* ===== Chapters ===== */
.chapter { position: relative; padding: var(--chapter-pad) 0; }
/* Every chapter head: the heading with its // marker under it, the way the Show rail reads. */
.chapter-head { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.marker { color: var(--red-text); white-space: nowrap; font-size: 14px; }
/* Chapter heads open the way the books' chapters do: number, title in capitals, then a dateline (Chase, 2026-09-14). */
.ch-num { color: var(--fg-3); margin-bottom: -4px; }
.ch-date { color: var(--fg-3); font-size: 14px; white-space: normal; } /* stands alone under the title since the // marker went (decision 5) */
.foot-top .chapter-head { align-items: flex-start; }
.kicker { display: flex; align-items: center; gap: 12px; margin-top: 48px; color: var(--fg); font-size: 14px; }
/* The mark: the bolt from the favicon, the jump's own signature, wherever a label or an active row needs a tick. Scarlet through a mask. */
.kicker-sq, .card-sq { display: inline-block; width: 14px; height: 14px; background: var(--primary); flex: none; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M19 3 L9 18 h6 l-2 11 10-16 h-6 z'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M19 3 L9 18 h6 l-2 11 10-16 h-6 z'/%3E%3C/svg%3E") center / contain no-repeat; }

/* 02 · Books: three cards, their pricing composition. The middle card is dark, like theirs. */
.cards { display: grid; grid-template-columns: repeat(3, 1fr); column-gap: 16px; row-gap: 0; margin-top: 56px; }
.card { --fg: var(--ink); --fg-2: var(--t-paper-2); --fg-3: var(--t-paper-3); --rule: var(--rule-paper); position: relative; display: grid; grid-row: span 7; grid-template-rows: subgrid; row-gap: 0; align-content: start; margin-bottom: 16px; padding: 24px; background: var(--paper-bright); color: var(--fg); }
/* Chase, 2026-09-14: the cards share seven row tracks (label, cover, title, copy, list, meta, button), so every list starts at the same height. */
/* The chip: a small scarlet flag beside the label, for the book that is not out yet. */
.chip { display: inline-block; margin-left: 10px; padding: 3px 8px; border: 1px solid var(--primary-deep); color: var(--primary-deep); font-size: 11px; letter-spacing: 0.08em; line-height: 1; vertical-align: 1px; border-radius: 2px; }
/* The evidence tag: anything held wears a case tag with a punched hole; it comes off when the shop opens (Chase, 2026-09-14). */
/* The tag carries the site's clock, hands at ten o'clock like the loader (Chase, 2026-09-14). */
.tag { position: relative; display: inline-block; border: 1px solid currentColor; padding: 4px 10px 4px 26px; border-radius: 2px; }
.tag::before { content: ""; position: absolute; left: 9px; top: 50%; width: 11px; height: 11px; transform: translateY(-50%); background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Ccircle cx='6' cy='6' r='5' fill='none' stroke='%23000' stroke-width='1.2'/%3E%3Cpath d='M6 6 L6 2.6 M6 6 L3.4 4.5' fill='none' stroke='%23000' stroke-width='1.2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Ccircle cx='6' cy='6' r='5' fill='none' stroke='%23000' stroke-width='1.2'/%3E%3Cpath d='M6 6 L6 2.6 M6 6 L3.4 4.5' fill='none' stroke='%23000' stroke-width='1.2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; }
.shop-note.tag { color: var(--fg-2); font-size: 13px; }
/* Button-sized tag: Book 03's Coming soon sits where a buy button would (Chase, 2026-09-14). */
.btn-tag { display: inline-flex; align-items: stretch; color: var(--primary-deep); padding: 0; cursor: default; }
.btn-tag .btn-label { padding-left: 34px; }
.btn-tag .btn-label .sc-live { left: 34px; }
.btn-tag::before { left: 12px; }
.card-label { display: flex; align-items: center; gap: 8px; color: var(--fg); }
/* The cover is sized by height so the whole card fits one screen. */
.card-cover { display: block; position: relative; color: inherit; justify-self: start; margin: 20px 0 20px; width: clamp(160px, 46%, 300px); aspect-ratio: 2 / 3; align-self: flex-start; overflow: visible; background: var(--ink-2); }
.card-cover img { border-radius: 2px; } /* sized by the card, not the screen height, so it grows with the card at 1920 (major 17) */
.card-cover img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease-out-quart); }
/* Chase, 2026-09-17: a cover does not grow on hover; the tear and the label are its hover. */
.card .h3 { margin-bottom: 10px; font-size: clamp(20px, 1.6vw, 26px); }
/* The price: after the summary on a card, after the name on the shelf (Chase, 2026-09-21). */
.price { font-size: 16px; letter-spacing: 0.04em; color: var(--fg); }
.card-price { margin-top: 14px; }
.extra-price-line { margin-top: 10px; }
.card-copy { color: var(--fg-2); text-wrap: pretty; font-size: 15px; line-height: 1.45; max-width: 32em; } /* about 66 characters a line at the widest (major 17) */
.card-more { display: none; }
.card-list { list-style: none; margin-top: 16px; font-size: 15px; }
.card-list li { padding: 7px 0; border-top: 1px solid var(--rule); }
.card-meta { color: var(--fg-3); align-self: end; padding-top: 16px; }
.card .btn { justify-self: start; align-self: start; margin-top: 14px; }
/* On ink (2026-09-16, Justin: less white): the cards and the buy band sit one step lighter than the ground, paper type, ink rules. */
.ground-ink .card, .ground-ink .shop-band { --fg: var(--paper); --fg-2: var(--t-ink-2); --fg-3: var(--t-ink-3); --rule: var(--rule-ink); --red-text: var(--primary-bright); background: var(--ink-3); }
.ground-ink .btn-tag, .ground-ink .chip { color: var(--fg-3); border-color: currentColor; }
/* The buy band: a fourth card across the row, same ground and padding as the three above. */
.shop-band { --fg: var(--ink); --fg-2: var(--t-paper-2); --fg-3: var(--t-paper-3); display: grid; grid-template-columns: auto 1fr auto; gap: 24px 48px; align-items: center; margin-top: 0; padding: 24px; background: var(--paper-bright); }
.shop-note { color: var(--fg-2); }
.shop-side { display: flex; flex-direction: column; align-items: flex-end; gap: 12px; }
.shop-when { font-size: 15px; }
.shop-lede { font-size: clamp(18px, 1.4vw, 24px); max-width: 30em; text-wrap: pretty; }

/* 03 · Show: their featured work. A sticky rail, three columns wide, and the episodes stacked at 16:10. */
.fw { display: grid; grid-template-columns: 3fr 9fr; gap: 64px; align-items: start; }
.fw > * { min-width: 0; }
.fw-rail { position: sticky; top: calc(16px + var(--head-h)); height: calc(100vh - 16px - var(--head-h)); }
.fw-rail-in { height: 100%; display: flex; flex-direction: column; justify-content: space-between; align-items: flex-start; padding: 32px 0; }
.fw-rail-in > * { flex-shrink: 0; } /* M13: a short window used to squeeze All episodes to 23 px */
.fw-rail-in.is-tight { padding: 0; } /* the script sets these when the rail cannot hold its contents: padding goes first */
.fw-rail-in.is-short .fw-index { display: none; } /* then the episode index */
.side-copy { color: var(--fg-2); max-width: 28em; margin-top: 32px; }
/* The episode index: an odometer counter and a track listing, the way the third book's contents page reads. Ours, not theirs. */
.fw-index { display: flex; flex-direction: column; gap: 20px; }
.fw-counter { display: flex; align-items: baseline; gap: 12px; font-family: var(--mono); line-height: 1; }
.fw-num { font-size: clamp(56px, 5.4vw, 88px); letter-spacing: 0.02em; color: var(--paper); min-width: 2ch; }
.fw-of { color: var(--fg-3); }
.fw-tracks { list-style: none; display: flex; flex-direction: column; padding-top: 12px; background: repeating-linear-gradient(90deg, var(--fg-2) 0 28px, transparent 28px 48px) top / 100% 2px no-repeat; }
.fw-track { position: relative; display: grid; grid-template-columns: 64px 1fr; gap: 10px; align-items: baseline; width: 100%; padding: 10px 0; background: none; border: 0; border-bottom: 1px solid var(--rule); font: inherit; text-align: left; color: var(--fg-3); cursor: pointer; transition: color 0.3s; }
.fw-track:hover, .fw-track.is-active { color: var(--paper); }
.fw-track-bolt { position: absolute; left: -22px; top: 50%; margin-top: -6px; width: 12px; height: 12px; background: var(--primary); opacity: 0; transform: scale(0); transition: opacity 0.3s, transform 0.4s var(--ease-out-back); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M19 3 L9 18 h6 l-2 11 10-16 h-6 z'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M19 3 L9 18 h6 l-2 11 10-16 h-6 z'/%3E%3C/svg%3E") center / contain no-repeat; }
.fw-track.is-active .fw-track-bolt { opacity: 1; transform: scale(1); }
.fw-track-k { font-size: 12px; }
.fw-track-t { font-size: 15px; }
.fw-list { display: flex; flex-direction: column; gap: 96px; }
.fw-media { display: block; position: relative; aspect-ratio: 16 / 10; overflow: hidden; background: var(--ink-2); }
.fw-media img { width: 100%; height: 100%; object-fit: cover; will-change: transform; }
/* The hover clip: a few silent seconds of the episode over its still. It arrives after the tear, so the strike reads first. */
.fw-media video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; pointer-events: none; }
.has-cursor-label .fw-media { cursor: none; } /* only while the script runs the label that stands in for the pointer (major 9). The book covers came out 2026-09-20: they stopped being links when the shop arrived, so there is no label to stand in for the pointer. */
/* The cursor label, their follower: a brand label that trails the pointer over an episode and reads View on YouTube. */
.cursor-label { position: fixed; left: 0; top: 0; z-index: 9995; border-radius: 2px; height: 42px; padding: 0 20px; background: var(--primary-deep); color: var(--on-primary); font-size: 14px; letter-spacing: 0.06em; white-space: nowrap; pointer-events: none; opacity: 0; will-change: transform; } /* centered on the pointer by the script (xPercent/yPercent), never by a CSS transform: GSAP owns this element's transform (review 2026-09-20, fix 7) */
/* Chase, 2026-09-14: an arrow pointing up and right after the label says the link leaves the site. Drawn on a pseudo-element so the script can rewrite the label's text without losing it. */
.cursor-label { display: inline-flex; align-items: center; gap: 10px; }
.cursor-label.no-arrow { gap: 0; } .cursor-label.no-arrow::after { display: none; } /* the up-right arrow is for outbound links; a cover glides within the page */ /* sized like .btn: 42px tall, 20px sides, 14px label (Chase, 2026-09-14) */
.cursor-label::after { content: ""; flex: none; width: 10px; height: 10px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 9.5 L9.5 2.5 M3.5 2.5 H9.5 V8.5' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='square'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 9.5 L9.5 2.5 M3.5 2.5 H9.5 V8.5' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='square'/%3E%3C/svg%3E") center / contain no-repeat; }
.fw-all .btn-label::after { content: ""; flex: none; width: 10px; height: 10px; margin-left: 10px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 9.5 L9.5 2.5 M3.5 2.5 H9.5 V8.5' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='square'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 9.5 L9.5 2.5 M3.5 2.5 H9.5 V8.5' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='square'/%3E%3C/svg%3E") center / contain no-repeat; }
.fw-cap { display: flex; justify-content: space-between; align-items: baseline; gap: 24px; margin-top: 20px; }
/* The episode thumbnail (Chase, 2026-09-17): over an episode row, the episode's own still rides the pointer on the label's trail and its clip
   plays over it. It sits above the pointer, and below it when the pointer is near the top of the window (the script flips it). */
.cursor-thumb { position: fixed; left: 0; top: 0; z-index: 9994; width: 240px; aspect-ratio: 16 / 9; margin-top: -22px; overflow: hidden; border-radius: 2px; background: var(--ink-2); box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55); pointer-events: none; opacity: 0; will-change: transform; }
.cursor-thumb.is-below { margin-top: 22px; }
.cursor-thumb img, .cursor-thumb video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.cursor-thumb video { opacity: 0; } /* the episode's clip plays over its still, the way the two big stills above do (Chase, 2026-09-17) */
.fw-meta { color: var(--fg-3); white-space: nowrap; }

/* 03 · Shows: two cards of equal weight, the book cards' anatomy (label, media, title, dateline, copy, list, button). */
.shows { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 56px; }
.show { --fg: var(--paper); --fg-2: var(--t-ink-2); --fg-3: var(--t-ink-3); --rule: var(--rule-ink); display: flex; flex-direction: column; align-items: flex-start; padding: 24px; background: var(--ink-3); border-radius: 2px; }
.show-media { width: 100%; margin: 20px 0 24px; aspect-ratio: 16 / 9; }
.show .h3 { margin-bottom: 8px; }
.show-date { color: var(--fg-3); font-size: 14px; }
.show-copy { color: var(--fg-2); margin-top: 14px; max-width: 34em; text-wrap: pretty; font-size: 15px; line-height: 1.45; }
.show-tracks { list-style: none; width: 100%; margin-top: 24px; padding-top: 12px; background: repeating-linear-gradient(90deg, var(--fg-2) 0 28px, transparent 28px 48px) top / 100% 2px no-repeat; }
.show-track { display: grid; grid-template-columns: 76px 1fr auto; gap: 12px; align-items: baseline; padding: 11px 0; border-bottom: 1px solid var(--rule); color: var(--fg); transition: color 0.3s; }
a.show-track:hover { color: var(--primary-bright); }
.show-track-k { color: var(--fg-3); font-size: 12px; }
.show-track-t { font-size: 15px; }
.show-track-v { color: var(--fg-3); font-size: 12px; text-align: right; white-space: nowrap; }
.show-track.is-held { color: var(--fg-2); }
.show-track-v.tag { padding: 3px 8px 3px 22px; }
.show-track-v.tag::before { left: 7px; width: 10px; height: 10px; }
.show .btn { margin-top: 24px; }

/* Table rows (their List grammar): hairlines; on desktop a square rides the viewport center and pushes the rows it passes */
/* The center line: Book 1's yellow dashes ticking by, in the page's own ink (Chase, 2026-09-14). */
.rows { position: relative; border-top: 0; padding-top: 12px; background: repeating-linear-gradient(90deg, var(--fg-2) 0 28px, transparent 28px 48px) top / 100% 2px no-repeat; }
.row { display: grid; grid-template-columns: 110px 1fr auto; gap: 24px; align-items: baseline; padding: 22px 0; border-bottom: 1px solid var(--rule); }
.row-k { color: var(--fg-3); }
.row-name { font-size: clamp(18px, 1.4vw, 24px); }
.row-v { color: var(--fg-3); text-align: right; }
.row-event, .row-buy { grid-template-columns: 110px 1fr auto; grid-template-areas: "k name v" "k sub v"; }
.row-event .row-k, .row-buy .row-k { grid-area: k; }
.row-event .row-name, .row-buy .row-name { grid-area: name; font-family: var(--mono); text-transform: uppercase; letter-spacing: 0.02em; font-size: clamp(16px, 1.3vw, 22px); }
.row-event .row-sub, .row-buy .row-sub { grid-area: sub; color: var(--fg-2); font-size: 15px; margin-top: 4px; }
.row-event .row-v { grid-area: v; align-self: center; }
.row-sub .row-line { display: block; } /* an event's facts, one to a line (2026-10-03) */
.row-sub .row-line + .row-line { margin-top: 2px; }
.row-sub .link { font-size: inherit; color: var(--fg); }
.row-buy .row-v { grid-area: v; align-self: baseline; }
.row-event.is-past .row-name { color: var(--fg-2); }
/* Event titles wrap: the decode's no-wrap rule pushed phones sideways. Lettera is monospaced, so the noise wraps the same as the text. */
.row-name.sc { display: block; white-space: normal; }
.row-name .sc-ghost, .row-name .sc-live { white-space: normal; }
.row-name .sc-live { right: 0; }
.odo { display: flex; flex-direction: column; line-height: 1; }
.odo b { font-weight: 400; font-size: clamp(22px, 1.9vw, 32px); color: var(--fg); }
.odo i { font-style: normal; margin-top: 4px; }
/* The stamps: slammed on as the row arrives (JS), and on hover the row's title decodes and the stamp fills in. */
.stamp { border: 1px solid var(--fg-3); padding: 6px 12px; border-radius: 2px; transform-origin: center; transition: background-color 0.2s steps(2), color 0.2s steps(2), border-color 0.2s steps(2); }
.row-event.is-past .stamp { border-style: dashed; } /* the first iteration's past stamps */
a.row:hover .stamp { background: var(--fg); color: var(--bg); border-color: var(--fg); }
.stamp-next { background: var(--primary-deep); color: var(--on-primary); border-color: var(--primary-deep); }
a.row:hover .stamp-next { background: var(--fg); border-color: var(--fg); }

/* 04 · Off the page. Sits above the footer, so the footer slides in underneath it instead of over its last row. */
#events { position: relative; z-index: 2; }
.events-rows { margin-top: 48px; }

/* Forms */
.form { display: flex; flex-direction: column; gap: 12px; max-width: 560px; }
.form-label { color: var(--fg-3); }
.form-row { display: flex; gap: 12px; flex-wrap: wrap; }
.input { flex: 1; min-width: 240px; height: 42px; border-radius: 2px; font: inherit; font-size: 16px; background: transparent; border: 1px solid var(--fg-3); color: var(--fg); padding: 0 14px; transition: border-color 0.3s; }
.input::placeholder { color: var(--fg-3); }
.input:focus { outline: 2px solid var(--primary); outline-offset: 1px; border-color: transparent; }
.form-note { color: var(--fg-3); margin-top: 6px; }
.list-note { margin-top: 12px; font-size: 13px; color: var(--t-ink-2); }
.list-note[hidden] { display: none; }
.input-paper { border-color: var(--t-ink-3); color: var(--paper); }

/* 05 · Footer: theirs, dark, full screen. Slides up from -20% and fades its content in with its own entry. Chase's composition
   2026-09-13: the headline and form, the ride at 21:9, then the nav large on the left and the logo on the right. */
.foot { position: relative; z-index: 1; overflow: hidden; min-height: 100svh; padding: 0; }
/* The slide-up starts 20% high, which only the script's scroll entry resolves; with no script the footer sits where it
   belongs (review 2026-09-20, fix 2). */
.js .foot { transform: translate3d(0, -20%, 0); will-change: transform; }
.foot-in { --foot-fade: 1; position: relative; background: var(--ink-2); /* one step lighter than the page, the shows chapter's tone, so the footer reads as its own sheet now that no chapter is paper (Chase, 2026-09-17) */ min-height: 100svh; display: flex; flex-direction: column; padding-top: calc(16px + var(--head-h) + 48px); padding-bottom: 48px; }
/* The entry fades the footer's content, never its ink. With no script the footer is simply there. */
.js .foot-in { --foot-fade: 0; }
.foot-in > * { opacity: var(--foot-fade); }
.foot-top { display: flex; flex-direction: column; align-items: flex-start; gap: 28px; }
.foot-h2 { max-width: 22ch; }
.foot-sub { max-width: 34em; }
.foot-form { max-width: 640px; width: 100%; margin-top: 4px; }
.foot-form .form-row { flex-wrap: nowrap; }
.foot-form .input { flex: 1 1 auto; min-width: 0; }
.foot-form .btn { flex: none; }
@media (max-width: 480px) { .foot-form .form-row { flex-wrap: wrap; } .foot-form .input { flex: 1 1 100%; } } /* M12: the field was 91 px wide at 320 */
.foot-ride { margin-top: 64px; }
.video-frame { position: relative; aspect-ratio: 21 / 9; overflow: hidden; background: var(--ink-2); }
.video-frame video { width: 100%; height: 100%; object-fit: cover; display: block; will-change: transform; }
.video-tag { position: absolute; left: 16px; bottom: 16px; padding: 6px 10px; background: rgba(10, 6, 5, 0.7); color: var(--t-ink-2); }
.foot-end { margin-top: auto; display: grid; grid-template-columns: 1fr auto; gap: 64px; align-items: center; padding-top: 64px; }
.foot-left { display: flex; flex-direction: column; gap: 48px; align-items: flex-start; }
.foot-nav { display: flex; flex-direction: column; gap: 16px; align-items: flex-start; font-family: var(--mono); text-transform: uppercase; font-size: clamp(40px, 4.6vw, 76px); line-height: 1.05; letter-spacing: 0.02em; }
.foot-nav a { color: var(--paper); transition: color 0.3s; }
.foot-nav a:hover { color: var(--primary-bright); }
.foot-social { display: flex; gap: 24px; flex-wrap: wrap; }
.foot-brand { display: flex; flex-direction: column; align-items: center; gap: 20px; }
.foot-logo { width: min(340px, 100%); height: auto; }
.foot-about { max-width: 44ch; margin-bottom: -8px; font-size: 14px; line-height: 1.55; color: var(--t-ink-2); text-align: center; }
.foot-copy { color: var(--t-ink-3); text-align: center; }

/* Reveal defaults (JS drives; hidden only when JS is on) */
.js [data-reveal] { opacity: 0; }

/* Touch has no hover label, so every still carries a standing tag. */
@media (hover: none) {
  .fw-media::after { content: "Watch on YouTube"; position: absolute; left: 12px; bottom: 12px; border-radius: 2px; padding: 6px 28px 6px 10px; background: var(--primary-deep) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 9.5 L9.5 2.5 M3.5 2.5 H9.5 V8.5' fill='none' stroke='%23FAF8F3' stroke-width='1.6' stroke-linecap='square'/%3E%3C/svg%3E") no-repeat right 10px center / 10px 10px; color: var(--on-primary); font-family: var(--mono); font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; line-height: 1.4; }
}

/* ===== Reduced motion ===== */
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal], .js [data-text] { opacity: 1; visibility: visible; }
  .hero-art-img { opacity: 1 !important; }
  .line-inner { opacity: 1 !important; }
  .rect { display: none; }
  .link::before, .link::after, .row, .work-media img, .idx::before, .menu-word-slot, .menu-glyph i { transition: none; }
  .loader { display: none; }
  .dial-tick { opacity: 1; }
  .head { transform: none; }
  .foot { transform: none; }
  .js .foot-in { --foot-fade: 1; }
  .video-frame video { transform: none !important; }
}

/* ===== Responsive ===== */
@media (max-width: 1100px) {
  .cards { grid-template-columns: 1fr 1fr; }
  .fw { grid-template-columns: 1fr 2fr; gap: 40px; }
}
@media (max-width: 1023px) {
  .js .head.header-hidden { --header-y: -200%; }
  .menu-inner { padding: 20px 24px 24px; }
  .menu-file { margin-bottom: 20px; font-size: 11px; }
  .menu-grid { grid-template-columns: 1fr; gap: 24px; }
  .menu-tiles { display: none; }
  .menu-clip { max-height: calc(100svh - 16px - var(--head-h) - 8px); overflow-y: auto; overscroll-behavior: contain; }
}
@media (max-width: 820px) {
  :root { --gutter: 20px; --chapter-pad: 80px; --head-h: 60px; }
  .wordmark { font-size: 12px; letter-spacing: 0.08em; }
  /* Chase, 2026-09-17: the odometer stays on a phone, the reels alone; the bar packs its three parts so they fit. */
  .odo-read { gap: 0; }
  .trip-label, .trip-unit { display: none; }
  .trip-digit { width: 1.4ch; height: 26px; line-height: 26px; font-size: 17px; }
  .trip-dot { font-size: 17px; line-height: 26px; }
  .head-bar { grid-template-columns: auto auto auto; justify-content: space-between; gap: 12px; }
  /* The site name gives up its single line on a phone so the reels and the menu square keep theirs: two balanced lines, Two Wheel over Time Traveler. */
  .wordmark { white-space: normal; text-wrap: balance; line-height: 1.3; }
  .head-right .btn .btn-label { padding: 0 12px; font-size: 12px; }
  .hero { padding-bottom: 32px; }
  .hero-art { width: 100%; opacity: 0.85; }
  .hero-art::after { background: linear-gradient(0deg, var(--ink) 18%, rgba(10,6,5,0.5) 55%, rgba(10,6,5,0.15) 100%); }
  .hero-copy { max-width: 100%; }
  .display { font-size: clamp(44px, 12vw, 72px); max-width: none; }
  .hero-proof { margin-top: 56px; gap: 10px; }
  .card { padding: 24px; }
  .shows { grid-template-columns: 1fr; }
  .hero-mark { width: 120px; margin-bottom: 24px; }
  .hero-side { display: none; }
  .hero-frame { inset: calc(16px + var(--head-h)) 12px 12px; }
  .ghost-num { font-size: 140px; top: 14px; }
  .hero-slip { margin-left: 0; }
  .fw { grid-template-columns: 1fr; gap: 40px; }
  .fw-rail { position: static; height: auto; }
  .fw-rail-in { padding: 0; gap: 24px; }
  .fw-index { display: none; }
  .fw-list { gap: 48px; }
  .fw-cap { flex-direction: column; align-items: flex-start; gap: 8px; }
  .fw-meta { white-space: normal; }
  .row { grid-template-columns: 72px 1fr auto; gap: 14px; padding: 18px 0; }
  .row-event, .row-buy { grid-template-columns: 72px 1fr; grid-template-areas: "k name" "k sub" "k v"; }
  .row-event .row-v, .row-buy .row-v { justify-self: start; margin-top: 10px; align-self: start; }
  .foot-in { padding-top: calc(16px + var(--head-h) + 32px); }
  .video-frame { aspect-ratio: 16 / 9; }
  .foot-ride { margin-top: 40px; }
  .foot-end { grid-template-columns: 1fr; gap: 40px; }
  .shop-band { grid-template-columns: 1fr; }
  .shop-side { align-items: flex-start; }
  .foot-brand { align-items: flex-start; }
  .foot-logo { width: min(300px, 100%); }
  .foot-copy, .foot-about { text-align: left; }
}
@media (max-width: 700px) {
  .cards { grid-template-columns: 1fr; }
  .card { grid-row: auto; grid-template-rows: none; grid-template-columns: 112px 1fr; column-gap: 16px; align-items: start; }
  .card > * { grid-column: 1 / -1; }
  .card-cover { grid-column: 1; grid-row: 1 / span 2; width: 112px; height: auto; margin: 0 0 16px; }
  .sheet { display: none; }
  .card .h3 { grid-column: 2; grid-row: 1; margin: 0; }
  .card-meta { grid-column: 2; grid-row: 2; align-self: start; padding-top: 8px; }
  /* Chase, 2026-09-14: on phones the summary clamps to three lines behind Read more so a card is not a screen and a half. */
  .js .card-copy.is-clamped { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
  .js .card-more { display: inline-block; margin-top: 12px; font-family: var(--mono); font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase; background: none; border: 0; padding: 0 0 3px; color: var(--fg); cursor: pointer; }
}
@media (max-width: 600px) {
  .head-right .btn { display: none; }
}

/* The shop's extras, to Chase's sketch 2026-09-20: one item fills one column of
   the same three-column grid the books use above, with the photograph on the
   left, the mark and what is in the package beside it, and the button sitting
   on the photograph's bottom edge. The columns and the gap are the books' own,
   so the two halves of the chapter line up. */
/* The shelf holds the small items, each one its own card like the books above
   (Chase, 2026-09-20). Same three columns, same gap, same 24px inset and the
   same ink, so a small card's picture starts and ends on the same line as the
   card over it. Everything else names the shelf and sits between the two rows,
   above the cards rather than inside one. */
.shelf { display: block; }
.shelf-head { margin: 56px 0 20px; color: var(--red-text); font-size: clamp(16px, 1.3vw, 20px); }
.extras { display: grid; grid-template-columns: repeat(4, 1fr); column-gap: 16px; row-gap: 16px; }
.extra { --fg: var(--paper); --fg-2: var(--t-ink-2); --fg-3: var(--t-ink-3); --rule: var(--rule-ink); display: grid; grid-template-columns: 46% 1fr; grid-template-rows: auto auto 1fr; column-gap: 20px; row-gap: 0; padding: 24px; background: var(--ink-3); border-radius: 2px; color: var(--fg); text-decoration: none; }
.extra-shot { display: block; overflow: hidden; border-radius: 2px; background: var(--ink-2); }
/* No hover on the picture. The button is the only thing in the shop that
   answers the pointer for now (Chase, 2026-09-20). */
.extra-shot img { display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; } /* square, as Justin's store photographs are (Chase, 2026-09-27) */
.extra-body { display: flex; flex-direction: column; align-items: flex-start; }
.extra-label { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--fg-3); }
.extra-name { margin-top: 12px; font-size: clamp(16px, 1.3vw, 20px); line-height: 1.4; text-wrap: pretty; }
.extra-add { margin-top: auto; }
/* How many, then Add to cart (Chase, 2026-09-21). The cart's own stepper stands on the button and is exactly as
   wide as it, on the card's or the shelf's own inks. It belongs to cart.js, so it shows only once that script is
   running. On the shelf the button keeps the photograph's bottom edge. */
.buy { display: inline-flex; flex-direction: column; align-items: stretch; gap: 8px; }
.card .buy { justify-self: start; align-self: start; margin-top: 14px; }
.card .buy .btn { margin-top: 0; }
/* The book that is not for sale yet has no stepper, so its tag stands at the foot of the row, level with the buttons. */
.card > .btn-tag { align-self: end; }
.buy .btn .btn-label { flex: 1; justify-content: center; }
.buy .btn .btn-label .sc-live { left: 50%; transform: translate(-50%, -50%); }
.qty { display: none; align-items: stretch; justify-content: space-between; height: 42px; border: 1px solid var(--rule); border-radius: 2px; color: var(--fg); }
.shop-ready .qty { display: flex; }
.qty-step { width: 36px; padding: 0; font: inherit; font-size: 16px; line-height: 1; color: var(--fg-2); background: none; border: 0; cursor: pointer; }
.qty-step:hover, .qty-step:focus-visible { color: var(--fg); }
.qty-step[disabled] { cursor: default; opacity: 0.4; }
/* Sold out (2026-10-03): the button grays and stops answering; the stepper goes, as there is nothing to count. */
.buy.is-sold .qty { display: none; }
.buy.is-sold .btn, .buy.is-sold .btn:hover { background: rgba(232, 228, 220, 0.12); color: var(--t-ink-2); pointer-events: none; cursor: default; }
.sold-tag[hidden] { display: none; }
.qty-n { flex: 1; display: inline-flex; align-items: center; justify-content: center; min-width: 28px; font-size: 14px; }
@media (max-width: 1023px) { .extras { grid-template-columns: 1fr 1fr; } }
/* Four across, each card the photograph over its label, name and price (Chase, 2026-09-27). Two across on a tablet and a phone. */
.extra { display: flex; flex-direction: column; }
.extra-shot { width: 100%; margin-bottom: 18px; }
.extra-name { margin-top: 10px; }
@media (max-width: 600px) { .extras { column-gap: 12px; row-gap: 12px; } .extra { padding: 14px; } .extra-shot { margin-bottom: 12px; } .extra-name { font-size: 15px; } }
/* The label that stands in for the pointer reads View over a shop item, as View on YouTube does over a still. */
.has-cursor-label [data-item-card] { cursor: none; }
/* The three books sit three across over the shelf, the same card at a larger size (Chase, 2026-09-27). */
.extras-books { grid-template-columns: repeat(4, 1fr); margin-top: 56px; } /* three books and the shirt (Chase, 2026-09-27) */
.extras-books + .shelf, .extras-books ~ * .shelf { margin-top: 0; }
/* With Everything else gone (Chase, 2026-09-27) the shelf follows the books' row at the cards' own 16px gap. */
.shelf .extras { margin-top: 16px; }
.extra-soon { cursor: default; }
/* A book not yet in the store shows its whole cover on the card's ink rather than cropped to the photographs' shape. */
.extra-cover { display: flex; align-items: center; justify-content: center; aspect-ratio: 1; background: var(--ink-2); }
.extra-cover img { width: auto; height: 100%; aspect-ratio: auto; object-fit: contain; }
@media (max-width: 1023px) { .extras-books { grid-template-columns: 1fr 1fr; } }
/* A sold book's photograph and title open its listing; both are buttons dressed as what they were. */
button.card-cover { padding: 0; border: 0; font: inherit; cursor: pointer; }
.card-title { padding: 0; font: inherit; color: inherit; text-align: left; text-transform: inherit; letter-spacing: inherit; background: none; border: 0; cursor: pointer; }
.card-title:hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }

/* A shelf card is the photograph, label, name and price, and the whole card opens
   the item (Chase, 2026-09-27). The name is the one button; its hit area is
   stretched over the card, so the keyboard has one stop per item. Under the
   pointer the name underlines. */
.extra { position: relative; cursor: pointer; }
button.extra-name { padding: 0; font: inherit; font-size: clamp(16px, 1.3vw, 20px); line-height: 1.4; color: inherit; text-align: left; background: none; border: 0; cursor: pointer; }
button.extra-name::after { content: ''; position: absolute; inset: 0; border-radius: 2px; }
/* View rides the pointer over the photograph only (Chase, 2026-09-27): the photograph sits above the card's click area and
   opens the item itself, so over the name and price it is the plain pointer. */
.extra .extra-shot[data-item-open] { position: relative; z-index: 1; }
button.extra-name:focus-visible { outline: none; }
button.extra-name:focus-visible::after { outline: 2px solid var(--primary); outline-offset: 3px; }
.extra:hover .extra-name { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }

/* The item, opened. The cart panel's ink, hairline and X; the card's 24px inset;
   the page's type. On a phone it takes the whole screen. */
.item { --fg: var(--paper); --fg-2: var(--t-ink-2); --fg-3: var(--t-ink-3); --rule: var(--rule-ink); width: min(1040px, calc(100vw - 32px)); max-width: none; max-height: calc(100dvh - 32px); margin: auto; padding: 0; overflow: auto; overscroll-behavior: contain; color: var(--fg); background: var(--ink-2); border: 1px solid var(--rule-ink); border-radius: 2px; box-shadow: 0 18px 60px rgba(0, 0, 0, 0.5); }
.item::backdrop { background: rgba(0, 0, 0, 0.6); }
.item-in { padding: 24px; }
.item-head { position: relative; display: flex; align-items: center; justify-content: space-between; min-height: 40px; padding-bottom: 12px; margin-bottom: 24px; border-bottom: 1px solid var(--rule-ink); }
.item-close { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; margin: -4px -12px 0 0; padding: 0; color: var(--t-ink-2); background: none; border: 0; cursor: pointer; }
.item-close:hover, .item-close:focus-visible { color: var(--paper); }
/* Opened by a tap or a click, the X holds its ring until a key is pressed; the keyboard always sees it (cart.js). */
[data-pointer-opened] .item-close:focus-visible { outline: none; }
/* The photograph full screen, over the open item (Chase, 2026-09-27). */
.zoom { --zoom-pad: clamp(56px, 8vw, 120px); --zoom-pad-x: clamp(16px, 8vw, 120px); width: 100vw; height: 100dvh; max-width: none; max-height: none; margin: 0; padding: var(--zoom-pad) var(--zoom-pad-x); border: 0; background: transparent; cursor: zoom-out; }
.zoom[open] { display: flex; align-items: center; justify-content: center; }
.zoom::backdrop { background: rgba(0, 0, 0, 0.8); } /* see-through, not solid (Chase, 2026-09-27) */
/* The X rides the photograph's or the video's top right corner, not the window's (Chase, 2026-09-27); the room around
   them is the pad, so neither comes near the window's edges. */
.zoom-stage { position: relative; display: block; }
.zoom img { display: block; max-width: calc(100vw - 2 * var(--zoom-pad-x)); max-height: calc(100dvh - 2 * var(--zoom-pad)); width: auto; height: auto; object-fit: contain; }
.zoom-close { position: absolute; bottom: 100%; right: -12px; margin: 0 0 4px; color: var(--paper); }
/* The teaser over the page, on a laptop (Chase, 2026-09-27). */
.video-pop-frame { width: min(1280px, calc(100vw - 2 * var(--zoom-pad-x)), calc((100dvh - 2 * var(--zoom-pad)) * 16 / 9)); aspect-ratio: 16 / 9; background: var(--ink-2); cursor: default; }
.video-pop-frame iframe { display: block; width: 100%; height: 100%; border: 0; }
.item-grid { display: grid; grid-template-columns: minmax(0, 46%) 1fr; column-gap: 32px; align-items: start; }
.item-shot { display: block; width: 100%; padding: 0; border: 0; overflow: hidden; border-radius: 2px; background: var(--ink-3); cursor: zoom-in; }
.item-shot img { display: block; width: 100%; height: auto; max-height: calc(100dvh - 240px); object-fit: contain; }
.item-thumbs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.item-thumb { width: 56px; padding: 0; background: var(--ink-3); border: 1px solid var(--rule-ink); border-radius: 2px; cursor: pointer; overflow: hidden; }
.item-thumb[aria-pressed="true"] { border-color: var(--paper); }
.item-thumb img { display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; }
.item-body { display: flex; flex-direction: column; align-items: flex-start; }
.item-name { font-size: clamp(20px, 1.7vw, 28px); font-weight: 400; line-height: 1.3; text-wrap: pretty; }
.item-price { margin-top: 10px; }
.item-copy { margin-top: 20px; max-width: 34em; color: var(--fg-2); font-size: 15px; line-height: 1.55; text-wrap: pretty; }
.item-copy > * + * { margin-top: 12px; }
/* Justin's headings in the site's typewriter face, as its other small heads are; bold at Geist's 500, the heaviest
   weight the page loads, so nothing is faked. */
.item-copy h4 { margin-top: 24px; font-family: var(--mono); font-size: 14px; font-weight: 400; font-synthesis: none; letter-spacing: 0.06em; text-transform: uppercase; color: var(--fg); }
.item-copy h4 strong { font-weight: 400; }
.item-copy > h4:first-child { margin-top: 0; }
.item-copy strong { font-weight: 500; color: var(--fg); }
.item-copy ul, .item-copy ol { padding-left: 1.2em; }
.item-copy li + li { margin-top: 6px; }
.item-copy a { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; }
.item-sizes { margin: 24px 0 0; padding: 0; border: 0; min-width: 0; }
.item-sizes-label { margin-bottom: 10px; padding: 0; font-size: 13px; color: var(--fg-3); }
.item-size-row { display: flex; flex-wrap: wrap; gap: 8px; }
.item-size { position: relative; display: inline-flex; }
.item-size input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.item-size span { display: inline-flex; align-items: center; justify-content: center; min-width: 42px; height: 42px; padding: 0 12px; font-size: 14px; color: var(--fg); border: 1px solid var(--rule); border-radius: 2px; pointer-events: none; }
.item-size input:hover + span { border-color: var(--fg-2); }
.item-size input:checked + span { color: var(--ink); background: var(--paper); border-color: var(--paper); }
.item-size input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 3px; }
.item-size input:disabled { cursor: default; }
.item-size input:disabled + span { color: var(--fg-3); text-decoration: line-through; }
.item-size-ask { margin-top: 10px; font-size: 13px; color: var(--primary-bright); }
.item-size-ask[hidden] { display: none; }
/* Add to cart, Shop's button and More payment options share one width, as the cart panel's do. */
.item-actions { display: flex; flex-direction: column; width: min(100%, 360px); margin-top: 28px; }
.item-actions .buy { display: flex; }
.item-more { margin-top: 16px; align-self: center; text-decoration: none; }
.item-more[hidden] { display: none; }
/* On a computer the modal holds still at the window's height and only the description scrolls, so the photograph,
   the sizes and the buttons stay in view however long Justin's words run (Chase, 2026-09-27). */
@media (min-width: 701px) {
  .item[open] { display: flex; flex-direction: column; overflow: hidden; }
  .item-in { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .item-grid { flex: 1 1 auto; min-height: 0; grid-template-rows: minmax(0, 1fr); }
  .item-body { height: 100%; min-height: 0; }
  .item-copy { flex: 0 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-right: 12px; }
  .item-sizes, .item-actions { flex: none; }
  /* Where the words run on below, they fade out rather than stop mid-line; the fade goes once the end is reached. */
  .item-copy.is-more { -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 48px), transparent); mask-image: linear-gradient(to bottom, #000 calc(100% - 48px), transparent); }
}
@media (max-width: 700px) {
  .item { width: 100vw; max-height: none; height: 100dvh; border: 0; border-radius: 0; }
  .item-in { padding: 16px var(--gutter) 32px; }
  .item-grid { grid-template-columns: 1fr; row-gap: 24px; }
  .item-shot img { max-height: 70dvh; }
}

/* The cart. An icon alone where the Shop button was, always there, with the count
   on its corner once there is one (Chase, 2026-09-21). Outlined at the Menu
   square's size, so the Menu stays the one filled block in the bar. The icon is
   small enough that the odometer keeps its place on a phone; only under 360 wide
   do the reels give way. */
.cart-btn { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; color: inherit; border-radius: 2px; box-shadow: inset 0 0 0 1px currentColor; }
.cart-glyph { display: block; }
.cart-count { position: absolute; top: -7px; right: -7px; display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 4px; font-size: 11px; line-height: 1; letter-spacing: 0; color: var(--on-primary); background: var(--primary-deep); border-radius: 2px; }
.cart-count[hidden] { display: none; }
@media (max-width: 820px) {
  /* In a narrow window on a computer the hover effect has the site name in its
     one-line copies, which kept it from folding onto two lines. */
  .wordmark .sc-ghost, .wordmark .sc-live { white-space: normal; }
  .wordmark .sc-live { right: 0; }
}
@media (max-width: 359px) { .head-center { display: none; } }

/* The order, opened from the bar. A reader takes things out of it here rather
   than being sent to Shopify to do it (Chase, 2026-09-20). It borrows the head
   bar's own ink and hairlines, and sits under the bar rather than covering the
   page, because the menu already owns the full-screen panel. */
.order[hidden] { display: none; }
.order { position: absolute; top: calc(var(--head-h) + 8px); right: 16px; z-index: 60; width: min(420px, calc(100vw - 32px)); background: var(--ink-2); border: 1px solid var(--rule-ink); border-radius: 2px; box-shadow: 0 18px 60px rgba(0, 0, 0, 0.5); }
.order-in { padding: 20px; color: var(--paper); }
.order-head { display: flex; align-items: baseline; justify-content: space-between; padding-bottom: 12px; border-bottom: 1px solid var(--rule-ink); color: var(--t-ink-3); }
/* The X is the Menu square's own open mark, and sits in the same column: a 40px box whose right edge is the Menu
   square's right edge, wherever the bar has put it (the bar draws in by 16px once the page has scrolled). */
.head { --bar-pad: 0px; }
.head.is-scrolled { --bar-pad: 16px; }
.order { --order-right: 16px; }
.order-head { position: relative; min-height: 40px; align-items: center; }
.order-close { position: absolute; top: 50%; right: calc(var(--gutter) + var(--bar-pad) - var(--order-right) - 21px); display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; margin-top: -26px; padding: 0; color: var(--t-ink-2); background: none; border: 0; cursor: pointer; transition: right 0.5s ease-out; }
.order-close:hover, .order-close:focus-visible { color: var(--paper); }
.order-lines { margin: 0; padding: 0; list-style: none; }
.order-line { display: grid; grid-template-columns: 56px 1fr auto; gap: 4px 14px; align-items: start; padding: 16px 0; border-bottom: 1px solid var(--rule-ink); }
.order-shot { grid-row: span 2; }
.order-shot img { display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; border-radius: 2px; }
.order-name { font-size: 15px; line-height: 1.35; text-wrap: pretty; }
.order-price { text-align: right; color: var(--t-ink-2); }
.order-foot { grid-column: 2 / -1; display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 10px; }
/* How many, and a way to say two without clicking Add twice. */
.order-qty { display: inline-flex; align-items: center; border: 1px solid var(--rule-ink); border-radius: 2px; }
.order-step { width: 26px; height: 24px; padding: 0; font: inherit; font-size: 14px; line-height: 1; color: var(--t-ink-2); background: none; border: 0; cursor: pointer; }
.order-step:hover, .order-step:focus-visible { color: var(--paper); }
.order-qty-n { min-width: 22px; text-align: center; font-size: 13px; color: var(--paper); }
/* The trash can stands in the same column as the X and the Menu square above it: its box is 8px narrower than
   theirs, so it sits 4px further in. */
.order-drop { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; margin-right: calc(var(--gutter) + var(--bar-pad) - var(--order-right) - 17px); transition: margin-right 0.5s ease-out; padding: 0; color: var(--t-ink-2); background: none; border: 0; cursor: pointer; }
.order-drop:hover, .order-drop:focus-visible { color: var(--primary-bright); }
.order-drop[disabled] { cursor: default; opacity: 0.6; }
.order-empty[hidden], .order-sum[hidden], .order-go[hidden], .order-note[hidden] { display: none; }
.order-none { padding: 20px 0; color: var(--t-ink-2); }
.order-sum { display: flex; align-items: baseline; justify-content: space-between; padding: 16px 0; color: var(--t-ink-2); }
/* The only full-width button on the site. Its label is an inline block sized to
   its words, so it has to be told to fill and center, and the copy the text
   effect lays over the top has to be centered with it. */
.order-go { width: 100%; }
.order-go .btn-label { flex: 1; justify-content: center; }
.order-go .btn-label .sc-live { left: 50%; transform: translate(-50%, -50%); }
.order-shop-pay { margin-top: 8px; --shop-pay-button-width: 100%; --shop-pay-button-height: 42px; --shop-pay-button-border-radius: 2px; }
.order-shop-pay[hidden] { display: none; }
.order-note { margin-top: 12px; font-size: 12px; color: var(--t-ink-3); }
/* What shows the moment something is added. The same panel in the same place, so
   the cart is one thing a reader learns once. */
.added:focus { outline: none; }
.added .order-head { align-items: center; }
.added-head { display: inline-flex; align-items: center; gap: 10px; color: var(--paper); }
.added-line { align-items: center; grid-template-columns: 56px 1fr; border-bottom: 0; }
.added-line .order-shot { grid-row: auto; }
.added-line .order-shot:empty { display: none; }
.added-what { display: flex; flex-direction: column; gap: 6px; }
.added-qty { font-size: 12px; color: var(--t-ink-2); }
.added-qty[hidden] { display: none; }
.added .order-go + .order-go { margin-top: 8px; }
.added-keep { display: block; margin: 16px auto 0; padding: 0 0 3px; font: inherit; font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--t-ink-2); background: none; border: 0; border-bottom: 1px solid currentColor; cursor: pointer; }
.added-keep:hover, .added-keep:focus-visible { color: var(--paper); }
@media (max-width: 600px) {
  /* 14px: the bar's buttons end 6px below the bar's own height on a phone, so this
     leaves the same 8px under the cart icon that the panel has on a computer. */
  .order { --order-right: 8px; top: calc(var(--head-h) + 14px); right: 8px; left: 8px; width: auto; }
}
/* A chapter's heading block takes focus when a chapter link is followed, so the keyboard comes along; it is not a control,
   so it shows no ring (review 2026-09-20, fix 6). */
[data-focus-target]:focus { outline: none; }
