/* RUNROO Racing Services, shared chrome: header, mobile menu, footer,
   assistant. Loaded by every page after its own stylesheet. Every class is
   rr- prefixed so it cannot collide with the page styles underneath it.
   Colours are RUNROO tokens (brand-os/tokens.json), gold and black only. */

:root {
  --rr-black: #000000;
  --rr-panel: #0A0A0A;
  --rr-line: #1F1F1F;
  --rr-gold: #D4A72C;
  --rr-gold-hover: #DCB752;
  --rr-gold-pressed: #B69026;
  --rr-white: #FFFFFF;
  --rr-muted: #9E9E9E;
  --rr-meta: #808080;
  --rr-pad: clamp(1.25rem, 4vw, 4.5rem);
  --rr-nav-h: 5rem;
}

body.rr-menu-open { overflow: hidden; }

.rr-skip {
  position: fixed; top: .75rem; left: .75rem; z-index: 1000;
  transform: translateY(-160%);
  padding: .75rem 1rem; background: var(--rr-white); color: var(--rr-black);
  font: 700 .9rem/1 "Satoshi", Arial, sans-serif;
}
.rr-skip:focus { transform: none; }

/* Header */
.rr-header {
  position: fixed; z-index: 300; top: 0; left: 0; width: 100%; height: var(--rr-nav-h);
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 1.5rem;
  padding: 0 var(--rr-pad);
  border-bottom: 1px solid rgba(255, 255, 255, .08);
  background: rgba(0, 0, 0, .72);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  font-family: "Satoshi", Arial, sans-serif;
}
.rr-brand { display: flex; align-items: center; min-height: 2.75rem; width: clamp(9.5rem, 12vw, 12rem); }
.rr-brand img { width: 100%; height: auto; display: block; }
.rr-nav { display: flex; justify-content: center; gap: clamp(.9rem, 1.7vw, 2rem); }
.rr-nav-link {
  position: relative; display: inline-flex; align-items: center; min-height: 2.75rem;
  color: var(--rr-muted); font-size: .76rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; text-decoration: none; white-space: nowrap;
}
.rr-nav-link::after {
  content: ""; position: absolute; left: 0; bottom: .5rem; width: 100%; height: 1px;
  background: var(--rr-gold); transform: scaleX(0); transform-origin: left; transition: transform 180ms ease;
}
.rr-nav-link:hover, .rr-nav-link:focus-visible, .rr-nav-link[aria-current="page"] { color: var(--rr-white); }
.rr-nav-link:hover::after, .rr-nav-link:focus-visible::after, .rr-nav-link[aria-current="page"]::after { transform: scaleX(1); }
.rr-actions { display: flex; align-items: center; gap: .75rem; }
/* Skip-animation toggle, header, homepage only (mounted conditionally in
   chrome.js's headerMarkup()). Very subtle on purpose -- a ghost pill that
   barely draws the eye next to the gold CTA, fills in slightly on
   hover/focus. Visibility (shown until the finish section, hidden/inert
   after, back on scroll-up, always shown in calm mode) is driven by
   updateHeaderMotionToggle() in main.js via the .is-hidden class; label and
   click wiring come for free from the existing [data-motion-toggle] system. */
.rr-skip-toggle {
  display: inline-flex; align-items: center; justify-content: center; min-height: 2.75rem;
  padding: .55rem .95rem; border: 1px solid rgba(255, 255, 255, .16); border-radius: 999px;
  background: transparent; color: rgba(255, 255, 255, .42); cursor: pointer; white-space: nowrap;
  font: 700 .68rem/1 "Satoshi", Arial, sans-serif; letter-spacing: .07em; text-transform: uppercase;
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease, opacity 220ms ease;
}
.rr-skip-toggle:hover, .rr-skip-toggle:focus-visible {
  background: rgba(255, 255, 255, .07); color: var(--rr-white); border-color: rgba(255, 255, 255, .32);
}
.rr-skip-toggle.is-hidden { opacity: 0; pointer-events: none; }
@media (max-width: 600px) { .rr-skip-toggle { display: none; } }

