/* ==========================================================================
   Vaux — Group Trip marketing landing page
   Built from design_handoff_landing_page. Values are lifted from the handoff;
   see README.md for the deviations and why.
   ========================================================================== */

/* --- Fonts ---------------------------------------------------------------
   Lexend + Manrope come from Google Fonts, loaded in the document head.
   They MUST be loaded explicitly — nothing else imports them, and if they go
   missing everything silently falls back to system UI. */

@font-face {
  font-family: 'Jokker';
  src: url('../fonts/Jokker-Medium.woff2') format('woff2'),
       url('../fonts/Jokker-Medium.woff') format('woff');
  font-weight: 500;
  font-display: swap;
}

@font-face {
  font-family: 'Timeburner';
  src: url('../fonts/timeburnerbold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}

/* --- Tokens -------------------------------------------------------------- */

:root {
  /* Muted lavender, taken from the globe's own arcs and stamp plates
     (#A9A5D0 / #9A97AE / #CECEDB — the last is Vaux's dark-mode accent).

     Two earlier passes are worth not repeating. The handoff's warm cream and
     terracotta fought the globe once it became the hero. Replacing it with the
     globe's indigo stamp ink (#474C7D) was too saturated at button and node
     size — it read as a third colour competing with the hero, and cheap.

     The fix that mattered was not hue but treatment: depth here comes from a
     bright lit edge, a hard outer line and a real cast shadow, never from a
     soft three-stop gradient. Keep that if the hue ever moves again. */
  --canvas: #EDEBF3;
  --ink: #0B0B0D;
  --ink-deep: #2F2B40;
  --ink-mid: #443F5B;
  --text-mid: #5C5773;
  --text-muted: #6E6987;
  --text-dim: #ABA6BE;
  --accent: #7E7AA8;
  --accent-deep: #5A5680;
  --lavender: #CECEDB;
  --hairline: rgba(110, 106, 133, 0.18);

  --dark-button: #0B0B0D;
  --silver-button: linear-gradient(178deg, #FFFFFF 0%, #E6E8EE 50%, #C0C4D0 100%);
  --ease: cubic-bezier(0.25, 0.8, 0.25, 1);

  /* The phone renders at a fixed 298 x 588 and is scaled as one unit.
     Nothing inside it reflows — see README, "the phone is an art object". */
  --phone-scale: 1;
  --screen-w: 298px;
  --screen-h: 588px;
}

/* --- Reset --------------------------------------------------------------- */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--canvas);
}

body {
  font-family: 'Manrope', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { text-decoration: none; color: inherit; }
button { font: inherit; border: 0; background: none; cursor: pointer; }

/* --- Animations ----------------------------------------------------------
   mkFill and mkTap are documented in the handoff as unused leftovers, but the
   prototype does use them (stay-coverage bar, settle button). Kept. */

@keyframes mkFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-9px); }
}
@keyframes mkGlow {
  0%, 100% { opacity: 0.5;  transform: scale(0.94); }
  50%      { opacity: 0.85; transform: scale(1.04); }
}
@keyframes mkSheen {
  0%        { transform: translateX(-140%) rotate(14deg); }
  55%, 100% { transform: translateX(240%)  rotate(14deg); }
}
/* -52px = 2 x the 26px pattern, so the loop is seamless. The prototype used
   -64px, which is not a multiple and visibly jumped every 26s. */
@keyframes mkDrift {
  0%   { transform: translate3d(0, 0, 0); }
  100% { transform: translate3d(0, -52px, 0); }
}
@keyframes mkPulse {
  0%   { transform: scale(0.5); opacity: 0.9; }
  70%  { transform: scale(1);   opacity: 0.1; }
  100% { transform: scale(1);   opacity: 0; }
}
@keyframes mkFill {
  0%        { width: 0%; }
  44%, 100% { width: 57%; }
}
@keyframes mkTap {
  0%, 62%, 78%, 100% { transform: scale(1); }
  70%                { transform: scale(0.965); }
}

/* --- Page shell ----------------------------------------------------------
   align-items: flex-start is load-bearing. Centering a fixed 1440px child in a
   narrower viewport splits the overflow evenly, and browsers cannot scroll into
   inline-start overflow — the left ~258px becomes unreachable.

   overflow: clip, NOT hidden. `hidden` makes this element the nearest scrollport
   for descendant sticky positioning; the phone then resolves to zero travel and
   degrades to static. `clip` still clips the dot overlay without creating a
   scroll container. */

.page {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 40px;
  padding: 40px 40px 88px;
  background-color: var(--canvas);
  background-image:
    radial-gradient(110% 74% at 18% -8%, rgba(150, 144, 195, 0.24) 0%, rgba(237, 235, 243, 0) 58%),
    radial-gradient(96% 62% at 90% 4%, rgba(206, 206, 219, 0.68) 0%, rgba(237, 235, 243, 0) 56%);
  overflow: clip;
}

