/* Hero: poster headline, photo plate, live deck and flight log (module M3).
   Desktop is a 12-column poster: the fitted headline spans the measure (in
   bone; the autopilot is the lamp hanging before its second line), the copy
   takes columns 1–4 and the photo plate 5–12, untouched over the faces.
   The deck docks on the plate's inline-start edge, half on ink and half over
   the street. From 1201 px the flight log is the plate's caption band, so the
   whole hand-off (headline, CTA, deck, log) shares the first viewport; below
   that it runs under the plate. Either way the log is stacked above the deck,
   so no card ever passes over its text. .hero[data-phase] lights one cell
   (signal for like and chat, cabin amber for the date).
   The match is her: the woman at the café table, cropped from the plate's
   own photograph; on the date beat her card lands on her in the picture.
   The photograph and every portrait are shown in full colour, as taken; the
   date beat only brings up a warm light over the café table. Phones stage
   the photo first, the headline on its scrim.
   While the autopilot runs, only transform and opacity move. */

.hero {
  position: relative;
  isolation: isolate;
  padding-block: calc(76px + clamp(20px, 3.4vh, 44px)) clamp(64px, 7vw, 112px);
}
.hero-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(16px, 1.7vw, 28px);
  align-items: start;
}

/* ── Kicker and poster headline ───────────────────────── */
.hero-kicker {
  grid-column: 1 / -1;
  margin-block-end: clamp(12px, 1.4vw, 20px);
  font: 500 13px/1.4 var(--font-text);
  letter-spacing: .01em;
  color: var(--muted);
}
.kicker-sep { margin-inline: 2px; color: var(--faint); }
.hero-title {
  grid-column: 1 / -1;
  margin-block-end: clamp(28px, 3vw, 48px);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fit, clamp(56px, 7.2vw, 128px));
  line-height: .94;
  letter-spacing: -.05em;
  overflow-wrap: break-word;
  color: var(--bone);
}
:is(:lang(zh), :lang(ja), :lang(ko)) .hero-title {
  font-size: var(--fit, clamp(56px, 7.6vw, 132px));
  line-height: 1.06;
  letter-spacing: -.03em;
}
/* The rise mask: a clip with headroom, so tall marks and descenders (the
   Latvian ņ cedilla, Vietnamese stacks) are never cut. */
.hero-line { display: block; clip-path: inset(-.35em -.1em -.3em -.1em); }
.hero-line > span { display: inline-block; max-width: 100%; }
/* The second line is set in bone like the first; the autopilot is not paint
   but a lamp before it, lit in the signal (grey when off, amber once landed).
   It hangs in the margin, so both lines keep one hard edge, sits on the
   x-height like a status light, and breathes while the autopilot works. Its net
   advance is zero (fit.js measures it all the same); the line's clip leaves
   room for the hang and the breath. */
.hero-accent { color: inherit; }
.hero-lamp { --lamp: .19em; --hang: .13em; margin-inline: calc(-1 * var(--lamp) - var(--hang)) var(--hang); vertical-align: .29em; }
.hero-line:has(> span > .hero-lamp) { clip-path: inset(-.35em -.6em -.3em -.6em); }
:is(:lang(zh), :lang(ja), :lang(ko)) .hero-lamp { --lamp: .17em; --hang: .12em; vertical-align: .33em; }
.hero-title:is(:lang(ar), :lang(he)) .hero-lamp { vertical-align: .36em; }

/* ── Copy ─────────────────────────────────────────────── */
.hero-copy { grid-column: 1 / span 4; min-width: 0; }
.hero-description { max-width: 32em; font-size: clamp(16px, 1.22vw, 18px); line-height: 1.6; color: var(--muted); }
.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 28px; margin-block-start: 28px; }
/* "See the demo" scrolls to the demo panel: a plain link with a down arrow, not a play button. */
.demo-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  font-size: 15px;
  font-weight: 600;
  color: var(--bone);
  text-decoration: underline;
  text-decoration-color: var(--line-2);
  text-decoration-thickness: 1px;
  text-underline-offset: 6px;
  transition: text-decoration-color var(--t-ui) var(--ease);
}
.demo-link svg { width: 16px; height: 16px; stroke-width: 2; transition: translate var(--t-ui) var(--ease); }
.demo-link:hover { text-decoration-color: currentColor; }
.demo-link:hover svg { translate: 0 3px; }
.hero-footnote { display: flex; flex-direction: column; gap: 7px; margin-block-start: 28px; font-size: 13px; line-height: 1.45; color: var(--faint); }
.hero-footnote li { display: flex; align-items: center; gap: 8px; }
.hero-footnote svg { width: 15px; height: 15px; color: var(--muted); }
/* From tablet up the reassurances run as one row of fine print under the CTA,
   wrapping only where the column is too narrow for all three. */
