/* Jack Spareribs -- design tokens and layout
   Palette v3, 2026-09-01, after Ace called v2 the generic AI look (warm
   cream, terracotta, serif). True black instead of brown-black, one vivid
   flag-red doing the work, gold used sparingly and bright, off-white text
   instead of ivory. Display face is IM Fell English, Ace's own pick off a
   real side-by-side (Rye read Western, not pirate). Old ship's-log
   letterforms, not a literary serif, not a literal "pirate font" clip-art
   face.
   Full-bleed photo scenes instead of boxed image cards, so the page moves
   like a journey instead of a stacked slideshow. Body: Public Sans.
   Utility/labels: Oswald. */

:root {
  --ink: #0a0a0c;
  --ink-2: #16171a;
  --text: #f0f0ee;
  --red: #d7391d;
  --red-deep: #b82d14;
  --gold: #f2b705;
  --fog: #9a9d9f;
  --line: rgba(240, 240, 238, 0.14);

  --bg: var(--ink);
  --panel: var(--ink-2);
  --text-dim: var(--fog);
  --accent: var(--red);
  --accent-strong: var(--gold);
  --accent-deep: var(--red-deep);
  --on-accent: var(--ink);
  --border: var(--line);

  --font-display: "IM Fell English", Georgia, "Times New Roman", serif;
  --font-body: "Public Sans", -apple-system, "Segoe UI", sans-serif;
  --font-label: "Oswald", "Arial Narrow", sans-serif;

  --measure: 62ch;
  --radius: 3px;
}

* { box-sizing: border-box; }

html {
  color-scheme: dark;
  /* Disables mobile Chrome/Safari's automatic text-inflation on narrow
     text columns (a real, separate mechanism from any rem/vw sizing,
     invisible to desktop devtools emulation since it doesn't apply
     there). Likely the actual cause of headline/CTA text reading larger
     on a real phone than any emulated or desktop test showed all day. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

a { color: inherit; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: 0.01em;
  text-wrap: balance;
  margin: 0;
}

p { margin: 0 0 1em; max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

.eyebrow {
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.78rem;
  color: var(--accent-strong);
  font-weight: 500;
}

.container {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 clamp(1.25rem, 4vw, 3rem);
}

/* ---------- Skip link / focus ---------- */

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: var(--ink);
  padding: 0.75rem 1.25rem;
  z-index: 100;
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.skip-link:focus { left: 1rem; top: 1rem; }

:focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: 3px;
}

/* ---------- Top bar ---------- */

.topbar {
  position: relative;
  z-index: 10;
  padding-top: 1.1rem;
  padding-bottom: 1.1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
  background: var(--ink);
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  text-decoration: none;
}
.wordmark img {
  height: 64px;
  width: auto;
  filter: invert(1);
}
.wordmark-text {
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--text);
  white-space: nowrap;
}
.footer-brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.footer-brand img {
  height: 52px;
  width: auto;
  display: block;
  filter: invert(1);
}
.footer-brand span {
  font-family: var(--font-display);
  font-size: 16.8px;
  color: var(--text);
}

/* Real logo, used big and low-opacity as an actual brand element instead of
   hiding it at illegible sizes. Ace, 2026-09-04: "I actually have a fucking
   logo why not use it for branding on my own site." */
.brand-watermark {
  position: absolute;
  top: 50%;
  right: -4%;
  transform: translateY(-50%);
  width: clamp(16rem, 34vw, 26rem);
  height: auto;
  filter: invert(1);
  opacity: 0.06;
  pointer-events: none;
  z-index: 0;
}

.topbar-phone {
  font-family: var(--font-label);
  letter-spacing: 0.04em;
  font-size: 0.9rem;
  text-decoration: none;
  color: var(--text-dim);
  border: 1px solid var(--border);
  padding: 0.45rem 0.9rem;
  border-radius: var(--radius);
  transition: border-color 0.15s ease, color 0.15s ease;
}
.topbar-phone:hover, .topbar-phone:focus-visible { border-color: var(--accent); color: var(--accent-strong); }

/* 2026-09-24: at phone width the wordmark text and the About/phone buttons
   overlapped by ~64px and the number broke over three lines. Let the button
   group drop to its own row only when it truly does not fit. Desktop unchanged. */
.topbar-phone { white-space: nowrap; }
/* No breakpoint: the group wraps only at the exact width it would collide. */
.topbar { flex-wrap: wrap; row-gap: 0.75rem; column-gap: 1rem; }

/* ---------- Hero ---------- */

/* Hero rebuilt 2026-09-03 from the taller PSD (jack-ship-monkey-layers2.psd,
   6080x4500 vs the original 6080x3072): one continuous art band, no separate
   text block above it. Logo, headline, sub and CTA sit inside a black-to-
   clear fade at the top of the photo itself, the way the old single-photo
   hero worked, adapted to the three-cutout mechanic (ship, Jack, Maynard)
   so each piece can still be positioned independently. No scroll mechanic,
   static positioning only, per Ace directly.
   Character widths use clamp() directly instead of width% + min-width: the
   two-system fight between those (percentage shrinking past a fixed-px
   floor) is what caused Jack and Maynard to stop shrinking and grow into
   each other and the figurehead at phone widths. clamp() alone is
   continuous by construction, so there is no floor to fall off of. */