.dots {
  position: absolute;
  inset: -80px 0 0 0;
  background-image: radial-gradient(rgba(126, 122, 168, 0.09) 1px, transparent 1px);
  background-size: 26px 26px;
  animation: mkDrift 26s linear infinite;
  pointer-events: none;
}

.artboard {
  position: relative;
  width: 1440px;
  margin: 0 auto;
  border: 1px solid rgba(255, 255, 255, 0.8);
  border-radius: 28px;
  background: rgba(252, 252, 254, 0.74);
  backdrop-filter: blur(40px) saturate(1.4);
  -webkit-backdrop-filter: blur(40px) saturate(1.4);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.95),
              0 34px 90px rgba(90, 86, 128, 0.14);
  overflow: clip;
}

/* --- Typography helpers -------------------------------------------------- */

.jokker {
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
}

/* Headlines are metallic, not flat — 172deg reads as light falling across
   brushed metal. Never apply this to body copy; the contrast loss hurts. */
.metal { color: #0B0B0D; }

/* --- Nav ----------------------------------------------------------------- */

.nav-row {
  display: flex;
  justify-content: center;
  padding: 22px 48px 0;
}

.nav-pill {
  position: relative;
  display: flex;
  align-items: center;
  gap: 30px;
  padding: 11px 12px 11px 24px;
  border: 1px solid rgba(255, 255, 255, 0.9);
  border-radius: 9999px;
  background: rgba(253, 253, 255, 0.84);
  backdrop-filter: blur(30px) saturate(1.6);
  -webkit-backdrop-filter: blur(30px) saturate(1.6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.98),
              0 14px 34px rgba(90, 86, 128, 0.14);
  overflow: hidden; /* clips the sheen sweep */
}

.sheen {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 50%, rgba(255, 255, 255, 0) 100%);
  pointer-events: none;
}

.nav-pill .sheen { width: 90px; animation: mkSheen 7s var(--ease) infinite; }

.wordmark {
  font-family: 'Timeburner', system-ui, sans-serif;
  font-weight: 700;
  font-size: 23px;
  letter-spacing: -0.16px;
  color: #0B0B0D;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 26px;
}

.nav-link {
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
  transition: color 200ms var(--ease);
}

.nav-link:hover { color: var(--ink-deep); }

.nav-link.is-active {
  padding: 8px 14px;
  border: 1px solid rgba(255, 255, 255, 0.9);
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.86);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 1), 0 1px 3px rgba(18, 17, 32, 0.12);
  color: var(--accent-deep);
}

/* Log in and Sign up are nested in their own group with a tight 8px gap so
   they read as a paired set rather than two unrelated nav items. */
.nav-auth {
  display: flex;
  align-items: center;
  gap: 8px;
}

.btn-ghost {
  display: flex;
  align-items: center;
  padding: 11px 19px;
  border: 1px solid rgba(45, 49, 70, 0.24);
  border-radius: 9999px;
  background: transparent;
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #2A211B;
  transition: background 200ms var(--ease);
}

.btn-ghost:hover { background: rgba(45, 49, 70, 0.06); }

.btn-dark-pill {
  display: flex;
  align-items: center;
  padding: 12px 21px;
  border: 0;
  border-radius: 9999px;
  background: var(--dark-button);
  box-shadow: 0 8px 20px rgba(11, 11, 13, 0.24);
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #FFFFFF;
  transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}

.btn-dark-pill:hover {
  transform: translateY(-1px);
  box-shadow: 0 12px 28px rgba(11, 11, 13, 0.3);
}

/* --- Hero row -------------------------------------------------------------
   The hero's visual is the globe. The phone starts lower, beside step 1 — it
   is the product tour's instrument, and leading with it before a visitor knows
   what Vaux is spends the reveal too early. */

.hero-row {
  display: flex;
  align-items: center;
  gap: 56px;
  padding: 48px 48px 24px;
}

.hero-copy {
  flex: 1 1 0;
  min-width: 0;
}

.hero-globe {
  flex: 0 0 clamp(380px, 38vw, 560px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  min-width: 0;
}

/* Square, so the sphere has the same room in both axes at every width. */
.globe-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  opacity: 0;
  transition: opacity 700ms var(--ease);
}

.globe-stage.is-ready { opacity: 1; }

/* No atlas, no globe — collapse the stage rather than leaving a hole. */
.globe-stage.is-failed { display: none; }

/* touch-action is the important one. Without pan-y, a vertical swipe starting
   on the globe is captured for rotation and the page cannot be scrolled at all
   on a phone — the visitor is simply stuck on the hero. This trades latitude
   dragging on touch for a page that scrolls, which is not a close call. */
.globe-stage canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
  touch-action: pan-y;
}