@media (min-width: 641px) {
  .hero-footnote { flex-flow: row wrap; gap: 6px 18px; margin-block-start: 18px; font-size: 12.5px; }
  .hero-footnote li { gap: 6px; }
  .hero-footnote svg { width: 14px; height: 14px; }
}

/* ── Visual: plate, deck, flight log ──────────────────── */
.hero-visual {
  --card-w: clamp(128px, 11.7vw, 176px);
  --card-h: calc(var(--card-w) * 4 / 3);
  --log-gap: clamp(16px, 1.6vw, 24px);
  grid-column: 5 / -1;
  min-width: 0;
  display: grid;
  grid-template-columns: [deck-start] calc(var(--card-w) / 2) [photo-start] calc(var(--card-w) / 2) [deck-end] var(--log-gap) [log-start] minmax(0, 1fr) [end];
  grid-template-rows: auto auto;
}
.hero-photo {
  grid-column: photo-start / end;
  grid-row: 1;
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
  background: var(--ink-2);
}
.hero-photo img { width: 100%; height: 100%; object-fit: cover; object-position: 62% 50%; }
/* Right-to-left pages mirror the picture (it holds no text), so the deck sits
   on the street side and the couple stays clear of it, as in left-to-right. */
[dir=rtl] .hero-photo img { scale: -1 1; }
/* The photograph is always shown as taken, in full colour. On the date beat
   a warm light comes up over the café table: a soft-light glow, so the scene
   warms and lifts a little without a colour cast (opacity only). */
.hero-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(70% 60% at calc(50% - 2% * var(--dir)) 62%, rgb(255 196 128 / .6), transparent 76%);
  mix-blend-mode: soft-light;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-scene) var(--ease);
}
.hero[data-phase=date] .hero-photo::after { opacity: 1; }
/* While the autopilot plays the date beat the light comes up as her card
   lands on her (hero.js TRAVEL), not before. */
html:not([data-autopilot=off], .is-landed) .hero[data-phase=date].is-playing .hero-photo::after { transition-delay: .8s; }

/* The deck: a real drag target. Cards are hidden until their portrait decodes. */
.hero-deck {
  grid-column: deck-start / deck-end;
  grid-row: 1;
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  inline-size: var(--card-w);
  user-select: none;
  -webkit-user-select: none;
}
.deck-stack { position: relative; inline-size: var(--card-w); block-size: var(--card-h); touch-action: pan-y; }
/* Cards further back sit diagonally behind the top one, toward inline-start
   and down, like a pile of prints, in full colour.
   While the autopilot runs, every move here is transform or opacity, so the
   loop costs the main thread nothing between its phase edges. */
.deck-card {
  --depth: 0;
  position: absolute;
  inset: 0;
  z-index: calc(8 - var(--depth));
  border-radius: 10px;
  opacity: 0;
  translate: calc(var(--depth) * -9px * var(--dir)) calc(var(--depth) * 7px);
  touch-action: pan-y;
  transition: translate .5s var(--ease), opacity var(--t-ui) var(--ease);
}
.deck-card[data-depth="1"] { --depth: 1; }
.deck-card[data-depth="2"] { --depth: 2; }
.deck-card[data-depth="3"] { --depth: 3; }
.deck-card[data-depth=out] { z-index: 9; pointer-events: none; }
.deck-card.is-ready:not([data-depth="3"]) { opacity: 1; }
.deck-stack:has(> .deck-card[data-depth="0"].is-ready) { cursor: grab; }
.deck-stack:has(> .is-dragging) { cursor: grabbing; }
.deck-card.is-recycling, .deck-card.is-recycling *, .deck-card.is-recycling::before, .deck-card.is-recycling::after { transition: none; }
.deck-face {
  position: relative;
  display: block;
  inline-size: 100%;
  block-size: 100%;
  overflow: hidden;
  border-radius: inherit;
  box-shadow: 0 24px 44px -20px rgb(0 0 0 / .75);
}
/* The hairline keeps the card's edge on the photo. */
.deck-face::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgb(242 240 234 / .14);
  pointer-events: none;
}
.deck-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  -webkit-user-drag: none;
}
/* Her card: the woman at the café table, cropped from the hero photograph the
   plate already shows (hero.js sets the crop as shares of that picture), so
   the date can land exactly on her. In right-to-left pages the picture is
   mirrored, as on the plate. */