.hero { background: var(--ink); }

.hero-art {
  position: relative;
  width: 100%;
  /* FIXED height, not min-height, as of 2026-09-09 late session. Every
     version of this box that sized itself off its own content (min-height
     + flex, before that a plain flex column) had the same underlying bug:
     .hero-art-ship/-jack/-maynard are all position:absolute against THIS
     box, so anything that changed this box's height (the headline wrapping
     a different number of lines) moved all three of them, even though
     they're visually three independent image layers. Ace's real phone has
     wrapped this same headline to 7 lines one day and 8 the next, against
     4-5 in every emulator/devtools test available here, a gap never
     explained. Chasing that gap by tuning font-size or box height was the
     loop: every fix here changed a number that the characters' position
     was still, indirectly, a function of.
     Fixed height removes the dependency completely. Ship/Jack/Maynard's
     absolute positions are now a function of ONLY this fixed number, never
     of text length, on any device, measured or not. .hero-overlay (the
     text) goes back to being absolutely positioned on top instead of
     stacked in normal flow above the characters, with its own max-height
     capped against this same fixed number (see .hero-overlay below) so it
     is mathematically impossible for it to grow into the character band,
     regardless of how many lines any device ever wraps this headline to.
     If text needs more room than its cap allows, it scrolls inside its own
     box instead of pushing or overlapping anything, a real but rare
     degradation, not a break.
     820px -> 700px below 500px width, 2026-09-09 later same session: 820px
     was sized against the phone's full nominal viewport height (a Pixel 8
     reports 915px), which is never what's actually visible on load. Real
     mobile Chrome keeps the URL bar and gesture bar on screen until the
     user scrolls, eating a real chunk of that height first, confirmed by
     Ace's own screenshot of his actual phone: Jack and Maynard cropped
     down to their eyebrows, not because anything was positioned wrong,
     but because the box itself was taller than the room actually on
     screen. 700px leaves real margin under a realistic ~750-780px usable
     height instead of assuming the full 915px is available.
     700px -> 740px, same night, right after deploy: tried growing the box
     to fit the real 8-line headline under the text cap. Wrong lever: it
     also pushed Jack/Maynard's floor (they're anchored to this box's own
     bottom) back toward the real phone viewport edge, confirmed by Ace's
     own live screenshot right after deploying it, cropped again, the
     exact problem 820px->700px already fixed once. Reverted to 700px,
     proven safe for the characters both times. The actual fix for the
     CTA is shrinking the real long-wrap TEXT instead (see .hero h1's
     narrow-width font-size below), not growing the box that both the
     text and the characters have to share. */
  height: 700px;
  overflow: hidden;
  background: var(--ink);
  --hero-reserve: 440px;
}

@media (max-width: 499px) {
  /* Real phones only. 280px -> 250px: measured Ace's actual reported
     8-line wrap directly (forced via max-width in devtools to reproduce
     the real line count, not guessed) at exactly 454px content height.
     Against the 460px cap that 280px reserve gave, that was only 6px of
     margin, too thin given how much this exact device has drifted from
     every tool here tonight. 250px keeps the text a 490px cap (36px of
     real margin over the measured 8-line case) while staying a real 20px
     above the character clearance need (~230px, Jack, the larger of the
     two), checked by calculation, not assumed safe. */
  .hero-art { --hero-reserve: 250px; }
}

@media (min-width: 500px) {
  /* Laptops/tablets: capped to fit a typical landscape window, see the
     comment above. */
  .hero-art { height: 760px; }
}

@media (min-width: 700px) {
  /* See .hero-overlay's comment: narrowed once Jack/Maynard start growing
     via vw here, because the headline's own text needs more room at this
     range's larger font sizes than it needed the reserved-zone to shrink
     to protect them. */
  .hero-art { --hero-reserve: 350px; }
}

.hero-art-ship {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Below ~930px, slide the crop left across the source image (which
     reads on screen as the ship sliding right) so the figurehead tracks
     into the shrinking gap between Jack and Maynard instead of getting
     covered by them as they grow. Continuous, not a breakpoint snap.
     min(100vw, 490px) freezes this at its ~490px value for anything
     wider: 2026-09-08 night, the formula was only swept/verified up to
     490px, and left uncapped it kept drifting back toward center all
     the way to 930px, which slides Maynard's puppet face-first into the
     figurehead by the time you reach tablet/desktop widths. */
  /* No transform here: this box is already filled exactly by object-fit
     cover + inset:0. A translateY on top of that (25.3px, removed
     2026-09-08) shifts the image off its own box, exposing the box's
     own black background as a bar along the edge it moves away from. */
  object-position: clamp(28%, calc(50% - (930px - min(100vw, 490px)) * 0.26), 50%) 68%;
}