.globe-stage.is-dragging canvas { cursor: grabbing; }
.globe-stage.is-over-stamp canvas { cursor: pointer; }

.globe-hint {
  position: absolute;
  left: 50%;
  bottom: 2%;
  transform: translateX(-50%);
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-dim);
  pointer-events: none;
  transition: opacity 300ms var(--ease);
}

.globe-stage.is-dragging .globe-hint { opacity: 0; }

/* Anchored to the stamp it names, so it reads as a label on the globe rather
   than a floating tooltip. */
.globe-tip {
  position: absolute;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 7px 11px;
  transform: translate(-50%, -100%);
  border: 1px solid rgba(100, 116, 139, 0.18);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.95);
  box-shadow: 0 8px 22px rgba(71, 76, 125, 0.16);
  white-space: nowrap;
  pointer-events: none;
}

.globe-tip b {
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: 12px;
  letter-spacing: -0.1px;
  color: var(--ink);
}

.globe-tip i {
  font-style: normal;
  font-size: 10.5px;
  color: var(--text-muted);
}

.globe-stats {
  display: flex;
  align-items: baseline;
  gap: 30px;
}

.globe-stat {
  display: flex;
  align-items: baseline;
  gap: 7px;
}

.globe-stat-n {
  font-family: 'Lexend', system-ui, sans-serif;
  font-weight: 300;
  font-size: 21px;
  letter-spacing: -0.6px;
  color: var(--ink);
}

.globe-stat-l {
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* --- Tour row ------------------------------------------------------------ */

.tour-row {
  display: flex;
  align-items: flex-start;
  gap: 56px;
  padding: 60px 48px 88px;
}

/* The handoff put a 520px min-width here to guarantee the hero headline's
   three-line break. That backstop is what made the page non-adaptive: it gave
   the row a hard 1064px minimum (520 copy + 392 phone + 56 gap + 96 padding),
   and once the artboard was narrower than that the row overflowed and the
   artboard's `overflow: clip` sliced the phone in half. Silent — no scrollbar,
   no error, just a cut-off device.

   The copy column now absorbs all the flex instead. The headline break is
   handled by the font-size clamp below, which is the right tool for it. The
   only fixed width left in the row is the phone column, so the row's minimum
   is 544px and nothing can clip. */
.col-copy {
  flex: 1 1 0;
  min-width: 0;
}

/* 392px is load-bearing: 320px device + halos that extend past it. At 320px the
   device overflowed its column and the artboard's overflow: clip sliced the
   right side off. Do not reduce below ~380px without re-measuring. */
.col-phone {
  flex: 0 0 392px;
  position: sticky;
  top: 24px;
  display: flex;
  justify-content: center;
  padding: 8px 0;
}

/* --- Hero ---------------------------------------------------------------- */

.hero {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* The shield inherits the accent so it can never drift from the palette
   again — it was hard-coded terracotta. */
.trust-row { color: var(--accent); }

/* 62px is the design size and is what you get at 1440+. Below that it scales
   with the viewport rather than forcing the column to stay wide — that trade
   is what makes the page adaptive instead of clipping. */
.hero h1 {
  margin: 0;
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: clamp(42px, 4.4vw, 62px);
  line-height: 1.04;
  letter-spacing: -2.3px;
  text-wrap: pretty;
}

.hero-body {
  display: block;
  padding-top: 22px;
  max-width: 520px;
  font-size: 18px;
  line-height: 1.6;
  color: var(--ink-mid);
  text-wrap: pretty;
}

.hero-cta-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-top: 32px;
}

/* The button stays deliberately wide, but the label and arrow sit together at
   the left edge, aligned with the headline and body copy above them. Centred
   left the label floating with dead space on both sides; space-between pushed
   the two apart with a gap in the middle. Left-aligned, the whole hero column
   shares one edge. */
.btn-primary {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 14px;
  min-width: 340px;
  padding: 21px 30px;
  border: 0;
  border-radius: 10px;
  background: var(--dark-button);
  box-shadow: 0 12px 28px rgba(11, 11, 13, 0.28);
  overflow: hidden;
  transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}

.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 18px 38px rgba(11, 11, 13, 0.32);
}

.btn-primary .sheen {
  width: 70px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.34) 50%, rgba(255, 255, 255, 0) 100%);
  animation: mkSheen 5.5s var(--ease) infinite;
}

.btn-primary .btn-label,
.btn-primary svg { position: relative; }

.btn-label {
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #FFFFFF;
}

.sub-cta {
  display: block;
  padding-top: 14px;
  font-weight: 500;
  font-size: 14px;
  color: var(--text-mid);
}

.trust-row {
  display: flex;
  align-items: center;
  gap: 7px;
  padding-top: 26px;
}

.trust-row span {
  font-weight: 500;
  font-size: 13px;
  color: var(--text-muted);
}

/* --- Section heading ----------------------------------------------------- */