.deck-card.is-her img {
  position: absolute;
  inset-block-start: calc(var(--crop-y) / var(--crop-h) * -100%);
  inset-inline-start: calc(var(--crop-x) / var(--crop-w) * -100%);
  inline-size: calc(100% / var(--crop-w));
  block-size: calc(100% / var(--crop-h));
  max-inline-size: none;
  object-fit: fill;
}
[dir=rtl] .deck-card.is-her img { scale: -1 1; }
/* Cards further back sit in shadow (opacity only). */
/* The lock: a ring on the card edge, outside the portrait. It closes in from
   a wider ring as it lights (scale and opacity only). Signal while the
   autopilot matches; cabin amber on the date beat and under a human like (human
   light); a plain line toward pass. */
.deck-card::before {
  content: "";
  position: absolute;
  inset: -5px;
  z-index: 3;
  border: 2px solid var(--signal);
  border-radius: 14px;
  opacity: 0;
  scale: 1.05;
  pointer-events: none;
  transition: opacity var(--t-ui) var(--ease), scale var(--t-ui) var(--ease);
}
.deck-card:is(.is-matched, [data-cue])::before { opacity: 1; scale: 1; }
.hero[data-phase=date] .deck-card.is-matched::before,
.deck-card[data-cue=like]::before { border-color: var(--amber); }
.deck-card[data-cue=pass]::before { border-color: var(--line-2); }
.deck-pill {
  position: absolute;
  inset-block-start: 0;
  left: 50%;
  z-index: 3;
  translate: -50% -50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 6px 12px 6px 9px;
  border: 1px solid var(--line-2);
  border-radius: 99px;
  background: var(--ink);
  color: var(--bone);
  font: 650 12px/1.2 var(--font-text);
  white-space: nowrap;
  box-shadow: 0 10px 24px -10px rgb(0 0 0 / .8);
  animation: hero-pill var(--t-ui) var(--ease) both;
}
.deck-pill svg { width: 13px; height: 13px; stroke-width: 2.4; }
/* Chat beat: the log's own chat line opens as a bubble on the card's inline-end edge. */
.deck-bubble {
  position: absolute;
  inset-block-start: 41%;
  inset-inline-start: calc(100% - 16px);
  z-index: 10;
  inline-size: max-content;
  max-inline-size: 17em;
  padding: 10px 14px 11px;
  border-radius: 16px;
  border-start-start-radius: 4px;
  background: var(--ink-4);
  color: var(--bone);
  font: 500 14px/1.42 var(--font-text);
  box-shadow: 0 18px 40px -14px rgb(0 0 0 / .85), inset 0 0 0 1px rgb(242 240 234 / .08);
  pointer-events: none;
  opacity: 0;
  translate: 0 10px;
  transition: opacity var(--t-ui) var(--ease), translate var(--t-ui) var(--ease);
}
.deck-bubble.is-shown { opacity: 1; translate: 0 0; transition-duration: var(--t-scene); }
.deck-caption {
  position: absolute;
  inset-block-start: calc(100% + 22px);
  inset-inline-start: 0;
  inline-size: max(100%, 11em);
  font-size: 12px;
  line-height: 1.45;
  color: var(--faint);
  transition: color var(--t-ui) var(--ease);
}
/* The hand-off: the caption carries the message where the visitor is looking. */
.deck-caption.is-handoff { color: var(--bone); }

/* ── Flight log ───────────────────────────────────────── */
/* An annunciator panel: a cell lights and dims in one step, as instrument
   lamps do (no colour transitions, so the running loop paints once per phase
   edge, not every frame). */