.hero-art-jack,
.hero-art-maynard {
  position: absolute;
  bottom: 0;
  height: auto;
  max-height: 90%;
}

.hero-art-jack {
  /* Second pass, 2026-09-09, per Ace's re-marked reference: 412px
     confirmed fine as-is (floor untouched, 270px). 700px untouched too,
     he didn't circle Jack bigger there. 960px+ is where he circled Jack
     bigger, so only the growth rate past that point changes: 28.1vw ->
     32.2vw. Ceiling raised 360px -> 370px, the most room available
     before the 1366px text-reserve clearance (350px there) starts
     getting eaten, checked by calculation and then by looking, same
     constraint as the first pass. right:0 unchanged. */
  /* Third pass: measured, not just eyeballed, that Jack was smaller and
     lower at 960px than 1366px, because 32.2vw hadn't reached the 370px
     ceiling until ~1149px width, real numbers: 309px wide/top 492px at
     960px vs 370px wide/top 430px at 1366px. Steepened so the ceiling is
     reached at ~960px instead: 32.2vw -> 38.5vw. Ceiling raised 370px ->
     380px too (per "even more could be showing" at 1366px), the max that
     still clears the 1366px text-reserve limit with real margin. */
  width: clamp(270px, 38.5vw, 380px);
  aspect-ratio: 1600 / 1625;
  /* Was a clamp() formula sliding right to -40px at narrow widths, which
     put Jack's right edge 40px past the actual screen edge below ~451px,
     cropping into his face, not just background (measured via
     getBoundingClientRect, not by eye). Jack must stay fully on screen at
     every width, per Ace directly, ranked above tight figurehead
     clearance, so pinned flush to the edge instead. */
  right: 0;
  bottom: -6%;
}

.hero-art-maynard {
  /* Second pass, 2026-09-09, per Ace's re-marked reference (fuchsia
     circles this time, not just blue): 412px confirmed fine, floor
     untouched at 200px. Everywhere else he's still marked much bigger,
     "head as big as mine," and marked the figurehead itself in fuchsia
     as a hard exclusion zone, so growth needs real headroom this pass,
     not the 290px ceiling from the first one. 24vw -> 34vw, 290px ->
     380px ceiling.
     Position rebuilt again, simpler and more robust than the first
     pass's two-part rule (a flat right-edge lock plus a separate ramp
     for 700px+, which needed re-deriving by hand every time the size
     changed, exactly the fragility that caused this pass to be needed
     at all): `left` is now always exactly -50% of his own width
     (calc(-0.5 * var(--maynard-w))), one formula, no breakpoint, no
     ramp. At 412px this resolves to exactly -100px, matching Ace's own
     already-approved narrow position byte for byte, not a coincidence,
     the ratio was chosen backward from that confirmed-good value. His
     right edge is now 50% of his own width from the left edge at every
     size, so a bigger Maynard's right edge moves right somewhat (as
     intended, matching the bigger/closer read Ace asked for) but by a
     bounded, predictable fraction of his own size, not by a value that
     can drift independently of it. */
  /* Third pass: same fix as Jack, measured not eyeballed. 34vw hadn't
     reached the 380px ceiling until ~1118px width, which is why he read
     as "pretty much only his head" at 960px (301px tall there against
     350px at 1366px). Steepened to 40vw so the ceiling lands at ~950px.
     Ceiling raised 380px -> 420px too, per "even more could be showing"
     at 1366px: his bottom sits further down than Jack's (-12% vs -6%,
     see below), which leaves real extra headroom under the same 1366px
     text-reserve limit, checked by calculation (up to ~478px would still
     clear it) before picking 420px, a real increase with margin to
     spare, not the max possible. */
  --maynard-w: clamp(200px, 40vw, 420px);
  width: var(--maynard-w);
  aspect-ratio: 1600 / 1474;
  /* -0.5 -> -0.6, this pass: Ace's real phone showed his hand and
     Maynard's paw close enough to read as touching, a real device gap
     this session never explained (same category as the headline-wrap
     gap). Can't fix the unexplained cause in the time left, so building
     in real margin instead: 20% more leftward shift at every width,
     e.g. 100px -> 120px at the 412px floor, gap to Jack's hand grows
     from 42px to 62px measured. Defensive buffer against a gap that's
     real but not understood, not a guess that it'll be enough. */
  left: calc(-0.6 * var(--maynard-w));
  /* -2% unchanged at 412px, matches Ace's own "fine as-is" call there.
     Overridden wider, see the 700px+ rule below. */
  bottom: -2%;
}