.section-head {
  display: flex;
  align-items: flex-end;
  gap: 48px;
  padding: 56px 0 8px;
}

.section-head h2 {
  flex: 1 1 0;
  min-width: 0; /* a flex item's auto minimum is its longest word — let it wrap */
  margin: 0;
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: clamp(30px, 2.9vw, 40px);
  line-height: 1.12;
  letter-spacing: -1.3px;
  color: #0B0B0D;
  text-wrap: pretty;
}

.section-aside {
  flex: 0 1 360px;
  min-width: 0;
  font-size: 16px;
  line-height: 1.6;
  color: var(--text-muted);
  text-wrap: pretty;
}

/* --- Steps ---------------------------------------------------------------
   Inactive is the default state. The active step is lit by the [data-step]
   rules below. The handoff's prototype snapped these colors with no
   transition; 250ms is the documented production fix. */

.step {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 560px;
  padding: 28px 0;
}

/* The last step needs a taller block than the rest. Sticky positioning ends
   with its container, so if step 5 is the same height as the others the phone
   starts sliding away the moment step 5 lights up — the Split screen would be
   the one screen nobody gets to read. The extra height buys the pin ~450px of
   scroll after step 5 activates. */
.step[data-n="6"] { min-height: 900px; }

.step-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 20px;
}

.step-node {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  border: 1px solid var(--hairline);
  border-radius: 9999px;
  background: rgba(253, 253, 255, 0.74);
  box-shadow: none;
  font-family: 'Lexend', system-ui, sans-serif;
  font-weight: 300;
  font-size: 14px;
  color: var(--text-dim);
  transition: background 250ms var(--ease), border-color 250ms var(--ease),
              box-shadow 250ms var(--ease), color 250ms var(--ease);
}

.step-tab {
  flex: 0 0 auto;
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-dim);
  transition: color 250ms var(--ease);
}

.step-rule {
  flex: 1 1 auto;
  height: 1px;
  background: var(--hairline);
  transition: background 250ms var(--ease);
}

.step h3 {
  display: block;
  max-width: 520px;
  margin: 0;
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: clamp(27px, 2.6vw, 36px);
  line-height: 1.13;
  letter-spacing: -1.2px;
  color: rgba(24, 24, 27, 0.24);
  text-wrap: pretty;
  transition: color 250ms var(--ease);
}

.step-body {
  display: block;
  padding-top: 16px;
  max-width: 500px;
  font-size: 17px;
  line-height: 1.62;
  color: rgba(24, 24, 27, 0.22);
  text-wrap: pretty;
  transition: color 250ms var(--ease);
}

.step-points {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 22px;
  margin: 0;
  list-style: none;
}

.step-points li {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  max-width: 471px;
  font-size: 15px;
  line-height: 1.55;
  color: rgba(24, 24, 27, 0.22);
  transition: color 250ms var(--ease);
}

.tick {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 21px;
  height: 21px;
  margin-top: 1px;
  border-radius: 9999px;
  background: rgba(100, 116, 139, 0.09);
  transition: background 250ms var(--ease);
}

.tick svg { stroke: var(--text-dim); transition: stroke 250ms var(--ease); }

/* Active step. Five explicit pairs — the whole left column dims except the
   current step, which lights up with a glowing terracotta node. */
#tour[data-step="1"] .step[data-n="1"] .step-node,
#tour[data-step="2"] .step[data-n="2"] .step-node,
#tour[data-step="3"] .step[data-n="3"] .step-node,
#tour[data-step="4"] .step[data-n="4"] .step-node,
#tour[data-step="5"] .step[data-n="5"] .step-node,
#tour[data-step="6"] .step[data-n="6"] .step-node {
  background: #0B0B0D;
  border-color: #0B0B0D;
  box-shadow: 0 6px 16px rgba(11, 11, 13, 0.3);
  color: #FFFFFF;
}

#tour[data-step="1"] .step[data-n="1"] .step-tab,
#tour[data-step="2"] .step[data-n="2"] .step-tab,
#tour[data-step="3"] .step[data-n="3"] .step-tab,
#tour[data-step="4"] .step[data-n="4"] .step-tab,
#tour[data-step="5"] .step[data-n="5"] .step-tab,
#tour[data-step="6"] .step[data-n="6"] .step-tab {
  color: var(--accent-deep);
}

#tour[data-step="1"] .step[data-n="1"] .step-rule,
#tour[data-step="2"] .step[data-n="2"] .step-rule,
#tour[data-step="3"] .step[data-n="3"] .step-rule,
#tour[data-step="4"] .step[data-n="4"] .step-rule,
#tour[data-step="5"] .step[data-n="5"] .step-rule,
#tour[data-step="6"] .step[data-n="6"] .step-rule {
  background: rgba(126, 122, 168, 0.45);
}