.rr-btn {
  display: inline-flex; align-items: center; justify-content: center; min-height: 2.75rem;
  padding: .6rem 1.1rem; border: 1px solid transparent; border-radius: 999px; cursor: pointer;
  font: 700 .74rem/1 "Satoshi", Arial, sans-serif; letter-spacing: .09em; text-transform: uppercase;
  text-decoration: none; white-space: nowrap; position: relative; overflow: hidden;
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
}
.rr-btn::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: -30%; width: 30%; pointer-events: none;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .5), transparent);
  transform: skewX(-18deg) translateX(-160%); transition: transform .75s ease;
}
.rr-btn:hover::after { transform: skewX(-18deg) translateX(560%); }
.rr-btn-gold { background: var(--rr-gold); color: var(--rr-black); border-color: var(--rr-gold); }
.rr-btn-gold:hover {
  background: transparent; color: var(--rr-gold); transform: translateY(-2px);
  box-shadow: 0 0 0 1px rgba(212, 167, 44, .35), 0 0 28px rgba(212, 167, 44, .4);
}
.rr-btn-gold:active { background: var(--rr-gold-pressed); color: var(--rr-black); transform: none; box-shadow: none; }
.rr-menu-btn {
  display: none; min-height: 2.75rem; padding: .5rem .3rem; border: 0; background: none; cursor: pointer;
  color: var(--rr-white); font: 700 .8rem/1 "Satoshi", Arial, sans-serif; letter-spacing: .06em; text-transform: uppercase;
}
.rr-header :focus-visible, .rr-menu :focus-visible, .rr-footer :focus-visible { outline: 2px solid var(--rr-gold); outline-offset: 3px; }

/* Mobile menu */
.rr-menu {
  position: fixed; z-index: 400; inset: 0; display: none; overflow-y: auto;
  padding: 1.25rem; background: var(--rr-black); font-family: "Satoshi", Arial, sans-serif;
}
.rr-menu.is-open { display: block; }
.rr-menu-head { display: flex; align-items: center; justify-content: space-between; }
.rr-menu-head img { width: 8rem; height: auto; }
.rr-menu-head button {
  min-height: 2.75rem; padding: .5rem .75rem; border: 0; background: none; cursor: pointer;
  color: var(--rr-white); font: 700 .85rem/1 "Satoshi", Arial, sans-serif; text-transform: uppercase;
}
.rr-menu nav { display: grid; margin-top: 2.5rem; }
.rr-menu-link {
  padding: .8rem 0; border-bottom: 1px solid var(--rr-line); color: var(--rr-white); text-decoration: none;
  font-family: "Clash Display", Arial, sans-serif; font-size: clamp(1.5rem, 7vw, 2rem); font-weight: 600; text-transform: uppercase;
}
.rr-menu-link[aria-current="page"] { color: var(--rr-gold); }
.rr-menu-cta { justify-self: start; margin-top: 1.75rem; }