@media (min-width: 700px) {
  /* Ace's "no floating, no showing under his butt" fuchsia mark was on
     the 1366px shot specifically; scoped to 700px+ generally rather than
     just that one width, since it's the same mechanism (he grows taller
     as his width grows past the 412px floor) and 412px itself was
     confirmed fine and left untouched, see the base rule above.
     A flat -12% here would have snapped hard at exactly 700px (-2% is
     -15.2px against the 760px box, -12% is -91.2px, a 76px jump), the
     same bug class fixed twice already tonight for a different property.
     Ramped in px instead (bottom stays % in the base rule since .hero-art
     is a fixed height here, so a px ramp resolves identically): linear
     from -15.2px at 700px width to -91.2px at 960px width, then clamp()
     holds flat past 960px. */
  .hero-art-maynard {
    bottom: clamp(-91.2px, calc(-15.2px - (100vw - 700px) * 0.2923), -15.2px);
  }
}

/* Jack's width-driven growth (see .hero-art-jack, clamp with a 960px
   crossover) is the only thing that changes for either character above
   700px now. Maynard's horizontal position has no breakpoint at all,
   see his own comment: the -50%-of-own-width calc() formula holds at
   every width without a separate rule for this range. */

/* Dark vignette along the bottom of the whole art band, so the frame
   itself reads as a deliberate edge rather than the photo just stopping. */
.hero-art::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent 82%, var(--ink) 100%);
}

/* Slow fade from black at the top down to clear, using the real extra sky
   the taller source photo has, not a short band. Text and logo live in
   this zone. */
.hero-fade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to bottom,
    rgba(10,10,12,0.6) 0%,
    rgba(10,10,12,0.48) 20%,
    rgba(10,10,12,0.22) 40%,
    rgba(10,10,12,0) 58%);
}

/* Logo moved into the open sky beside the crow's nest, top-right, big
   enough to actually read, phone stacked underneath it. Both scale with
   the viewport instead of a breakpoint, so the logo grows continuously
   into that space rather than jumping sizes, including running up against
   the crow's nest itself at the narrowest widths, per Ace directly. */
.hero-brand-corner {
  position: absolute;
  top: clamp(24px, 4vw, 48px);
  right: clamp(12px, 2.5vw, 24px);
  z-index: 6;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 9.6px;
}

.hero-logo {
  height: clamp(96px, 19vw, 216px);
  width: auto;
}