#tour[data-step="1"] .step[data-n="1"] h3,
#tour[data-step="2"] .step[data-n="2"] h3,
#tour[data-step="3"] .step[data-n="3"] h3,
#tour[data-step="4"] .step[data-n="4"] h3,
#tour[data-step="5"] .step[data-n="5"] h3,
#tour[data-step="6"] .step[data-n="6"] h3 {
  color: var(--ink);
}

#tour[data-step="1"] .step[data-n="1"] .step-body,
#tour[data-step="2"] .step[data-n="2"] .step-body,
#tour[data-step="3"] .step[data-n="3"] .step-body,
#tour[data-step="4"] .step[data-n="4"] .step-body,
#tour[data-step="5"] .step[data-n="5"] .step-body,
#tour[data-step="6"] .step[data-n="6"] .step-body,
#tour[data-step="1"] .step[data-n="1"] .step-points li,
#tour[data-step="2"] .step[data-n="2"] .step-points li,
#tour[data-step="3"] .step[data-n="3"] .step-points li,
#tour[data-step="4"] .step[data-n="4"] .step-points li,
#tour[data-step="5"] .step[data-n="5"] .step-points li,
#tour[data-step="6"] .step[data-n="6"] .step-points li {
  color: var(--ink-mid);
}

#tour[data-step="1"] .step[data-n="1"] .tick,
#tour[data-step="2"] .step[data-n="2"] .tick,
#tour[data-step="3"] .step[data-n="3"] .tick,
#tour[data-step="4"] .step[data-n="4"] .tick,
#tour[data-step="5"] .step[data-n="5"] .tick,
#tour[data-step="6"] .step[data-n="6"] .tick {
  background: rgba(22, 208, 133, 0.18);
}

#tour[data-step="1"] .step[data-n="1"] .tick svg,
#tour[data-step="2"] .step[data-n="2"] .tick svg,
#tour[data-step="3"] .step[data-n="3"] .tick svg,
#tour[data-step="4"] .step[data-n="4"] .tick svg,
#tour[data-step="5"] .step[data-n="5"] .tick svg,
#tour[data-step="6"] .step[data-n="6"] .tick svg {
  stroke: #0F7A38;
}

/* --- The phone ----------------------------------------------------------- */

.phone-float {
  position: relative;
  animation: mkFloat 9s var(--ease) infinite;
}

.halo {
  position: absolute;
  border-radius: 9999px;
  pointer-events: none;
}

/* Durations are deliberately mismatched so the two halos drift out of phase
   instead of pulsing in lockstep. */
.halo-warm {
  left: -22px;
  top: 84px;
  width: 300px;
  height: 300px;
  background: radial-gradient(circle, rgba(150, 156, 200, 0.5) 0%, rgba(150, 156, 200, 0) 68%);
  filter: blur(12px);
  animation: mkGlow 8s var(--ease) infinite;
}

.halo-lav {
  right: -18px;
  bottom: 100px;
  width: 200px;
  height: 200px;
  background: radial-gradient(circle, rgba(206, 206, 219, 0.6) 0%, rgba(206, 206, 219, 0) 70%);
  filter: blur(14px);
  animation: mkGlow 11s var(--ease) infinite;
}

/* The frame.
 *
 * This was a hand-built machined-metal rail with physical side buttons. The
 * handoff (§3) said outright that a CSS bezel is an approximation and a real
 * device render would look better — and the buttons were the tell: at this
 * size they read as four dark smudges on the silhouette rather than as
 * hardware, and every extra piece of chrome competes with the screen, which is
 * the only part anyone is meant to look at.
 *
 * So: one flat, near-black frame with an even rail and a single soft edge
 * highlight. No gradient theatre, no buttons, no notch hardware. The screen
 * aperture stays exactly 298 x 588 with a 38px inner radius, per the handoff,
 * so the screens inside are untouched by this.
 *
 * If a licensed device asset ever lands, swap the background for it and keep
 * those aperture numbers. */
.bezel {
  position: relative;
  width: 318px;
  padding: 10px;
  border-radius: 48px;
  background: #14161B;
  box-shadow:
    /* the thin lit edge that stops it reading as a flat black rectangle */
    inset 0 0 0 1px rgba(255, 255, 255, 0.13),
    0 0 0 1px rgba(0, 0, 0, 0.55),
    /* the phone sits on the page */
    0 24px 50px rgba(20, 22, 32, 0.28),
    0 52px 100px rgba(20, 22, 32, 0.22);
  overflow: hidden;
}

/* A flat frame has nothing to catch light, so the sweep is gone. Kept as a
   no-op rule rather than pulled from the markup, so the element is still there
   if the frame ever goes back to metal. */
.bezel-sheen { display: none; }

/* 588px is the tallest screen that lets the whole device fit in a laptop
   viewport at top: 24px. Increasing it re-introduces the cut-off phone.
   The 38px radius is the 48px outer radius minus the 10px rail, which is what
   keeps the aperture concentric with the frame. */