/* Footer */
.rr-footer {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: 1.4fr .7fr .7fr 1fr; gap: 3rem; align-items: start;
  padding: 5rem var(--rr-pad); border-top: 1px solid var(--rr-line); background: var(--rr-black);
  color: var(--rr-white); font: 400 .88rem/1.6 "Satoshi", Arial, sans-serif;
}
.rr-footer a { color: inherit; text-decoration: none; }
.rr-footer p { margin: 0; }
.rr-footer-brand img { width: min(13rem, 100%); height: auto; display: block; }
.rr-footer-brand > p { max-width: 24rem; margin-top: 1.1rem; color: var(--rr-muted); font-size: .85rem; }
.rr-social { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.4rem; }
.rr-social-link {
  display: grid; place-items: center; width: 2.75rem; height: 2.75rem; border: 1px solid rgba(255, 255, 255, .18); border-radius: 50%;
  transition: border-color 200ms ease, color 200ms ease, transform 200ms ease;
}
.rr-social-link:hover { border-color: var(--rr-gold); color: var(--rr-gold); transform: translateY(-2px); }
.rr-social-link svg { width: 1.05rem; height: 1.05rem; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.rr-footer-brand .rr-footer-note { margin-top: 1rem; color: var(--rr-meta); font-size: .78rem; }
/* Round 8 (A2 item 7): was `display:grid` with no columns, so the default
   one-per-row auto-flow plus a 2.75rem min-height per link (a touch target
   sized for mobile tapping) made each 5-link column read as a tall vertical
   list -- exactly what Dylan called "too vertical." Links wrap as an inline
   row instead; the touch-friendly min-height only matters on the phone
   footer (unchanged, its own separate rules below still apply the tall
   list there). */
.rr-footer-nav { display: flex; flex-wrap: wrap; gap: .35rem 1.25rem; }
.rr-footer-nav p, .rr-footer-meta p:first-child {
  flex: 1 0 100%; margin-bottom: .35rem; color: var(--rr-gold); font-size: .7rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
}
.rr-footer-nav a, .rr-footer-meta a {
  display: inline-flex; align-items: center; width: fit-content; min-height: 2rem;
  border-bottom: 1px solid transparent; transition: color 180ms ease, border-color 180ms ease;
}
.rr-footer-nav a:hover, .rr-footer-meta a:hover { color: var(--rr-gold); border-color: var(--rr-gold); }
.rr-footer-meta { display: grid; gap: .4rem; color: var(--rr-muted); font-size: .82rem; }
/* B6: the finish line at the very bottom of the footer, like Website Blue's
   own footer-tail, in gold/white on black (no blue). */
/* Round 5: the painted FINISH LINE text sits in the bottom ~25% of
   182.jpg (1280x720); at 100%-width/auto-height the scaled image is much
   taller than this short band, so position-y needs to bias hard toward the
   bottom of the image to keep the text in the visible window, not the
   blank asphalt above it. */
/* Round 7 (A2 F1): the band used to start 3rem below the footer grid AND
   hide its artwork behind a 55% black plateau with the image pushed down, so
   the letters sat ~250px below the last text line. Now the band starts 28px
   below the last footer text (top margin = 28px minus the grid's own row
   gap, which is 3rem here, 2.5rem/2rem on smaller screens), and the image
   is positioned so the painted stripe sits ~8px under the band's top edge
   (background-position-y = 8px minus 38.6vw, where 38.6vw is the stripe's
   depth in the image at this width: 68.6% of a 16:9 frame). The band is as
   tall as the artwork (13.2vw) plus room for the fade. */
.rr-footer-tail { grid-column: 1 / -1; position: relative; height: calc(13.2vw + 5rem); min-height: 12rem; margin: calc(28px - 3rem) calc(var(--rr-pad) * -1) -5rem; overflow: hidden; }
.rr-footer-tail-img {
  position: absolute; inset: 0; background: url('assets/seq2/finish/182.jpg') 50% calc(8px - 38.6vw) / 100% auto no-repeat;
  /* Round 5 (item 5): "barely visible, like a faint watermark" -- was .16,
     which still read clearly after three rounds of gradient-only fixes.
     Dropping the image's own opacity this far is the direct fix for
     "subtle"; the gradient below is what removes the edge. */
  /* Round 13 (Dylan direct): at .07 under a 40%-black overlay it had
     disappeared entirely. Faint but findable: the words read, softly. */
  opacity: .28; filter: grayscale(1) brightness(1.1) sepia(0.3) hue-rotate(-10deg);
}
/* B5: Website Blue keeps its footer-tail image at .15 opacity with a dark
   gradient over the whole band (its own .footer-tail::before), so the
   FINISH LINE text stays faint, not bold. Ours was .28 with the gradient's
   bottom stop nearly transparent (.1), so the text -- which sits in the
   image's bottom band -- came through far stronger than Blue's. Matched the
   image opacity to Blue's and raised the gradient's bottom stop so the
   overlay still covers the text there instead of clearing right before it. */
/* Round 4 (item 3): a 3-stop gradient with a sharp slope change at 35% (from
   .5 alpha at 0% down to .35 by 35%, then flat) reads as a visible edge right
   at that inflection point. Widened the band's own height (26vh -> 34vh, one
   more step toward Blue's 36vh) and spread the falloff across five evenly
   stepped stops instead, so the rate of change is gradual start to finish --
   no single point where the slope suddenly changes -- solid footer black at
   the very top, easing down to the faint see-through overlay at the bottom. */
/* Round 4 (item 3) again: the 5-stop version above still read as an edge --
   piecewise-linear gradients change SLOPE at every stop, and each of those
   rate changes is its own small kink even when the color deltas are smooth.
   A pure 2-stop gradient has exactly one slope, start to finish -- no point
   anywhere the rate changes, so there is nothing left to read as a line. */
/* Round 5 (item 5): still visible. The 2-stop taper's rate-of-change was
   constant, but it started reacting to the image at 0% -- right at the seam
   with the footer's own flat solid background above it, so the transition
   FROM flat-nothing TO a taper was itself the edge, no matter how smooth the
   taper's own slope was. Fixed at the source: a real flat black plateau
   (0-55%, identical to the footer's own background, mathematically zero
   change) that only starts easing well past halfway down the band ("fading
   over most of its height," not from the very top), landing on a faint
   overlay -- not a hard stop -- at the bottom. */
/* Round 11 addendum: widening this gradient's plateau (34% attempt below)
   changed nothing on screen -- because .rr-footer-tail-img is real DOM
   content that comes AFTER this ::before in the markup, it paints on TOP of
   the overlay, not under it. The overlay was darkening a layer nothing sat
   on top of. Moved to ::after (pseudo-elements without z-index still stack
   above real prior siblings in paint order), so it now actually sits over
   the image and can hide the abrupt seam where the image's own road/lane
   content (182.jpg, opacity .07) pops in at the tail's top edge (measured:
   0,0,0 at the boundary jumping to 15,14,13 within 8px). Solid black for the
   top third, matching the footer's own flat black above it, then eases to
   the faint bottom overlay so the finish line stays visible lower down. */
.rr-footer-tail::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  /* Round 14 (Dylan item 7): the 22% solid plateau + .72 midpoint sat right on
     top of the painted FINISH LINE letters (they live in the band's 20-60%),
     so the words were covered. Shorter plateau (seam stays hidden) and a lower
     overlay across the letters, so they read as just barely visible. */
  background: linear-gradient(to bottom, var(--rr-black) 0, var(--rr-black) 10%, rgba(10, 10, 10, .66) 26%, rgba(10, 10, 10, .5) 55%, rgba(10, 10, 10, .12) 100%);
}