.hero-phone {
  font-family: var(--font-label);
  letter-spacing: 0.04em;
  font-size: clamp(11.5px, 2vw, 13.6px);
  text-decoration: none;
  color: var(--text);
  border: 1px solid rgba(240,240,238, 0.4);
  padding: 5.6px 11.2px;
  border-radius: var(--radius);
  background: rgba(10,10,12,0.35);
  white-space: nowrap;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.hero-phone:hover, .hero-phone:focus-visible { border-color: var(--accent); color: var(--accent-strong); }

.hero-overlay {
  /* Absolutely positioned over the fixed-height .hero-art again (was
     normal-flow flex 2026-09-09 earlier session; reverted, see .hero-art's
     comment). z-index puts it above the ship/vignette layers. */
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 5;
  padding: clamp(24px, 4vw, 48px);
  padding-bottom: 0;
  /* Keeps the headline clear of the logo/phone stack in the opposite
     corner at narrow widths, where the two would otherwise collide. */
  padding-right: clamp(140px, 24vw, 224px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* The actual fix: this box's own height is capped against .hero-art's
     now-fixed height, leaving a hard reserved zone at the bottom for
     Jack/Maynard/the figurehead (--hero-reserve, set below and narrowed
     at 700px+). Because .hero-art no longer changes size, this clearance
     is a real, permanent guarantee, not a number that happened to work at
     the widths last tested. If the real device wraps the headline to 8
     lines, 12 lines, anything: the text scrolls inside this box instead
     of ever reaching the reserved zone.
     --hero-reserve is 440px below 700px width (real measured character
     clearance needed there is ~170px, so this has a wide safety margin)
     and 350px at 700px+ (real clearance needed there tops out ~267px at
     1366px, so still a real margin, just not 440's). It has to shrink at
     wide widths because the headline's own font grows via vw there
     (up to 57.6px) while its column doesn't grow as fast, so the natural
     3-5 wrapped lines need more room than 440px reservation left available;
     verified 350px is enough headroom for the CTA to render fully in view,
     not just clear of overlap, at 700/960/1366px. */
  max-height: calc(100% - var(--hero-reserve, 440px));
  overflow-y: auto;
}

.hero h1 {
  font-size: clamp(32px, 4.6vw, 57.6px);
  line-height: 1.08;
  /* Was a flat 20ch, then a 20ch/32ch jump at exactly 700px (2026-09-09):
     both were snap points on a slow resize, the exact bug class Ace and
     the Dude flagged after the width-jump fix on Jack/Maynard. clamp()
     holds 20ch until 60vw naturally grows past it (~943px width), scales
     continuously from there, then holds flat again at 32ch (~1508px
     width, comfortably past every width tested), no jump anywhere in
     between. */
  max-width: clamp(20ch, 60vw, 32ch);
  color: var(--text);
  text-shadow: 0 2px 20px rgba(0,0,0,0.85), 0 1px 4px rgba(0,0,0,0.9);
}

@media (max-width: 499px) {
  /* Real phones only. Ace's real device wraps this headline to 8 lines
     at the 32px floor above (confirmed directly tonight, not guessed).
     8 lines at 32px needs 454px of content, more than this box can give
     without either shrinking the text or growing the box; growing the
     box was tried and reverted, see .hero-art's comment, it pushed
     Jack/Maynard back toward the real viewport edge. Shrinking the text
     is the lever that doesn't cost the characters anything: 26px keeps 8
     lines at 224.64px instead of 276.48px, dropping total content to
     ~388px, a real ~62px margin under the 450px cap this box's 700px
     height and 250px reserve actually leave, not a razor's edge. */
  .hero h1 { font-size: 26px; }
}

.hero-sub {
  margin-top: clamp(6.4px, 2vw, 17.6px);
  max-width: 48ch;
  font-size: 16.8px;
  color: rgba(240,240,238, 0.9);
  line-height: 1.3;
  text-shadow: 0 1px 12px rgba(0,0,0,0.85), 0 1px 3px rgba(0,0,0,0.9);
}

.hero-cta-row {
  margin-top: clamp(9.6px, 3vw, 25.6px);
  display: flex;
  flex-wrap: wrap;
  gap: 14.4px;
}

.hero-cta-row .btn-primary {
  box-shadow: 0 6px 20px rgba(0,0,0,0.5);
}

.btn {
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.85rem;
  font-weight: 500;
  text-decoration: none;
  padding: 0.85rem 1.6rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  display: inline-block;
  transition: transform 0.12s ease, background 0.15s ease, border-color 0.15s ease;
}

.btn-primary {
  background: var(--accent);
  color: var(--ink);
}
.btn-primary:hover, .btn-primary:focus-visible { background: var(--accent-strong); transform: translateY(-1px); }

.btn-ghost {
  border-color: rgba(240,240,238, 0.4);
  color: var(--text);
  background: transparent;
}
.btn-ghost:hover, .btn-ghost:focus-visible { border-color: var(--accent-strong); color: var(--accent-strong); }

/* ---------- Doors: sort by who's booking ---------- */

.doors {
  padding: clamp(3rem, 7vw, 5rem) 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background: var(--panel);
}

.doors-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  margin-top: 1.75rem;
}

@media (min-width: 760px) {
  .doors-grid { grid-template-columns: repeat(2, 1fr); }
}

.door {
  display: block;
  background: var(--ink);
  border: 1px solid var(--border);
  border-top: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: 1.6rem;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease, transform 0.12s ease;
}
.door:hover, .door:focus-visible {
  border-top-color: var(--accent-strong);
  transform: translateY(-2px);
}

.door-label {
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 0.82rem;
  color: var(--accent-strong);
}

.door-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 1.1rem;
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.78rem;
  color: var(--accent-strong);
}
.door:hover .door-arrow, .door:focus-visible .door-arrow { text-decoration: underline; }

.door p {
  margin-top: 0.7rem;
  color: var(--text);
  font-size: 0.98rem;
}

.scene-intro {
  padding: 2rem 0 0;
}

/* ---------- The journey: full-bleed scenes (Ship / Show / Where He's Been) ---------- */

.journey {
  border-top: 1px solid var(--border);
}

.scene {
  position: relative;
  min-height: clamp(26rem, 72vh, 44rem);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  border-bottom: 1px solid var(--border);
}

.scene-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.scene.scene-right .scene-img { object-position: 65% 50%; }
.scene.scene-left .scene-img { object-position: 35% 50%; }

/* The Show photo is 4:3, the wide box crops most of its height, and at
   50% (centered) that cut the crowd at the bottom almost entirely.
   Pushed toward the bottom of the frame so the crowd is the thing kept,
   not the sky. */
#the-show .scene-img { object-position: 50% 32%; }

/* The Ship photo is a wide panorama (Ferris wheel left, ship hull and its
   own sign right of center). A narrow tall box can't hold both. Wide keeps
   the 35% crop above, which shows both. Below 700px, where the box turns
   tall and narrow, this switches to the hull/sign instead of losing both
   to a strip of sky. A clamp()/calc() mix (percent + px) here silently
   failed to resolve in testing, plain values only, so this is a real
   breakpoint, not the continuous trick used elsewhere tonight. */
@media (max-width: 700px) {
  #the-ship .scene-img { object-position: 68% 42%; }
}

.scene-scrim {
  position: absolute;
  inset: 0;
}
.scene.scene-left .scene-scrim {
  background:
    linear-gradient(180deg, rgba(10,10,12,0.05) 0%, rgba(10,10,12,0.3) 55%, rgba(10,10,12,0.92) 100%),
    linear-gradient(90deg, rgba(10,10,12,0.65) 0%, rgba(10,10,12,0.05) 50%);
}
.scene.scene-right .scene-scrim {
  background:
    linear-gradient(180deg, rgba(10,10,12,0.05) 0%, rgba(10,10,12,0.3) 55%, rgba(10,10,12,0.92) 100%),
    linear-gradient(270deg, rgba(10,10,12,0.65) 0%, rgba(10,10,12,0.05) 50%);
}

/* Ace, 2026-09-03: the ship's actual color and lit detail were getting
   muted by a gradient that started darkening halfway up the frame. Crushed
   down into a tighter band at the very bottom, near-clear through the
   ship itself, only the vertical (top-to-bottom) gradient touches, the
   horizontal one above still handles left-side text contrast. */
#the-ship .scene-scrim {
  background:
    linear-gradient(180deg, rgba(10,10,12,0.02) 0%, rgba(10,10,12,0.08) 68%, rgba(10,10,12,0.94) 100%),
    linear-gradient(90deg, rgba(10,10,12,0.65) 0%, rgba(10,10,12,0.05) 50%);
}