.screen {
  position: relative;
  width: var(--screen-w);
  height: var(--screen-h);
  border-radius: 38px;
  background: #FAFAFA;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.4);
  overflow: hidden;
  z-index: 2;
}

/* Everything on the screen lives in one fixed 298 x 588 box. On mobile that
   whole box is scaled as a single unit, which keeps the absolutely positioned
   bottom bars in the right place — scaling the children individually does not. */
.screen-inner {
  position: relative;
  width: var(--screen-w);
  height: var(--screen-h);
}

.notch-row {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 30px;
  padding-top: 6px;
}

/* Dynamic Island, not a notch — a floating pill with the camera visible in it.
   The faint ring is the lens; without it the pill reads as a black sticker. */
.island {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  width: 82px;
  height: 23px;
  padding-right: 6px;
  border-radius: 9999px;
  background: #08090C;
  box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.07);
}

.island-cam {
  width: 9px;
  height: 9px;
  border-radius: 9999px;
  background: radial-gradient(circle at 32% 30%, #24304A 0%, #0D1119 58%, #05070A 100%);
  box-shadow: inset 0 0 0 0.5px rgba(120, 150, 200, 0.28);
}

/* A single soft diagonal across the glass. Kept very low alpha — the moment it
   is readable as a shape it stops looking like glass and starts looking like a
   white triangle sitting on the screenshot. */
.screen-glare {
  position: absolute;
  inset: 0;
  z-index: 4;
  border-radius: 38px;
  background: linear-gradient(148deg,
    rgba(255, 255, 255, 0.16) 0%,
    rgba(255, 255, 255, 0.05) 18%,
    rgba(255, 255, 255, 0) 38%);
  pointer-events: none;
}

.home-indicator {
  position: absolute;
  left: 50%;
  bottom: 7px;
  width: 104px;
  height: 4px;
  margin-left: -52px;
  border-radius: 9999px;
  background: rgba(8, 16, 33, 0.28);
}

/* --- Screen switching ----------------------------------------------------
   All six screens live in the DOM; the active step reveals one.

   The mapping is offset by one from the step number because step 1 is the trip
   list, which is the same screen the hero state shows:
     0 hero, 1 Trips -> trip list + the product's own nav bar
     2 Hub  3 Plan  4 Travel  5 Stays  6 Split -> in-trip + the trip tab bar

   Everything inside a screen uses the PRODUCT palette (#FAFAFA / #081021 /
   #64748B), which is now close to the shell's rather than set against it. */

.scr { display: none; }

#tour[data-step="0"] .scr-list,
#tour[data-step="1"] .scr-list,
#tour[data-step="2"] .scr-hub,
#tour[data-step="3"] .scr-plan,
#tour[data-step="4"] .scr-travel,
#tour[data-step="5"] .scr-stays,
#tour[data-step="6"] .scr-split { display: block; }

.scr-trip { display: none; }
#tour[data-step="2"] .scr-trip,
#tour[data-step="3"] .scr-trip,
#tour[data-step="4"] .scr-trip,
#tour[data-step="5"] .scr-trip,
#tour[data-step="6"] .scr-trip { display: block; }

.trip-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 26px;
  font-family: 'Timeburner', system-ui, sans-serif;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: -0.1px;
  color: rgba(8, 16, 33, 0.9);
}

/* The bottom bar swapping from the product nav to the trip tab bar is what
   makes this read as navigating inside one device rather than cutting to a
   different mockup. */
.navbar { display: none; }
#tour[data-step="0"] .navbar-product,
#tour[data-step="1"] .navbar-product { display: flex; }
#tour[data-step="2"] .navbar-trip,
#tour[data-step="3"] .navbar-trip,
#tour[data-step="4"] .navbar-trip,
#tour[data-step="5"] .navbar-trip,
#tour[data-step="6"] .navbar-trip { display: flex; }

/* Matches the product's tab: full-height pill inside the bar, not a padded
   label. 11px at 402pt scales to 8.5px in this 298px frame. */
.tab {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 0;
  min-width: 0;
  border-radius: 9999px;
  background: transparent;
  box-shadow: none;
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: 8.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #7C889A;
  white-space: nowrap;
  transition: background 180ms var(--ease), color 180ms var(--ease);
}

/* Step 5 is the Stays screen but its tab is Hub — that is per the design. */
#tour[data-step="2"] .tab-hub,
#tour[data-step="5"] .tab-hub,
#tour[data-step="3"] .tab-plan,
#tour[data-step="4"] .tab-travel,
#tour[data-step="6"] .tab-split {
  background: #FFFFFF;
  box-shadow: 0 1px 3px rgba(8, 16, 33, 0.1);
  color: var(--ink);
}