.flight-log {
  grid-column: log-start / end;
  grid-row: 2;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-block-start: 1px solid var(--line-2);
}
.flight-log > li {
  --cell: var(--bone);
  --cell-sub: var(--muted);
  --cell-lamp: transparent;
  --cell-ring: var(--line-2);
  --cell-accent: var(--cell);
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 14px clamp(12px, 1.2vw, 18px) 4px;
  color: var(--cell);
  transition: opacity var(--t-ui) var(--ease);
}
.flight-log > li + li { border-inline-start: 1px solid var(--line); }
.log-time {
  display: flex;
  align-items: center;
  gap: 8px;
  font: 500 11px/1 var(--font-mono);
  letter-spacing: .08em;
  font-variant-numeric: tabular-nums;
  color: var(--cell-time, var(--cell-sub));
  direction: ltr;
  unicode-bidi: isolate;
}
/* The weekday is filled in the page language (hero.js); right to left it leads on the right. */
[dir=rtl] .log-time { flex-direction: row-reverse; }
.log-day { unicode-bidi: isolate; }
/* The cell lamp: hollow when idle, lit in the cell's light. */
.log-time::after {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  margin-inline-start: auto;
  border-radius: 50%;
  background: var(--cell-lamp);
  box-shadow: inset 0 0 0 1px var(--cell-ring);
}
[dir=rtl] .log-time::after { margin-inline: 0 auto; }

/* Status row: auto-like, its counter and the annunciator. */
.flight-log > .floating-status { flex-flow: row wrap; align-content: flex-start; align-items: flex-end; column-gap: 12px; }
.floating-status > .log-time, .floating-status > div { flex: 1 0 100%; }
.floating-status .pulse-icon { display: none; }
.floating-status strong { display: block; font: 650 14px/1.3 var(--font-text); }
.floating-status div > span { display: block; margin-block-start: 3px; font-size: 12.5px; line-height: 1.4; color: var(--cell-sub); }
.hud-count {
  align-self: end;
  display: inline-flex;
  align-items: baseline;
  inline-size: 5.4em;
  font: 500 11px/1 var(--font-mono);
  color: var(--cell-sub);
  white-space: nowrap;
  direction: ltr;
  unicode-bidi: isolate;
  contain: layout paint;
}
/* Machine time: Archivo 62% with tabular figures; a like steps it to 75% for 200 ms, inside the fixed readout. */
.hud-count b {
  margin-inline-end: 2px;
  font: 800 22px/1 var(--font-display);
  font-stretch: 62%;
  font-variant-numeric: tabular-nums;
  color: var(--cell-accent);
}
.hud-count b.is-step { font-stretch: 75%; }
.log-state { align-self: end; justify-self: end; margin-inline-start: auto; padding-block-end: 2px; font: 500 10px/1 var(--font-mono); letter-spacing: .12em; color: var(--cell-sub); white-space: nowrap; }

/* Chat row. While the bubble on the deck speaks the line, the cell keeps only
   its time and label, so the sentence is never shown twice. */
.chat-tag { display: inline-flex; align-items: center; gap: 7px; font: 650 13px/1.3 var(--font-text); color: var(--cell-accent); }
.chat-tag .status-dot { display: none; }
.floating-chat p { font-size: 13.5px; line-height: 1.45; color: var(--cell); transition: opacity var(--t-ui) var(--ease); }
@media (min-width: 641px) {
  .hero:has(.deck-bubble.is-shown) .floating-chat p { opacity: 0; }
}

/* Date row. */
.match-top { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font: 650 14px/1.3 var(--font-text); }
.match-icon { display: none; }
.match-top .demo-badge { margin-inline-start: auto; }
.match-body { display: flex; align-items: center; gap: 10px; }
.match-body .letter-avatar { width: 28px; height: 28px; font-size: 14px; background: var(--cell-avatar, var(--amber)); color: var(--cell-avatar-ink, var(--on-amber)); box-shadow: inset 0 0 0 1px var(--cell-ring); }
.match-body strong { display: block; font: 650 13.5px/1.25 var(--font-text); }
.match-body p { margin-block-start: 2px; font-size: 12.5px; line-height: 1.35; color: var(--cell-sub); }
.match-bottom { display: flex; flex-wrap: wrap; gap: 2px 10px; font-size: 12px; line-height: 1.4; color: var(--cell-sub); }
.match-bottom span:first-child { display: inline-flex; align-items: center; gap: 5px; font-weight: 650; color: var(--cell-accent); }
.match-bottom svg { width: 13px; height: 13px; stroke-width: 2.2; }