/* Assistant: the gold orb and its panel */
.chat-bubble {
  position: fixed; bottom: 24px; right: 24px; z-index: 410; width: 62px; height: 62px; border-radius: 50%; border: none;
  cursor: pointer; color: var(--rr-gold); padding: 0; isolation: isolate; display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 32% 26%, #1F1F1F 0%, #0A0A0A 42%, #000000 100%);
  box-shadow: 0 14px 34px rgba(0, 0, 0, .55), 0 0 0 1px rgba(212, 167, 44, .55), 0 0 26px rgba(212, 167, 44, .28), inset 0 1px 0 rgba(255, 255, 255, .18), inset 0 -10px 18px rgba(0, 0, 0, .55);
  transition: transform .3s ease, box-shadow .3s ease;
}
.chat-orb-halo {
  position: absolute; inset: -10px; border-radius: 50%; z-index: -1; pointer-events: none;
  background: radial-gradient(circle, rgba(212, 167, 44, .34), rgba(212, 167, 44, 0) 68%);
  animation: rrOrbBreath 3.2s ease-in-out infinite;
}
.chat-orb-ring {
  position: absolute; inset: -3px; border-radius: 50%; pointer-events: none;
  background: conic-gradient(from 0deg, rgba(212, 167, 44, 0) 0deg, rgba(212, 167, 44, .95) 70deg, rgba(255, 236, 190, .95) 95deg, rgba(212, 167, 44, 0) 150deg, rgba(212, 167, 44, 0) 360deg);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
  animation: rrOrbSpin 5s linear infinite;
}
@keyframes rrOrbBreath { 0%, 100% { transform: scale(.92); opacity: .55; } 50% { transform: scale(1.12); opacity: 1; } }
@keyframes rrOrbSpin { to { transform: rotate(360deg); } }
.chat-bubble:hover { transform: translateY(-3px) scale(1.05); }
/* B6: raised only while the footer-tail band is on screen (class set by an
   IntersectionObserver in chrome.js), so the orb clears the FINISH LINE
   letters there without moving on every other page/scroll position. Height
   matches the tail's own min-height plus a margin so the bubble sits above
   the whole band, not just above the text line inside it. */
.chat-bubble.is-above-footer-tail { bottom: calc(11rem + 1.5rem); }
/* Dylan direct: the hero's start/finish progress bar (.race-line, styles.css)
   is `position: fixed; bottom: 1.1rem`, right at the page edge same as the
   bubble -- its "Finish" label was sitting under the bubble's bottom-left
   corner (confirmed live: bar top ~35px from viewport bottom, bubble's own
   default box already spans 24-86px up, fully swallowing it). Raised only
   while the bar is actually on (toggled by chrome.js, same pattern as
   is-above-footer-tail), so every other scroll position keeps the normal
   bottom-right spot. Desktop/tablet only -- .race-line is display:none on
   phone (styles.css, phone block), so this class is never toggled there. */