/* --- Footer CTA ---------------------------------------------------------- */

.cta-wrap { padding: 0 48px 88px; }

.cta {
  position: relative;
  display: flex;
  align-items: center;
  gap: 40px;
  padding: 46px 48px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 20px;
  background: #0B0B0D;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16), 0 26px 60px rgba(90, 86, 128, 0.3);
  overflow: hidden;
}

.cta .sheen {
  width: 180px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0) 100%);
  animation: mkSheen 9s var(--ease) infinite;
}

.cta-copy {
  flex: 1 1 auto;
  min-width: 0;
  position: relative;
}

.cta h2 {
  margin: 0;
  font-family: 'Jokker', system-ui, sans-serif;
  font-weight: 500;
  font-size: 34px;
  line-height: 1.14;
  letter-spacing: -1.1px;
  color: #FFFFFF;
  text-wrap: pretty;
}

.cta-body {
  display: block;
  padding-top: 14px;
  max-width: 520px;
  font-size: 16px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.66);
}

/* Silver, because a dark button would vanish against the dark slab. */
.btn-silver {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  padding: 18px 28px;
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: 10px;
  background: var(--silver-button);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.95), 0 10px 30px rgba(0, 0, 0, 0.28);
  transition: transform 200ms var(--ease), box-shadow 200ms var(--ease);
}

.btn-silver:hover {
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.95), 0 16px 38px rgba(0, 0, 0, 0.34);
}

.btn-silver .btn-label { color: #081021; }

/* --- Site footer --------------------------------------------------------- */

.site-foot {
  display: flex;
  align-items: center;
  gap: 18px;
  width: 1440px;
  margin: 0 auto;
  padding: 0 8px;
}

.site-foot .wordmark { font-size: 17px; }

.site-foot-rule {
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(90deg, rgba(126, 122, 168, 0.3), rgba(100, 116, 139, 0.08));
}

.site-foot span.meta {
  font-weight: 500;
  font-size: 12px;
  color: var(--text-muted);
}

/* ==========================================================================
   Mobile — under 900px
   The pinned-phone mechanic does not survive a phone-sized viewport: you
   cannot show a phone inside a phone. So the bezel, notch and halos come off
   and the screen becomes a plain screenshot card, still sticky at the top and
   still swapping as the copy scrolls beneath it. The tour survives; the
   skeuomorphism does not.
   ========================================================================== */

@media (max-width: 1150px) {
  :root { --phone-scale: 0.6; }

  .page {
    gap: 24px;
    padding: 14px 14px 40px;
  }

  .artboard {
    width: 100%;
    border-radius: 20px;
  }

  /* Nav collapses to wordmark + one action. The section links have nowhere
     useful to go on a small screen and the auth pair would wrap. */
  .nav-row { padding: 14px 14px 0; }

  .nav-pill {
    gap: 12px;
    width: 100%;
    padding: 9px 9px 9px 18px;
    justify-content: space-between;
  }

  .nav-links,
  .nav-auth .btn-ghost { display: none; }

  .btn-dark-pill { padding: 11px 18px; }

  /* Single column. The phone column moves above the copy and sticks to the
     top of the viewport. */
  .tour-row {
    flex-direction: column;
    gap: 0;
    padding: 20px 18px 40px;
  }

  .col-copy {
    order: 2;
    min-width: 0;
    width: 100%;
  }

  /* The band must be fully opaque for the whole height of the screenshot and
     edge to edge, or copy scrolling underneath shows through the margins
     beside the card. It only fades out below the card's bottom edge. */
  .col-phone {
    order: 1;
    position: sticky;
    top: 0;
    z-index: 5;
    align-self: stretch;
    flex: 0 0 auto;
    width: auto;
    margin: 0 -18px;
    padding: 10px 18px 34px;
    /* Opaque past the bottom of the card, then a 28px reveal. Fading across
       the card's own edge instead leaves half-lit text sitting behind it,
       which reads as a rendering fault rather than a transition. */
    background: linear-gradient(180deg,
      #F5F3F9 0%,
      #F5F3F9 calc(100% - 28px),
      rgba(245, 243, 249, 0) 100%);
  }

  /* Strip the device: no float, no halos, no metal, no notch. */
  .phone-float { animation: none; }
  .halo { display: none; }

  .bezel {
    width: calc(var(--screen-w) * var(--phone-scale));
    padding: 0;
    border: 0;
    border-radius: 22px;
    background: none;
    box-shadow: none;
  }

  .bezel-sheen { display: none; }

  /* Scale the fixed 298x588 screen as one unit. The outer .screen carries the
     scaled dimensions so surrounding layout stays honest; .screen-inner keeps
     its true size and is transformed, which preserves the absolutely
     positioned bottom bars. */
  .screen {
    height: calc(var(--screen-h) * var(--phone-scale));
    width: calc(var(--screen-w) * var(--phone-scale));
    border-radius: 22px;
    box-shadow: 0 1px 0 rgba(8, 16, 33, 0.06), 0 16px 40px rgba(90, 86, 128, 0.22);
  }

  .screen-inner {
    transform: scale(var(--phone-scale));
    transform-origin: top left;
  }

  /* No device, so no device cues. The spacer stays because the screen content
     is laid out expecting clearance at the top. */
  .notch-row { height: 14px; padding-top: 0; }
  .island,
  .home-indicator,
  .screen-glare { display: none; }

  /* Globe above the copy, so the first thing on a phone is the thing being
     sold rather than a headline with a blank half-screen under it. */
  .hero-row {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 18px 18px 0;
  }

  .hero-globe {
    order: -1;
    flex: 0 0 auto;
    gap: 14px;
  }

  /* Capped, or the sphere eats the whole first screen on a tall phone. */
  .globe-stage {
    width: min(100%, 60vh);
    align-self: center;
  }

  .globe-stats { gap: 22px; }
  .globe-stat-n { font-size: 18px; }

  .hero {
    min-height: 0;
    padding: 24px 0 8px;
  }

  .hero h1 {
    font-size: clamp(34px, 9.2vw, 46px);
    letter-spacing: -1.4px;
  }

  .hero h1 br { display: none; }

  .hero-body {
    padding-top: 16px;
    font-size: 16px;
  }

  .hero-cta-row { padding-top: 24px; }

  .btn-primary {
    min-width: 0;
    width: 100%;
    padding: 18px 22px;
  }

  .sub-cta { font-size: 13px; }

  .section-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    padding: 40px 0 4px;
  }

  .section-head h2 {
    font-size: clamp(26px, 7.4vw, 34px);
    letter-spacing: -0.8px;
  }

  .section-aside {
    flex: 0 0 auto;
    font-size: 15px;
  }

  /* Matched to the readable band left below the sticky screenshot (~55vh), so
     an active step's copy stays in that band for nearly its whole turn instead
     of sliding up behind the card early. */
  .step {
    min-height: 56vh;
    padding: 18px 0;
  }

  /* No sticky container to run out of on mobile, so the last step doesn't need
     the desktop's extra height. */
  .step[data-n="6"] { min-height: 56vh; }

  .step h3 {
    font-size: clamp(24px, 6.8vw, 30px);
    letter-spacing: -0.7px;
  }

  .step-body {
    padding-top: 12px;
    font-size: 15.5px;
  }

  .step-points li { font-size: 14px; }

  .cta-wrap { padding: 0 18px 40px; }

  .cta {
    flex-direction: column;
    align-items: flex-start;
    gap: 24px;
    padding: 30px 24px;
  }

  .cta h2 {
    font-size: clamp(25px, 6.8vw, 30px);
    letter-spacing: -0.7px;
  }

  .cta h2 br { display: none; }

  .cta-body { font-size: 15px; }

  .btn-silver {
    width: 100%;
    justify-content: center;
  }

  .site-foot {
    width: 100%;
    flex-wrap: wrap;
    gap: 12px;
  }
}