/* Japanese in the narrow cells, the bubble and the caption breaks at phrase boundaries. */
:lang(ja) :is(.flight-log, .deck-bubble, .deck-caption) { word-break: auto-phrase; }

/* Phase lighting. Without JS there is no phase: every cell reads in bone.
   (The lit rules name the list too, so they outrank the dimmed default.) */
.hero[data-phase] .flight-log > li { --cell: var(--faint); --cell-sub: var(--faint); --cell-avatar: transparent; --cell-avatar-ink: var(--faint); }
.hero:is([data-phase=like], [data-phase=match]) .flight-log > [data-log=like],
.hero[data-phase=chat] .flight-log > [data-log=chat],
.hero[data-phase=date] .flight-log > [data-log=date] {
  --cell: var(--bone);
  --cell-sub: var(--muted);
  --cell-ring: transparent;
  --cell-avatar: var(--amber);
  --cell-avatar-ink: var(--on-amber);
  background: rgb(242 240 234 / .035);
}
.hero:is([data-phase=like], [data-phase=match]) .flight-log > [data-log=like],
.hero[data-phase=chat] .flight-log > [data-log=chat] { --cell-lamp: var(--signal); --cell-accent: var(--signal); }
.hero[data-phase=date] .flight-log > [data-log=date] { --cell-lamp: var(--amber); --cell-accent: var(--amber); --cell-time: var(--amber); }

/* ── Entrance: once, on the final text ────────────────── */
html.is-localized .hero-line > span { animation: hero-rise 1.1s var(--ease) both; }
html.is-localized .hero-line + .hero-line > span { animation-delay: .12s; }
html.is-localized .hero-kicker { animation: hero-fade-up .9s var(--ease) both; }
html.is-localized .hero-description { animation: hero-fade-up .9s var(--ease) .25s both; }
html.is-localized .hero-actions { animation: hero-fade-up .9s var(--ease) .32s both; }
html.is-localized .hero-footnote { animation: hero-fade-up .9s var(--ease) .46s both; }
html.is-localized .flight-log { animation: hero-fade-up .9s var(--ease) .42s both; }
html.is-localized .deck-caption { animation: hero-fade-up .9s var(--ease) .5s both; }

@keyframes hero-rise { from { transform: translateY(calc(100% + .2em)); } to { transform: none; } }
@keyframes hero-fade-up { from { opacity: 0; translate: 0 18px; } to { opacity: 1; translate: 0 0; } }
@keyframes hero-pill { from { opacity: 0; translate: -50% -20%; } to { opacity: 1; translate: -50% -50%; } }

/* No JS: there is no deck, so the plate and the log take the whole column. */
@media (scripting: none) {
  .hero-deck { display: none; }
  .hero-photo, .flight-log { grid-column: deck-start / end; }
}

/* ── Wide desktop: the hand-off in one viewport ───────── */
/* The plate takes the deck on its inline-start edge and the flight log as a
   caption band over its lower part, below the faces (which sit in the upper
   half of the picture). The headline is fitted (fit.js) so the plate ends
   above the fold, and the CSS size is already that fit for two lines: the
   viewport height, less the header, kicker and margins, less the plate's
   height (8 of 12 columns, less half a card, at the plate's ratio), shared by
   two lines at the script's leading (mirroring the line-heights set here and
   in type.css). So the gated source text takes the same room as the final
   one, the plate does not move when the visitor's language arrives, and
   fit.js only refines the size for the real line count. */