.scene-content {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-top: 3rem;
  padding-bottom: 2.75rem;
}
.scene.scene-right .scene-inner { margin-left: auto; text-align: right; }
.scene.scene-right .scene-content .panel-link { margin-left: auto; }

.scene-inner { max-width: 40rem; }

.panel-num {
  font-family: var(--font-label);
  color: var(--accent-strong);
  font-size: 0.8rem;
  letter-spacing: 0.14em;
}

.scene h2 {
  margin-top: 0.6rem;
  font-size: clamp(1.9rem, 3.4vw, 2.9rem);
  color: var(--text);
}

.scene p {
  margin-top: 1.1rem;
  color: rgba(240,240,238, 0.85);
  font-size: 1.05rem;
  max-width: 42ch;
}
.scene.scene-right p { margin-left: auto; }
.scene p strong { color: var(--text); font-weight: 600; }

.panel-link {
  margin-top: 1.3rem;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.82rem;
  color: var(--accent-strong);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.panel-link:hover, .panel-link:focus-visible { border-color: var(--accent-strong); }

/* Where He's Been: manifest scene, image plus a long fading list */

.manifest-scene {
  background: var(--panel);
  padding: clamp(3.5rem, 8vw, 6rem) 0;
}

.manifest-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  align-items: start;
}

@media (min-width: 860px) {
  .manifest-grid { grid-template-columns: 0.85fr 1.15fr; gap: 4rem; }
}

.manifest-media img {
  width: 100%;
  border-radius: var(--radius);
}

.manifest-copy h2 {
  font-size: clamp(1.9rem, 3vw, 2.5rem);
  color: var(--text);
}
.manifest-copy > p {
  margin-top: 1.1rem;
  color: var(--text-dim);
  font-size: 1.02rem;
}

.route-scroll {
  margin-top: 1.5rem;
  max-height: 30rem;
  overflow: hidden;
  position: relative;
  -webkit-mask-image: linear-gradient(180deg, #000 72%, transparent 96%);
  mask-image: linear-gradient(180deg, #000 72%, transparent 96%);
}

.route-list {
  list-style: none;
  margin: 0;
  padding: 0;
  columns: 2;
  column-gap: 1.75rem;
  font-family: var(--font-body);
  font-size: 1.02rem;
  font-weight: 500;
  color: var(--text);
}
#track-list, #track-list-about { will-change: transform; }
.route-list li {
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  break-inside: avoid;
}
.route-list li span.tag {
  color: var(--text-dim);
  font-size: 0.88rem;
  font-weight: 400;
}

@media (max-width: 480px) {
  .route-list { columns: 1; column-gap: 1rem; font-size: 1rem; }
}

.route-note {
  margin-top: 0.9rem;
  font-size: 0.85rem;
  color: var(--text-dim);
  font-style: italic;
}

/* ---------- Origin ---------- */

.origin {
  padding: clamp(3.5rem, 8vw, 6rem) 0;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
.origin em { font-style: italic; }

.origin-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 3rem;
  align-items: center;
}

@media (min-width: 760px) {
  .origin-grid { grid-template-columns: 1.3fr 1fr; }
}

/* Two real vintage prints (1968, own white borders and date stamps
   already baked in), tossed at an angle like actual photos out of a
   drawer, not a tilted content-card pattern. Ace's call after flagging
   the earlier tilted-card treatment: these read differently because
   they're genuine prints. */
.origin-photos {
  position: relative;
  width: 100%;
  max-width: 25rem;
  height: clamp(13rem, 26vw, 18rem);
  margin: 0 auto;
}

/* Fixed rem sizing, not percentage, both photos are close to the same
   size as the box itself, so a percentage shift barely moves the overlap
   point, fixed offsets are the only way to land the cover precisely. */
.origin-photo {
  position: absolute;
  width: 11.5rem;
  height: auto;
  box-shadow: 0 1rem 2.25rem rgba(0,0,0,0.55);
}

.origin-photo-sword {
  left: 6.75rem;
  top: 0.5rem;
  transform: rotate(-9deg);
  z-index: 2;
}

.origin-photo-disney {
  left: 0;
  bottom: 0;
  transform: rotate(6deg);
  z-index: 1;
}

/* Smallest phones only: the tilted sword print poked 5px past the
   screen edge at 320px. Shrink the pair a touch, placement unchanged. */
@media (max-width: 359px) {
  .origin-photos { transform: scale(0.94); transform-origin: center top; }
}

/* ---------- Closing line ---------- */

.closing {
  padding: clamp(3rem, 7vw, 5rem) 0;
  text-align: center;
  border-bottom: 1px solid var(--border);
}
.closing p {
  max-width: 46ch;
  margin: 0 auto;
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  color: var(--text);
  font-weight: 500;
}

/* ---------- Testimonials ---------- */

.logbook {
  padding: clamp(3.5rem, 8vw, 6rem) 0;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}

.logbook-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  margin-top: 2.2rem;
}

@media (min-width: 760px) {
  .logbook-grid { grid-template-columns: 1fr 1fr; }
}

.logbook-entry {
  padding: 2rem;
  background: var(--ink);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
}

.logbook-entry blockquote {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.25rem;
  line-height: 1.4;
  color: var(--text);
}

.logbook-entry cite {
  display: block;
  margin-top: 1.1rem;
  font-style: normal;
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 0.8rem;
  color: var(--text-dim);
}
.logbook-entry cite strong {
  display: block;
  color: var(--accent-strong);
  font-family: var(--font-body);
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.95rem;
  font-weight: 600;
  margin-bottom: 0.15rem;
}

/* ---------- Quick specs (fair-buyer strip, second touch) ---------- */

.specs-strip { background: var(--ink-2); }
.specs-list {
  list-style: none;
  margin: 1.4rem 0 0;
  padding: 0;
  max-width: 46rem;
}
.specs-list li {
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  font-size: 1rem;
}

/* ---------- Footer ---------- */

footer {
  padding: 2.5rem 0 3rem;
}

.footer-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1.5rem;
  align-items: center;
}