/* Tablet and small laptop: stacked layout, but there is plenty of width for
   the real nav and a button that isn't stretched edge to edge. Without this
   the pill spans the viewport with a wordmark at one end and a button at the
   other, and the CTA reads as a banner rather than a button. */
@media (min-width: 640px) and (max-width: 1150px) {
  .nav-pill {
    width: auto;
    gap: 30px;
    padding: 11px 12px 11px 24px;
    justify-content: flex-start;
  }

  .nav-links { display: flex; }
  .nav-auth .btn-ghost { display: flex; }

  .btn-primary { max-width: 420px; }
  .btn-silver { width: auto; }

  .cta { padding: 40px 40px; }
}

/* Very narrow — keep the screenshot from eating the viewport. */
@media (max-width: 380px) {
  :root { --phone-scale: 0.52; }
}

/* Tablet portrait has the height to carry a larger screenshot. Gated on
   min-height too: the same width in landscape does not. */
@media (min-width: 700px) and (max-width: 1150px) and (min-height: 800px) {
  :root { --phone-scale: 0.75; }
}

/* Between the mobile breakpoint and the 1440 artboard, let the artboard be
   fluid rather than forcing a horizontal scrollbar. */
@media (min-width: 1151px) and (max-width: 1520px) {
  .artboard,
  .site-foot { width: 100%; }

}

/* --- Reduced motion ------------------------------------------------------
   The scroll-driven screen switching STAYS — it is content navigation, not
   decoration. Everything ambient stops. */

@media (prefers-reduced-motion: reduce) {
  .dots,
  .phone-float,
  .halo,
  .sheen,
  .bezel-sheen,
  .scr [style*="animation"] {
    animation: none !important;
  }

  * { transition-duration: 0.01ms !important; }
}