.chat-bubble.is-above-race-line { bottom: 4rem; }
.chat-bubble-icon { width: 26px; height: 26px; filter: drop-shadow(0 0 6px rgba(212, 167, 44, .55)); }
.chat-bubble-dot { position: absolute; top: 6px; right: 6px; width: 11px; height: 11px; border-radius: 50%; background: var(--rr-gold); border: 2px solid #000000; }
.help-panel {
  position: fixed; bottom: 98px; right: 24px; z-index: 405; width: 340px; max-width: calc(100vw - 32px);
  max-height: calc(100vh - 140px); max-height: calc(100dvh - 140px); overflow: auto;
  background: var(--rr-panel); border: 1px solid var(--rr-line); border-radius: 12px; padding: 24px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .5); color: var(--rr-white); font-family: "Satoshi", Arial, sans-serif;
  opacity: 0; visibility: hidden; transform: translateY(12px); transition: opacity .2s ease, transform .2s ease, visibility .2s ease;
}
.help-panel.open { opacity: 1; visibility: visible; transform: none; }
.help-panel .eyebrow { margin: 0; color: var(--rr-gold); font-size: .75rem; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; }
.help-close {
  position: absolute; top: 8px; right: 8px; width: 44px; height: 44px; padding: 0; border: none; background: none;
  color: var(--rr-muted); cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.help-close:hover { color: var(--rr-gold); }
.help-close svg { width: 16px; height: 16px; }
.help-qa { margin: 16px 0 0; }
.help-qa-item { margin-bottom: 16px; border-top: 1px solid var(--rr-line); padding-top: 14px; }
.help-qa-item:first-child { border-top: none; padding-top: 0; }
.help-qa-item dt { font-weight: 700; font-size: 14px; margin-bottom: 6px; }
.help-qa-item dd { margin: 0; font-size: 13px; line-height: 1.5; color: var(--rr-muted); }
.help-qa-item a { color: var(--rr-gold); }
.help-live-note { margin: 8px 0 0; font-size: 12px; color: var(--rr-meta); }

@media (max-width: 74rem) {
  .rr-nav, .rr-cta { display: none; }
  .rr-header { grid-template-columns: 1fr auto; }
  .rr-menu-btn { display: block; }
}
@media (max-width: 68rem) {
  .rr-footer { grid-template-columns: 1fr 1fr; }
  .rr-footer-brand, .rr-footer-meta { grid-column: 1 / -1; }
}
@media (max-width: 44rem) {
  :root { --rr-nav-h: 4.25rem; }
  .rr-header { gap: .5rem; padding: 0 .85rem; }
  .rr-brand { width: 7rem; }
  .rr-actions { gap: .35rem; }
  .rr-menu-btn { padding: .5rem .35rem; font-size: .78rem; }
  .rr-footer { gap: 2.5rem; padding: 4rem var(--rr-pad) 6rem; }
  .rr-footer-tail { margin-top: calc(28px - 2.5rem); }
  .chat-bubble { right: 16px; bottom: 16px; width: 52px; height: 52px; }
  .chat-bubble-icon { width: 23px; height: 23px; }
  .help-panel { right: 16px; bottom: 80px; }
}
.is-calm .chat-orb-halo, .is-calm .chat-orb-ring { animation: none; }
/* Spam honeypot: invisible to sighted and screen-reader users, present for
   bots that fill every field. Never remove from the tab order via display
   alone since some scrapers skip display:none — off-screen + tabindex=-1. */
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
@media (prefers-reduced-motion: reduce) { .chat-orb-halo, .chat-orb-ring { animation: none; } }

/* Marketing-consent checkbox, shared across every form on every page (chrome.css
   loads everywhere). rr- prefixed so it is safe to reuse on the homepage forms
   with the same markup. Native checkbox + accent-color instead of a custom
   pseudo-element widget: it already renders gold-filled with no extra markup. */
.rr-consent {
  display: flex; align-items: flex-start; gap: .65rem; min-height: 2.75rem; padding: .35rem 0;
  cursor: pointer; font: 400 .82rem/1.45 "Satoshi", Arial, sans-serif; color: var(--rr-muted);
}
.rr-consent .rr-consent-input {
  flex: none; display: inline-block; width: 1.2rem; max-width: 1.2rem; height: 1.2rem; margin: .15rem 0 0;
  accent-color: var(--rr-gold); cursor: pointer;
}
.rr-consent-input:focus-visible { outline: 2px solid var(--rr-gold); outline-offset: 3px; }
.rr-consent-text { flex: 1 1 auto; }
/* Consent copy is a paragraph, not a form label: beat the uppercase .field label style globally. */
.field label.rr-consent, label.rr-consent { text-transform: none; letter-spacing: normal; font-size: .8rem; font-weight: 400; line-height: 1.45; color: var(--rr-muted); }
.rr-consent-text a { color: var(--rr-gold); text-decoration: underline; text-underline-offset: .18em; }
.rr-sms-note { margin: 0; font: 400 .8rem/1.45 "Satoshi", Arial, sans-serif; color: var(--rr-muted); }

/* ===== PHONE (<=600px): global chrome (header, menu, chat bubble) =====
   Phase 2 mobile spec. This is its own block, not more overrides stacked on
   the 44rem breakpoint above (which stays, unchanged, for 601-704px) -- the
   phone width JS gate is main.js's PHONE = matchMedia('(max-width:600px)').
   Desktop/laptop/tablet and calm mode are untouched by anything below. */
@media (max-width: 600px) {
  /* Round 9, item 1: solid black (not translucent) so the film starting
     right below it never shows through the header's blur, a bit taller so
     the media window itself can grow, logo a bit bigger. */
  :root { --rr-nav-h: 66px; }
  .rr-header {
    height: 66px; padding: 0 20px; background: #000;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .rr-brand { width: 7rem; }
  /* Round 12, item 2: header logo swipes in from the left as the intro video
     starts. Film-mode only (html:not(.is-calm)) -- calm has no video/load
     moment, and an animation's `to{transform:none}` keyframe target makes
     getComputedStyle report an explicit identity matrix forever after
     (a browser quirk of fill-mode:both), which reads as a real diff against
     calm-base.json's plain `none` even once fully settled -- calm never
     needs this animation, so it's simplest to just not run it there. */
  html:not(.is-calm) .rr-brand { animation: rrBrandSwipeIn 550ms ease both; }
  @keyframes rrBrandSwipeIn {
    from { opacity: 0; transform: translateX(-1.25rem); }
    to { opacity: 1; transform: none; }
  }
  .rr-menu-btn { min-height: 44px; padding: .6rem; }
  .rr-actions { gap: .5rem; }

  /* Menu sheet: full-screen, 7 links + CTA, 56px rows (44px min tap target,
     56px per spec), safe-area padding top/bottom. */
  .rr-menu { padding: 20px; padding-top: max(20px, env(safe-area-inset-top)); padding-bottom: max(20px, env(safe-area-inset-bottom)); }
  .rr-menu-head img { width: 7rem; }
  .rr-menu-head button { min-height: 44px; }
  .rr-menu nav { margin-top: 2rem; }
  .rr-menu-link { min-height: 56px; padding: 0; display: flex; align-items: center; font-size: 1.4rem; }
  .rr-menu-cta { width: 100%; margin-top: 1.25rem; }
  .rr-menu-cta.rr-btn { width: 100%; min-height: 48px; }

  /* Round 9 (A2 item 14): Dylan wants the link columns BELOW the finish-line
     band on phone, laid out horizontally -- was the reverse (links above the
     band, one vertical column per group). grid-template-areas reorders the
     four blocks without touching the HTML (chrome.js emits them in the same
     order every breakpoint reads): brand+tail come first now, links after.
     Desktop's own horizontal nav (this round's earlier fix) is untouched --
     that lives outside this @media block. */
  .rr-footer {
    padding: 3rem 20px calc(3rem + env(safe-area-inset-bottom)); gap: 1.5rem 1rem;
    grid-template-columns: 1fr 1fr;
    /* Round 12 (A2 item 21): tail moved from 2nd to LAST -- Dylan wants the
       finish-line band at the very bottom of the footer, below the link
       columns AND the copyright/"preview build" meta line, not sandwiched
       between brand and the links. */
    grid-template-areas: "brand brand" "nav1 nav2" "meta meta" "tail tail";
  }
  .rr-footer-brand { grid-column: 1 / -1; grid-area: brand; }
  .rr-footer-tail { grid-area: tail; }
  .rr-footer-nav:nth-of-type(1) { grid-area: nav1; }
  .rr-footer-nav:nth-of-type(2) { grid-area: nav2; }
  .rr-footer-meta { grid-area: meta; }
  /* Links read as compact horizontal rows in their (now narrower, 2-col)
     group instead of one long vertical list. */
  .rr-footer-nav { display: flex; flex-wrap: wrap; gap: .3rem .9rem; }
  .rr-footer-nav a { min-height: 2rem; }
  /* Round 6 (A2 item 5): Dylan wants the finish-line band "a little bigger
     and higher" -- taller (20vh -> 24vh, min 8rem -> 9.5rem) and pulled up
     closer to the meta row above it (top margin 2rem -> 1.25rem) so it reads
     as its own moment instead of a thin afterthought. The gradient overlay
     (::before, above) is percentage-based against the band's own height, so
     it stays just as soft at the new size; is-above-footer-tail's bubble
     clearance (8rem + 1.5rem) already has real margin over a 9.5rem-tall
     band. */
  /* Round 7 F1 (phone): band starts 28px under the last footer line (row gap
     here is 2rem), artwork scaled to 130% width so the painted line is
     readable at phone size (stripe depth = 68.6% of a 16:9 frame at 130%
     width = 50.2vw), stripe ~10px under the top edge. */
  /* Round 12: bottom margin now cancels .rr-footer's own bottom padding
     (was -4rem, tuned to pull a sibling below it up over the gap when tail
     sat 2nd -- now that tail is the LAST grid item, that sibling doesn't
     exist, so the same negative value would just clip the band's own
     bottom against nothing). Bleeds the band flush to the viewport's
     bottom edge instead, which is what "the very bottom" means now. */
  .rr-footer-tail { height: 8.5rem; min-height: 0; margin: calc(28px - 2rem) -20px calc(-3rem - env(safe-area-inset-bottom)); }
  .rr-footer-tail-img { background-size: 130% auto; background-position: 50% calc(10px - 50.2vw); }

  /* Chat bubble: 52px/16px-from-edge already set at 44rem; add safe-area and
     the two new phone behaviors -- hidden while a form is on screen/focused
     (is-hidden-form, toggled from main.js), and opening it is a bottom sheet
     instead of a floating popover. */
  .chat-bubble { right: calc(16px + env(safe-area-inset-right)); bottom: calc(16px + env(safe-area-inset-bottom)); }
  .chat-bubble.is-above-footer-tail { bottom: calc(8rem + 1.5rem + env(safe-area-inset-bottom)); }
  .chat-bubble.is-hidden-form { opacity: 0; transform: scale(.82); pointer-events: none; }
  .help-panel {
    left: 0; right: 0; bottom: 0; width: 100%; max-width: none;
    max-height: 80svh; border-radius: 20px 20px 0 0;
    padding: 20px; padding-bottom: max(20px, calc(env(safe-area-inset-bottom) + 12px));
    transform: translateY(100%);
  }
  .help-panel.open { transform: translateY(0); }
  .help-close { top: 12px; right: 12px; width: 44px; height: 44px; }

  .rr-consent { min-height: 44px; }
}

/* ===== Signup popup (chrome.js signupPopup) ===== */
.rr-pop-root { position: fixed; inset: 0; z-index: 900; pointer-events: none; font-family: "Satoshi", Arial, sans-serif; }
.rr-pop-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .6); opacity: 0; transition: opacity 220ms ease; pointer-events: auto; }
.rr-pop {
  position: absolute; left: 50%; top: 50%; width: min(30rem, calc(100vw - 2rem)); padding: 1.75rem;
  transform: translate(-50%, -46%); opacity: 0; transition: opacity 220ms ease, transform 220ms ease; pointer-events: auto;
  background: var(--rr-panel); border: 1px solid var(--rr-line); border-top: 2px solid var(--rr-gold); color: var(--rr-white); outline: none;
}
.rr-pop-root.is-open .rr-pop-backdrop { opacity: 1; }
.rr-pop-root.is-open .rr-pop { opacity: 1; transform: translate(-50%, -50%); }
.rr-pop-x { position: absolute; top: .5rem; right: .5rem; width: 2.75rem; height: 2.75rem; display: grid; place-items: center; background: none; border: 0; color: var(--rr-muted); cursor: pointer; }
.rr-pop-x:hover { color: var(--rr-gold); }
.rr-pop-x:focus-visible, .rr-pop a:focus-visible, .rr-pop input:focus-visible, .rr-pop-submit:focus-visible { outline: 2px solid var(--rr-gold); outline-offset: 3px; }
.rr-pop-x svg { width: 1.2rem; height: 1.2rem; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; }
.rr-pop-eyebrow { margin: 0 0 .4rem; color: var(--rr-gold); font-size: .7rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }
.rr-pop-title { margin: 0 0 1rem; padding-right: 2rem; font: 600 1.5rem/1.15 "Clash Display", "Satoshi", Arial, sans-serif; }
.rr-pop-row { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }
.rr-pop input[type=text], .rr-pop input[type=email] {
  width: 100%; min-width: 0; height: 2.75rem; padding: 0 .8rem; background: #000; color: var(--rr-white);
  border: 1px solid rgba(255, 255, 255, .2); border-radius: 0; font: 400 .95rem "Satoshi", Arial, sans-serif;
}
.rr-pop .rr-consent { padding: .25rem 0; min-height: 0; font-size: .78rem; }
.rr-pop-submit { width: 100%; height: 2.75rem; margin-top: .35rem; cursor: pointer; }
.rr-pop-status { min-height: 1.2em; margin: .5rem 0 0; font-size: .82rem; color: var(--rr-muted); }
.rr-pop-join { margin: .4rem 0 0; font-size: .85rem; color: var(--rr-muted); }
.rr-pop-join a { color: var(--rr-gold); text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 600px) {
  .rr-pop-backdrop { background: rgba(0, 0, 0, .35); }
  /* Bottom sheet, lifted clear of the chat bubble (bottom right, 20px + ~60px). */
  .rr-pop { left: .75rem; right: .75rem; top: auto; bottom: 5.5rem; width: auto; padding: 1rem 1rem .75rem; transform: translateY(20px); }
  .rr-pop-root.is-open .rr-pop { transform: none; }
  .rr-pop-title { margin-bottom: .6rem; font-size: 1.2rem; }
  .rr-pop-eyebrow { margin-bottom: .2rem; }
  .rr-pop-row { grid-template-columns: 1fr; gap: .4rem; }
  .rr-pop .rr-consent { font-size: .72rem; line-height: 1.3; }
  .rr-pop-status:empty { display: none; }
  .rr-pop-join { margin-top: .2rem; font-size: .8rem; }
}
.rr-reg-note { margin: .6rem 0 0; font-size: .82rem; color: var(--rr-muted); }
.rr-reg-skip { display: block; margin-top: .7rem; padding: .7rem 1rem; text-align: center; font-weight: 700; font-size: .95rem; color: var(--rr-white); border: 1px solid rgba(255, 255, 255, .35); text-decoration: none; }
.rr-reg-skip:hover { border-color: var(--rr-gold); color: var(--rr-gold); }
.rr-reg-skip:focus-visible { outline: 2px solid var(--rr-gold); outline-offset: 3px; }
@media (max-width: 600px) { .rr-reg-note { font-size: .74rem; margin-top: .4rem; } .rr-reg-skip { margin-top: .5rem; padding: .6rem 1rem; } }
@media (prefers-reduced-motion: reduce) { .rr-pop, .rr-pop-backdrop { transition: none; } .rr-pop { transform: translate(-50%, -50%); } }
@media (prefers-reduced-motion: reduce) and (max-width: 600px) { .rr-pop { transform: none; } }

/* Round 2 phone pass, inner pages only (body.page-body; the homepage footer
   is left exactly as it was). Footer links clear 44px, and the legal row
   drops its text-node middots (font-size 0 hides them) so a wrapped row never
   strands a dangling separator before "Text alerts". */
@media (max-width: 600px) {
  body.page-body .rr-footer-nav a { min-height: 2.75rem; }
  body.page-body .rr-footer-meta p:nth-of-type(3),
  body.page-body .rr-footer-meta p:nth-of-type(4) { font-size: 0; }
  body.page-body .rr-footer-meta p:nth-of-type(3) a,
  body.page-body .rr-footer-meta p:nth-of-type(4) a { font-size: .82rem; min-height: 2.75rem; margin-right: 1.1rem; }
}