.footer-brand {
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--text);
}

.footer-contact {
  font-family: var(--font-label);
  font-size: 0.88rem;
  letter-spacing: 0.03em;
  color: var(--text-dim);
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.footer-contact a { text-decoration: none; }
.footer-contact a:hover, .footer-contact a:focus-visible { color: var(--accent-strong); }

.footer-note {
  margin-top: 1.5rem;
  font-size: 0.78rem;
  color: var(--fog);
  opacity: 0.7;
}

/* ---------- Buyer-door subpages (Fairs, Corporate, Community, Private) ----------
   Built 2026-09-04 off the Dude's locked copy draft
   (shared/copy-blocks/jack-spareribs-buyer-door-pages.md). Reuses every token and
   most component classes from the home page (.door, .doors-grid, .logbook-entry,
   .route-list, .specs-list, .closing) rather than inventing new patterns, since
   these are utility pages behind the home page's doors, not a second flagship. */

.page-hero {
  position: relative;
  min-height: clamp(20rem, 46vw, 30rem);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  border-bottom: 1px solid var(--border);
  background: var(--ink);
}
.page-hero-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.page-hero-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(10,10,12,0.12) 0%, rgba(10,10,12,0.55) 58%, rgba(10,10,12,0.96) 100%);
}
.page-hero-content {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-top: clamp(2.5rem, 6vw, 4rem);
  padding-bottom: clamp(2.25rem, 5vw, 3.25rem);
}
.page-hero .eyebrow { display: block; margin-bottom: 0.6rem; }
.page-hero h1 {
  font-size: clamp(2.1rem, 4.4vw, 3.4rem);
  color: var(--text);
  max-width: 18ch;
}
.page-hero-sub {
  margin-top: 1rem;
  max-width: 54ch;
  font-size: 1.08rem;
  color: rgba(240,240,238,0.9);
}
.page-hero-cta {
  margin-top: 1.6rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
}

.page-hero-caption {
  position: absolute;
  z-index: 3;
  right: clamp(1rem, 3vw, 1.75rem);
  bottom: 0.9rem;
  margin: 0;
  max-width: 20rem;
  text-align: right;
  font-family: var(--font-label);
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  font-style: italic;
  color: rgba(240, 240, 238, 0.65);
}

/* Below ~640px the hero's text stack can grow tall enough that this caption,
   pinned to the hero's own bottom edge, overlaps the CTA button under it.
   Take it out of the overlay entirely and let it flow on its own line. */
@media (max-width: 640px) {
  .page-hero { flex-wrap: wrap; }
  .page-hero-caption {
    position: static;
    width: 100%;
    margin: 1rem 0 0;
    padding: 0 clamp(1.25rem, 4vw, 3rem);
    max-width: none;
    text-align: left;
  }
}

/* No real photo picked yet for this page: plain text band instead of the
   photo-band hero, so nothing here looks like a finished decision. */