@media (min-width: 1201px) {
  .hero {
    --hero-plate: 1.6;
    --hero-container: min(1440px, 100vw - 2 * var(--gutter));
    --hero-plate-h: calc((var(--hero-container) * 2 / 3 - clamp(16px, 1.7vw, 28px) / 3 - clamp(200px, 16vw, 248px) / 2) / var(--hero-plate));
    --hero-room: calc(100vh - 30px - 76px - clamp(20px, 3.4vh, 44px) - 18.2px - clamp(12px, 1.4vw, 20px) - clamp(28px, 2.6vw, 44px) - var(--hero-plate-h));
  }
  .hero-title {
    --hero-lh: .94;
    margin-block-end: clamp(28px, 2.6vw, 44px);
    font-size: var(--fit, clamp(52px, min(8vw, var(--hero-room) / (2 * var(--hero-lh))), 128px));
  }
  :is(:lang(zh), :lang(ja), :lang(ko)) .hero-title { --hero-lh: 1.06; font-size: var(--fit, clamp(52px, min(8vw, var(--hero-room) / (2 * var(--hero-lh))), 128px)); }
  .hero-title:is(:lang(ar), :lang(he)) { --hero-lh: 1.22; }
  .hero-title:is(:lang(th), :lang(lo), :lang(km), :lang(my), :lang(hi), :lang(bn), :lang(ta), :lang(te), :lang(ka)) { --hero-lh: 1.3; }
  .hero-visual {
    --card-w: clamp(200px, 16vw, 248px);
    --caption-room: 58px;
    grid-template-rows: auto;
  }
  .hero-photo { aspect-ratio: 16 / 10; }
  .hero-deck { align-self: end; padding-block-end: var(--caption-room); }
  .deck-caption { inset-block-start: calc(100% - var(--caption-room) + 20px); }
  /* The band is stacked above the deck, so a thrown or dragged card passes
     under its text, never over it. Its shade starts at the deck's edge (the
     resting card is never dimmed) and only its cells take the pointer. The
     shade holds every cell at 4.5:1 over the brightest part of the photo. */
  .flight-log {
    grid-column: photo-start / end;
    grid-row: 1;
    align-self: end;
    position: relative;
    z-index: 3;
    padding-block-start: 64px;
    padding-inline: calc(var(--card-w) / 2 + var(--log-gap)) 6px;
    border-block-start: 0;
    pointer-events: none;
  }
  .flight-log::before {
    content: "";
    position: absolute;
    inset: 0;
    inset-inline-start: calc(var(--card-w) / 2);
    z-index: -1;
    border-end-end-radius: 8px;
    background: linear-gradient(rgb(11 13 18 / 0), rgb(11 13 18 / .62) 16%, rgb(11 13 18 / .86) 34%, rgb(11 13 18 / .94) 52%);
    -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--log-gap));
    mask-image: linear-gradient(to right, transparent, #000 var(--log-gap));
  }
  [dir=rtl] .flight-log::before {
    -webkit-mask-image: linear-gradient(to left, transparent, #000 var(--log-gap));
    mask-image: linear-gradient(to left, transparent, #000 var(--log-gap));
  }
  /* Under the deck, the plate's own shade carries the caption below the card. */
  .hero-photo::before {
    content: "";
    position: absolute;
    inset-block-end: 0;
    inset-inline-start: 0;
    inline-size: calc(var(--card-w) / 2 + var(--log-gap));
    block-size: calc(var(--caption-room) + 36px);
    background: linear-gradient(rgb(11 13 18 / 0), rgb(11 13 18 / .86) 50%, rgb(11 13 18 / .94));
    pointer-events: none;
  }
  .flight-log > li { padding-block: 14px 18px; border-block-start: 1px solid var(--line-2); pointer-events: auto; }
  .hero[data-phase] .flight-log > li { --cell: var(--muted); --cell-sub: var(--muted); }
  /* Over the photo a lit cell is a deeper well, not a bone tint: the shade
     alone lets the red label (13px) fall under 4.5:1 near the band's top
     edge, and this backing holds it at 4.8:1 or more. */
  .hero:is([data-phase=like], [data-phase=match]) .flight-log > [data-log=like],
  .hero[data-phase=chat] .flight-log > [data-log=chat],
  .hero[data-phase=date] .flight-log > [data-log=date] { background: rgb(11 13 18 / .5); }
  /* The bubble grows upward over the street, clear of the band's first cell. */
  .deck-bubble { inset-block: auto 59%; border-start-start-radius: 16px; border-end-start-radius: 4px; }
}
/* 16:9 screens and flatter: a flatter plate keeps the band above the fold. */
@media (min-width: 1201px) and (min-aspect-ratio: 17 / 10) {
  .hero { --hero-plate: 1.7778; }
  .hero-photo { aspect-ratio: 16 / 9; }
}
/* Short screens: a tighter band, so it stays under the chins on a lower plate. */
@media (min-width: 1201px) and (max-height: 820px) {
  .flight-log { padding-block-start: 40px; }
  .flight-log > li { padding-block: 11px 13px; gap: 5px; }
}
/* No JS, no deck: the plate takes the whole column at the same height. */
@media (min-width: 1201px) and (scripting: none) {
  .hero-photo { aspect-ratio: auto; block-size: var(--hero-plate-h); }
  .flight-log { grid-column: deck-start / end; padding-inline-start: 6px; }
  .flight-log::before { inset-inline-start: 0; border-end-start-radius: 8px; -webkit-mask-image: none; mask-image: none; }
}

/* ── Narrow desktop ───────────────────────────────────── */
/* The deck docks on the plate's bottom edge; when a tall headline pushes that
   edge past the fold, the stack rides up the plate's outer edge to stay in
   view, but never into its upper 35%, where the faces are. */
@media (max-width: 1200px) and (min-width: 1001px) {
  .hero-copy { grid-column: 1 / span 5; }
  .hero-visual { grid-column: 6 / -1; container-type: inline-size; }
  .hero-deck { padding-block-start: calc((100cqi - var(--card-w) / 2) * 9 / 16 * .35); }
  .deck-stack { position: sticky; inset-block-end: clamp(16px, 3vh, 28px); }
}

/* Below 1201 px three cells are too narrow to read: the log becomes a list of
   timed rows (time, then the entry) under the plate. It is an ink panel
   stacked above the deck, so a card thrown or dragged toward it slides behind
   it, never over its text. */
@media (max-width: 1200px) {
  .flight-log { position: relative; z-index: 3; grid-template-columns: minmax(0, 1fr); border-block-start: 0; background: var(--ink); }
  .flight-log > li, .flight-log > .floating-status { display: grid; grid-template-columns: 92px minmax(0, 1fr) auto; align-items: start; gap: 6px 16px; padding: 14px; border-block-end: 1px solid var(--line); }
  .flight-log > li + li { border-inline-start: 0; }
  .flight-log > li > *, .flight-log > .floating-status > div { grid-column: 2 / -1; }
  .flight-log > li > .log-time { grid-column: 1; grid-row: 1 / span 4; padding-block-start: 3px; white-space: nowrap; }
  .flight-log > .floating-status > .hud-count { grid-column: 2; }
  .flight-log > .floating-status > .log-state { grid-column: 3; }
}

/* ── Tablet: one column, the plate then deck beside the log, then the copy ── */
@media (max-width: 1000px) {
  .hero { padding-block: calc(76px + 28px) 72px; }
  .hero-grid { grid-template-columns: minmax(0, 1fr); }
  .hero-kicker, .hero-title, .hero-copy, .hero-visual { grid-column: 1; }
  .hero-title { font-size: var(--fit, clamp(48px, 7.4vw, 72px)); margin-block-end: 32px; }
  :is(:lang(zh), :lang(ja), :lang(ko)) .hero-title { font-size: var(--fit, clamp(52px, 8vw, 80px)); }
  .hero-visual {
    --card-w: 136px;
    order: 1;
    grid-template-columns: [deck-start photo-start] var(--card-w) [deck-end] 24px [log-start] minmax(0, 1fr) [end];
  }
  .hero-photo { grid-column: photo-start / end; aspect-ratio: 16 / 10; }
  .hero-deck { grid-row: 2; align-self: start; margin-block-start: calc(var(--card-h) * -.5); margin-inline-start: 16px; }
  .deck-caption { position: static; margin-block-start: 22px; inline-size: auto; }
  .deck-bubble { inset-block-start: 6%; }
  .hero-copy { order: 2; margin-block-start: 40px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 40px; align-items: start; }
  .hero-description { grid-column: 1; }
  .hero-actions, .hero-footnote { grid-column: 2; }
  .hero-actions { grid-row: 1; margin-block-start: 0; }
  .hero-footnote { grid-row: 2; }
  @media (scripting: none) {
    .hero-photo, .flight-log { grid-column: deck-start / end; }
  }
}

/* ── Phone: the photo is the stage, the headline sits on its scrim ── */
@media (max-width: 640px) {
  .hero { padding-block: 64px 56px; }
  .hero-grid { grid-template-areas: "stage" "desc" "actions" "log" "kicker" "foot"; }
  .hero-copy, .hero-visual { display: contents; }
  .hero-visual { --card-w: 112px; }
  .hero-photo {
    grid-area: stage;
    margin-inline: calc(var(--gutter) * -1);
    aspect-ratio: 4 / 5;
    max-height: 66svh;
    border-radius: 0;
  }
  /* The scrim rises steeply under the chins (the faces end at about 43% of
     the stage), so every glyph of the headline holds 3:1 even on the white
     shirt and the marble table in full daylight. */
  .hero-photo::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    /* A warm evening shadow under the headline (same darkness, so the same contrast), settling into the page's ink only at the foot. */
    background: linear-gradient(rgb(22 13 11 / 0) 38%, rgb(22 13 11 / .56) 50%, rgb(17 13 13 / .78) 63%, rgb(11 13 18 / .95) 90%);
    pointer-events: none;
  }
  .hero-title {
    grid-area: stage;
    align-self: end;
    position: relative;
    z-index: 2;
    margin: 0;
    padding-block-end: 16px;
    font-size: var(--fit, 40px);
  }
  :is(:lang(zh), :lang(ja), :lang(ko)) .hero-title { font-size: var(--fit, 46px); }
  .hero-description { grid-area: desc; margin-block-start: 18px; font-size: 15.5px; line-height: 1.6; }
  .hero-actions { grid-area: actions; margin-block-start: 20px; gap: 6px 20px; }
  .hero-actions .button { width: 100%; }
  .hero-deck { grid-area: log; justify-self: start; align-self: start; margin: 32px 0 0; }
  /* The date beat docks her card onto the date row's avatar, above the log panel. */
  .hero[data-phase=date] .hero-deck { z-index: 4; }
  .deck-caption { position: static; margin-block-start: 20px; inline-size: auto; font-size: 11px; line-height: 1.4; }
  .deck-bubble { display: none; }
  /* The match pill wraps within the card's width plus the gap to the log, so
     it never meets the screen edge or covers the log. */
  .deck-pill { max-inline-size: calc(var(--card-w) + 34px); inline-size: max-content; padding-inline: 10px; white-space: normal; text-align: center; }
  .flight-log { grid-area: log; margin-block-start: 32px; margin-inline-start: calc(var(--card-w) + 18px); border-block-start: 1px solid var(--line-2); }
  .flight-log > li, .flight-log > .floating-status { grid-template-columns: minmax(0, 1fr) auto; padding: 12px 0 4px; padding-inline-start: 2px; border-block-end: 0; }
  .flight-log > li > *, .flight-log > .floating-status > div { grid-column: 1 / -1; }
  .flight-log > li > .log-time { grid-column: 1 / -1; grid-row: auto; padding-block-start: 0; }
  .flight-log > .floating-status > .hud-count { grid-column: 1; }
  .flight-log > .floating-status > .log-state { grid-column: 2; }
  .hero-kicker { grid-area: kicker; margin-block: 24px 0; }
  .kicker-sep, .kicker-platforms { display: none; }
  .hero-footnote { grid-area: foot; margin-block-start: 16px; }
  @media (scripting: none) {
    .flight-log { margin-inline-start: 0; }
  }
}

/* Phones with JS and motion, while the autopilot works: the log shows the live
   row. All rows share one cell (so swapping them never moves the page) and
   stay in the accessibility tree; only their opacity changes. Paused, all
   rows are listed, as with reduced motion. */
@media (max-width: 640px) and (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  html:not([data-autopilot=off]) .flight-log { grid-template-areas: "row"; }
  html:not([data-autopilot=off]) .flight-log > li { grid-area: row; border-block-end: 0; }
  html:not([data-autopilot=off]) .hero:not([data-phase]) .flight-log > li:not([data-log=like]),
  html:not([data-autopilot=off]) .hero:is([data-phase=like], [data-phase=match]) .flight-log > li:not([data-log=like]),
  html:not([data-autopilot=off]) .hero[data-phase=chat] .flight-log > li:not([data-log=chat]),
  html:not([data-autopilot=off]) .hero[data-phase=date] .flight-log > li:not([data-log=date]) {
    opacity: 0;
  }
  .hero[data-phase] .flight-log > li[data-log] { background: none; }
}