.page-hero--text {
  min-height: auto;
  background: var(--ink);
}
.page-hero--text .page-hero-content { padding-top: clamp(3rem, 7vw, 4.5rem); padding-bottom: clamp(3rem, 7vw, 4.5rem); }

/* Fairs hero photo: continuous formula, not a breakpoint. A hard media-query
   swap between the mobile crop and the wide crop snapped visibly at 860px,
   the same "floating" problem the homepage hero's ship/Jack/Maynard
   positioning already solves with a formula instead of a jump. Narrow
   (~400px) wants Jack big and low (scale 1.5, low in frame, text bleeds off
   entirely). Wide (~1600px+) wants the zoom eased off so STATE FAIR reads
   above him. Interpolates smoothly between the two and clamps past them. */
.fair-hero-img {
  object-position: 58% clamp(58%, calc(80% - (100vw - 400px) * 0.01833), 80%);
  transform: scale(clamp(1, calc(1.5 - (100vw - 400px) / 2400px), 1.5));
  transform-origin: 58% clamp(58%, calc(80% - (100vw - 400px) * 0.01833), 80%);
}

.page-section { padding: clamp(3rem, 7vw, 5rem) 0; border-bottom: 1px solid var(--border); }
.page-section.panel { background: var(--panel); }
.page-section.has-watermark { position: relative; overflow: hidden; }
.page-section.has-watermark > .container { position: relative; z-index: 1; }

/* Real, load-bearing claim pulled out of a paragraph into its own line, per
   Ace 2026-09-04: nothing on these pages stood out for someone scanning
   tired on a phone. */
.claim-head {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  color: var(--accent-strong);
  margin-bottom: 0.6rem;
}
.page-section h2 { font-size: clamp(1.5rem, 2.6vw, 1.95rem); color: var(--text); }
.page-section .lede { margin-top: 1.1rem; font-size: 1.08rem; color: var(--text); max-width: var(--measure); }

.other-doors .doors-grid { margin-top: 1.5rem; }

.other-doors-links {
  margin-top: 1.25rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.75rem;
}
.other-doors-links a {
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 0.85rem;
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.1rem;
}
.other-doors-links a:hover, .other-doors-links a:focus-visible { color: var(--accent-strong); border-color: var(--accent-strong); }

/* Visible "not decided yet" marker for a photo slot Ace hasn't picked, so an
   unpicked slot never reads as a finished choice. Ace, 2026-09-04: reusing a
   real photo in the slot made the page look "very weird" and confusing,
   like a decision had already been made. */
.photo-tbd {
  position: relative;
  min-height: clamp(16rem, 34vw, 22rem);
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    repeating-linear-gradient(135deg, rgba(240,240,238,0.05) 0 14px, transparent 14px 28px),
    var(--ink-2);
  border-bottom: 1px dashed var(--border);
}
.photo-tbd-label {
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.85rem;
  color: var(--text-dim);
  text-align: center;
  max-width: 26rem;
  padding: 0 1.5rem;
}
.photo-tbd-label strong { display: block; color: var(--accent-strong); font-size: 0.78rem; margin-bottom: 0.4rem; }

/* ---------- Reveal-on-scroll, restrained ---------- */

@media (prefers-reduced-motion: no-preference) {
  .reveal.js-armed {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.6s ease, transform 0.6s ease;
  }
  .reveal.js-armed.is-visible {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ---------- Contact form ---------- */

.enquiry { margin-top: 2rem; max-width: 52rem; }
.enquiry .fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.5rem clamp(1.25rem, 3vw, 2.5rem);
}
.enquiry .f { margin: 0; max-width: none; }
.enquiry .f.wide { grid-column: 1 / -1; }
.enquiry .f label {
  display: block;
  font-family: var(--font-label);
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-strong);
  margin-bottom: 0.5rem;
}
.enquiry .f input, .enquiry .f select, .enquiry .f textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  padding: 0.7rem 0.85rem;
  border-radius: var(--radius);
}
.enquiry .f textarea { resize: vertical; line-height: 1.6; }
.enquiry .f input:focus-visible, .enquiry .f select:focus-visible, .enquiry .f textarea:focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: 1px;
}
.enquiry .f input::placeholder, .enquiry .f textarea::placeholder { color: var(--text-dim); opacity: 0.8; }
.enquiry .hint {
  display: block;
  margin-top: 0.55rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--text-dim);
}
.enquiry .send {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem 1.5rem;
  margin: 2.25rem 0 0;
}
.enquiry .send button { border: none; cursor: pointer; font-family: inherit; }
.enquiry .send .hint { margin-top: 0; max-width: 24rem; }
.enquiry .formstate { margin: 1.25rem 0 0; max-width: 40rem; color: var(--accent-strong); }
.enquiry .formstate:empty { margin: 0; }
.enquiry[data-sent="1"] .fields, .enquiry[data-sent="1"] .send { display: none; }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
