/* ==========================================================================
   3rd-i marketing site
   The whole site is a city atlas: quiet streets, one live route, clear stops.
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

:root {
  --sans: "SF Pro Display", -apple-system, BlinkMacSystemFont, "Inter", "Helvetica Neue", Arial, sans-serif;
  --void: #080a0f;
  --void-rgb: 8, 10, 15;
  --panel: #11141b;
  --panel-rgb: 17, 20, 27;
  --panel-2: #161a22;
  --text: #f4f5f7;
  --dim: #979eab;
  --soft: #6e7685;
  --line: rgba(255, 255, 255, 0.09);
  --line-hi: rgba(255, 255, 255, 0.16);
  --street: rgba(132, 150, 177, 0.09);
  --street-major: rgba(132, 150, 177, 0.15);
  --lot: rgba(132, 150, 177, 0.045);
  --lot-line: rgba(132, 150, 177, 0.08);
  --lot-hi: rgba(132, 150, 177, 0.08);
  --park: rgba(92, 193, 246, 0.05);
  --park-line: rgba(92, 193, 246, 0.08);
  --glass: rgba(13, 16, 22, 0.76);
  --glass-solid: #0e1117;
  --sky: #5cc1f6;
  --royal: #4979ef;
  --magenta: #f31a91;
  --alarm: #ef3b3b;
  --grad: linear-gradient(105deg, var(--sky), var(--royal) 52%, var(--magenta));
  /* The app's own CTA: light blue falling to deep blue, straight down. */
  --grad-cta: linear-gradient(180deg, #55b3ff, #1b74f0);
  --acc-sky: #5cc1f6;
  --acc-royal: #8e9bff;
  --acc-magenta: #ff4fae;
  --row: rgba(92, 193, 246, 0.08);
  --row-line: rgba(92, 193, 246, 0.14);
  --route-shadow: 0 0 18px rgba(73, 121, 239, 0.3);
  --lift: 0 24px 70px rgba(0, 0, 0, 0.24);
  /* Soft, colour-tinted card shadows instead of grey borders: the light-and-airy
     depth Life360 and the App Store screens use. */
  --soft-shadow: 0 22px 48px -20px rgba(40, 64, 140, 0.28), 0 4px 14px -8px rgba(40, 64, 140, 0.18);
  --soft-shadow-lg: 0 40px 90px -34px rgba(40, 64, 140, 0.4), 0 8px 22px -12px rgba(40, 64, 140, 0.2);
  /* Same family as the card shadows, tuned tighter: the floating header capsule
     sits close to the page, so its shadow is a short diffuse pad rather than the
     long card drop. `-lift` is the calmer-still scrolled state. */
  --header-shadow: 0 14px 34px -18px rgba(0, 0, 0, 0.72), 0 2px 10px -6px rgba(0, 0, 0, 0.5);
  --header-shadow-lift: 0 20px 44px -18px rgba(0, 0, 0, 0.8), 0 3px 12px -6px rgba(0, 0, 0, 0.58);
  --wrap: 1180px;
  --r-sm: 14px;
  --r: 22px;
  --r-lg: 30px;
  --pill: 999px;
  color-scheme: dark;
}

html[data-theme="light"] {
  --void: #f4f6fc;
  --void-rgb: 244, 246, 252;
  --panel: #ffffff;
  --panel-rgb: 255, 255, 255;
  --panel-2: #eef1f9;
  --text: #191d2b;
  --dim: #545c70;
  --soft: #6c7488;
  --line: rgba(28, 40, 82, 0.07);
  --line-hi: rgba(28, 40, 82, 0.14);
  --soft-shadow: 0 22px 46px -22px rgba(40, 64, 140, 0.22), 0 4px 12px -8px rgba(40, 64, 140, 0.12);
  --soft-shadow-lg: 0 44px 96px -38px rgba(40, 64, 140, 0.32), 0 8px 22px -14px rgba(40, 64, 140, 0.16);
  --header-shadow: 0 12px 30px -16px rgba(40, 64, 140, 0.34), 0 2px 8px -5px rgba(40, 64, 140, 0.16);
  --header-shadow-lift: 0 18px 40px -18px rgba(40, 64, 140, 0.42), 0 3px 10px -5px rgba(40, 64, 140, 0.2);
  --street: rgba(70, 104, 170, 0.05);
  --street-major: rgba(70, 104, 170, 0.09);
  --lot: rgba(70, 104, 170, 0.028);
  --lot-line: rgba(70, 104, 170, 0.05);
  --lot-hi: rgba(70, 104, 170, 0.045);
  --park: rgba(73, 121, 239, 0.045);
  --park-line: rgba(73, 121, 239, 0.07);
  --glass: rgba(248, 249, 251, 0.78);
  --glass-solid: #f8f9fb;
  --acc-sky: #1e8bfe;
  --acc-royal: #5a48e6;
  --acc-magenta: #d9309b;
  --row: rgba(30, 139, 254, 0.06);
  --row-line: rgba(30, 139, 254, 0.14);
  --route-shadow: 0 0 12px rgba(73, 121, 239, 0.18);
  --lift: 0 24px 70px rgba(26, 36, 54, 0.1);
  color-scheme: light;
}

html { scroll-behavior: smooth; scroll-padding-top: calc(var(--header-h, 72px) + 12px); }
html,
body { margin: 0; min-width: 320px; overflow-x: hidden; }
/* The header is position:fixed (see .hdr); this reserves the 72px of flow the
   old in-flow bar occupied so nothing shifts. */
body { padding-top: var(--header-h, 72px); }
body {
  min-height: 100vh;
  color: var(--text);
  background:
    radial-gradient(circle at 50% 0%, rgba(73, 121, 239, 0.07), transparent 30rem),
    var(--void);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
/* Light mode wears the store screens' pastel wash: sky, lilac and pink
   bleeding in from the edges of a near-white page. */
html[data-theme="light"] body {
  background:
    radial-gradient(60rem 42rem at 8% -6%, rgba(60, 158, 255, 0.16), transparent 60%),
    radial-gradient(54rem 40rem at 104% 12%, rgba(120, 96, 245, 0.13), transparent 60%),
    radial-gradient(52rem 44rem at -6% 62%, rgba(242, 74, 170, 0.1), transparent 58%),
    radial-gradient(56rem 46rem at 108% 88%, rgba(60, 158, 255, 0.12), transparent 60%),
    var(--void);
  background-attachment: fixed;
}

img,
svg { display: block; max-width: 100%; }
a { color: inherit; }
button,
input,
select,
textarea { font: inherit; }
button { color: inherit; }
p,
h1,
h2,
h3,
ul { margin-top: 0; }

.wrap { width: min(calc(100% - 44px), var(--wrap)); margin-inline: auto; }
.skip {
  position: fixed;
  left: 16px;
  top: -80px;
  z-index: 100;
  padding: 10px 14px;
  border-radius: 8px;
  background: var(--text);
  color: var(--void);
  text-decoration: none;
}
.skip:focus { top: 12px; }

/* ---------- the city atlas and the live route -------------------------- */

.field { display: none !important; }
.road {
  position: absolute;
  inset: 0 0 auto;
  z-index: 0;
  width: 100%;
  pointer-events: none;
  overflow: hidden;
}
.road svg { width: 100%; overflow: visible; }
.road-above { z-index: 2; }
/* Friends scattered across the city: the app's blue tear-drop pin holding a
   little avatar. Background decoration, kept slightly faded so it never fights
   the copy, and popped up from its tip as it scrolls into view. */
.pin-body {
  fill: url(#pinGrad);
  stroke: rgba(19, 43, 92, 0.14);
  stroke-width: 0.6;
  vector-effect: non-scaling-stroke;
}
.pin-ring { fill: #ffffff; }
.pin-pop {
  opacity: 0;
  transform: scale(0.28);
  transform-box: fill-box;
  transform-origin: 50% 100%;
  transition: transform 0.55s cubic-bezier(0.34, 1.56, 0.5, 1), opacity 0.4s ease;
}
.pin.is-in .pin-pop { opacity: 0.78; transform: scale(1); }
html[data-theme="dark"] .pin.is-in .pin-pop { opacity: 0.7; }
.city-lot {
  fill: var(--lot);
  stroke: var(--lot-line);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.city-lot-hi { fill: var(--lot-hi); }
.city-park {
  fill: var(--park);
  stroke: var(--park-line);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
/* Lit windows on the parcels: the city seen from above at night. Light mode
   barely shows them, which is correct for daylight. */
.city-win { fill: rgba(235, 242, 252, 0.3); }
.city-win-warm { fill: rgba(255, 196, 128, 0.26); }
html[data-theme="light"] .city-win { fill: rgba(58, 74, 98, 0.08); }
html[data-theme="light"] .city-win-warm { fill: rgba(58, 74, 98, 0.06); }
.route-bed,
.route-live {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.route-bed { stroke: var(--line-hi); stroke-width: 3; }
/* Dark mode: --line-hi is 16% white and the undrawn bed glows straight through
   the glass cards it crosses. Light mode stays on --line-hi; dark drops to a
   whisper. */
html:not([data-theme="light"]) .route-bed { stroke: rgba(255, 255, 255, 0.055); }
.route-live {
  stroke: url("#routeGradient");
  stroke-width: 3;
  filter: drop-shadow(var(--route-shadow));
}
/* The soft head that glows at the drawing edge while the line is filling in. */
.route-tip {
  fill: #ffffff;
  filter: drop-shadow(0 0 7px rgba(92, 193, 246, 0.9)) drop-shadow(0 0 14px rgba(73, 121, 239, 0.55));
  transition: opacity 500ms ease;
}
html[data-theme="light"] .route-tip {
  fill: var(--royal);
  filter: drop-shadow(0 0 7px rgba(73, 121, 239, 0.55));
}
/* The underline is the SAME line as the road, same weight and gradient, so
   where the road turns across a heading and back there is no step in weight:
   it reads as one continuous ribbon, not a thin road feeding a fat underline. */
.route-ink {
  fill: none;
  stroke: url("#routeGradientInk");
  stroke-width: 3;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(var(--route-shadow));
  transition: stroke-dashoffset 700ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.route-node-outer {
  fill: var(--void);
  stroke: var(--line-hi);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}
.route-node-inner {
  fill: var(--void);
  stroke: var(--soft);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
  transition: fill 300ms ease, stroke 300ms ease;
}
.route-node.is-passed .route-node-inner {
  fill: var(--node-color, var(--royal));
  stroke: var(--text);
}

header,
main,
footer { position: relative; z-index: 1; }
/* The <header> element must out-stack its later siblings (equal z-index paints
   in DOM order), or the fixed .hdr inside it renders UNDER main's content. */
header { z-index: 30; }

/* ---------- navigation -------------------------------------------------- */

/* The bar is a detached capsule floating inside a transparent fixed band.
   --header-gap is the inset above it, --header-bar-h the capsule itself, and
   --header-h stays what every consumer reads it as: the distance from the top
   of the viewport to the BOTTOM edge of the bar (body offset, anchor scroll
   padding, the mobile sheet, the pinned indoor-map stage). --header-w is the
   capsule width, shared by the surface and the row inside it.

   --header-h MUST stay a plain px length. Two scripts read it with
   `parseFloat(getComputedStyle(root).getPropertyValue("--header-h"))`, which
   returns the token as authored, so a calc() expression parses as NaN and
   silently falls back to 72: the pinned indoor-map stage and every anchor
   offset would then be measured against the wrong edge. Derive the capsule
   height FROM it, never the other way round. */
:root {
  --header-gap: 20px;
  --header-h: 78px;
  --header-bar-h: calc(var(--header-h) - var(--header-gap));
  --header-w: min(calc(100% - 44px), var(--wrap));
}
/* Lock the page behind the open mobile menu sheet. */
body.nav-open { overflow: hidden; }
/* FIXED, not sticky: html/body carry overflow-x:hidden (mobile invariant),
   which silently disables position:sticky, so a sticky header just scrolled
   away with the page. Fixed + body padding-top keeps the identical layout
   while the bar stays pinned. */
.hdr {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 30;
  height: var(--header-h);
  /* The band around the capsule is see-through, so it must not swallow clicks
     meant for the page underneath. Only the capsule takes the pointer. */
  pointer-events: none;
}
/* The capsule surface. It is a pseudo-element of .hdr rather than a background
   on .hdr-in so that paint order can put the mobile sheet BEHIND it (negative
   z-index) while the logo, burger and actions stay in front (z-index 1).
   .hdr-in must therefore keep z-index auto, or its children would be trapped in
   its own stacking context and the sheet could never pass under the capsule. */
.hdr::after {
  content: "";
  position: absolute;
  top: var(--header-gap);
  left: 50%;
  z-index: 0;
  width: var(--header-w);
  height: var(--header-bar-h);
  transform: translateX(-50%);
  border: 1px solid var(--line);
  border-radius: var(--pill);
  /* Liquid glass, the same material the bar has always worn: the page ground at
     low alpha over a wide blur. The blur, not the alpha, is what keeps labels
     legible while content slides underneath, so raise the blur before the
     opacity if this ever needs more separation. */
  background: rgba(var(--void-rgb), 0.72);
  background-clip: padding-box;
  box-shadow: var(--header-shadow);
  backdrop-filter: blur(30px) saturate(185%);
  -webkit-backdrop-filter: blur(30px) saturate(185%);
  pointer-events: auto;
  transition: box-shadow 300ms ease, background-color 300ms ease;
}
/* Once the page has moved, the capsule reads against live content instead of
   the top of the hero: a little more body in the glass and a longer shadow. It
   stays translucent. */
.hdr.is-scrolled::after {
  background: rgba(var(--void-rgb), 0.82);
  backdrop-filter: blur(34px) saturate(190%);
  -webkit-backdrop-filter: blur(34px) saturate(190%);
  box-shadow: var(--header-shadow-lift);
}
/* Selector carries .hdr so the capsule width beats the plain .wrap rule the
   element also matches (.wrap is redefined later in the file for narrow
   viewports and would otherwise win on source order). Gap and inner padding are
   fluid because the capsule is at its tightest just above the 980px breakpoint,
   where the full nav row still has to fit. */
.hdr .hdr-in {
  width: var(--header-w);
  height: var(--header-bar-h);
  margin-top: var(--header-gap);
  padding-inline: clamp(13px, 1.4vw, 20px) clamp(7px, 0.7vw, 10px);
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: clamp(14px, 2vw, 28px);
  pointer-events: auto;
}
/* Lifted clear of the capsule surface (which paints in the z-index 0 layer). */
.hdr-logo,
.nav-btn,
.hdr-end { position: relative; z-index: 1; }
.hdr-logo { display: block; width: 72px; }
.hdr-logo img { width: 72px; height: auto; }
.hdr-nav {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(20px, 2.6vw, 38px);
}
.hdr-nav a,
.foot-nav a {
  color: var(--dim);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: -0.01em;
  text-decoration: none;
  transition: color 180ms ease;
}
.hdr-nav a:hover,
.hdr-nav a[aria-current="page"],
.foot-nav a:hover { color: var(--text); }
/* Home shows in the desktop bar alongside the logo. The group/sub wrappers
   collapse so the anchors flow inline in the desktop row. */
.nav-group,
.nav-sub { display: contents; }
/* Gradient underline marks the active page in the desktop bar. */
.hdr-nav > a,
.nav-group > a { position: relative; }
.hdr-nav a[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -7px;
  height: 2px;
  border-radius: 2px;
  background: var(--grad);
}
/* The mobile menu footer (appearance + CTA) only exists inside the open menu. */
.nav-foot { display: none; }
.hdr-end { display: flex; align-items: center; gap: 10px; }
.nav-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border: 0;
  padding: 9px;
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
/* Three bars that morph into an X when the menu opens. */
.nav-btn-box { position: relative; width: 22px; height: 16px; }
.nav-bar {
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s ease;
}
.nav-bar:nth-child(1) { top: 0; }
.nav-bar:nth-child(2) { top: 7px; }
.nav-bar:nth-child(3) { top: 14px; }
.nav-btn[aria-expanded="true"] .nav-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-btn[aria-expanded="true"] .nav-bar:nth-child(2) { opacity: 0; transform: scaleX(0.3); }
.nav-btn[aria-expanded="true"] .nav-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
.theme-toggle {
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--dim);
  background: rgba(var(--panel-rgb), 0.54);
  border: 1px solid var(--line);
  border-radius: var(--pill);
  cursor: pointer;
  transition: color 0.3s ease, border-color 0.3s ease, background 0.3s ease;
}
.theme-toggle:hover { color: var(--sky); border-color: var(--line-hi); }
/* Animated sun <-> moon. The disc stays put; the rays retract and a masked
   "bite" slides across to carve the sun into a crescent. Driven off
   html[data-theme], so it animates on every toggle. */
.tsm { width: 19px; height: 19px; overflow: visible; }
.tsm-bite { transition: transform 0.5s cubic-bezier(0.45, 0, 0.15, 1); }
.tsm-rays {
  transform-origin: 12px 12px;
  transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.35s ease;
}
.tsm-rays line { transform-origin: 12px 12px; }
html[data-theme="light"] .tsm-bite { transform: translate(0, 0); }
html[data-theme="light"] .tsm-rays { opacity: 1; transform: scale(1) rotate(0); }
html[data-theme="dark"] .tsm-bite { transform: translate(-9px, 4px); }
html[data-theme="dark"] .tsm-rays { opacity: 0; transform: scale(0.35) rotate(-45deg); }

/* ---------- type and common controls ----------------------------------- */

h1,
h2,
h3 {
  margin-bottom: 0;
  font-weight: 600;
  text-wrap: balance;
}
h1 {
  font-size: clamp(50px, 7vw, 98px);
  line-height: 0.98;
  letter-spacing: -0.055em;
}
h2 {
  font-size: clamp(36px, 4.6vw, 64px);
  line-height: 1.03;
  letter-spacing: -0.043em;
}
h3 {
  font-size: clamp(19px, 2vw, 25px);
  line-height: 1.15;
  letter-spacing: -0.025em;
}
.eyebrow,
.ret-dist,
.press-lead,
.who,
.fork-who,
.tstamp,
.key {
  font-size: 11px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.eyebrow,
.ret-dist,
.press-lead { color: var(--dim); }
.eyebrow--brand,
.who,
.route-label {
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.lede {
  color: var(--dim);
  font-size: clamp(18px, 2vw, 23px);
  line-height: 1.48;
  letter-spacing: -0.018em;
}
.body { color: var(--dim); font-size: 17px; letter-spacing: -0.012em; }
.proof {
  color: var(--soft);
  font-size: 13px;
  line-height: 1.55;
}
/* Bottom-CTA trust line: give it real breathing room under the buttons instead
   of crowding them (Sam 2026-08-06, applies to every page's closing CTA). */
.proof--c { margin-top: clamp(20px, 2.6vw, 30px); }
/* Fine-print / disclaimer notes read as a quiet, intentional footnote chip:
   centered, contained, hairline border on a recessed surface, with an optional
   small icon. Theme-aware via tokens. */
.note {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  width: fit-content;
  max-width: min(100%, 46rem);
  margin-inline: auto;
  padding: 11px 18px;
  border-radius: 14px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--dim);
  font-size: 12.5px;
  line-height: 1.5;
  text-align: center;
  letter-spacing: -0.004em;
}
.note svg { flex: 0 0 auto; width: 16px; height: 16px; color: var(--sky); }
.note a { color: var(--text); font-weight: 600; }
.btn {
  min-height: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 0 20px;
  border: 1px solid transparent;
  border-radius: var(--pill);
  color: var(--text);
  background: transparent;
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: transform 180ms ease, background 180ms ease, border-color 180ms ease;
}
.btn:hover { transform: translateY(-2px); }
/* The tri-gradient pill is the site's primary action. The app-blue vertical
   gradient (--grad-cta) stays only where the site is depicting the app's own
   UI (the Go Live sheet, the entry pin). */
.btn-primary {
  color: #fff;
  background: var(--grad);
  /* Fill the gradient to the border box so the rounded pill caps do not clip it
     (the default padding-box origin insets the gradient inside the 1px border). */
  background-origin: border-box;
  box-shadow: 0 10px 30px rgba(73, 121, 239, 0.28);
}
/* Two-tone headings, straight off the App Store screens: black plus one
   phrase in an accent, alternating sky, violet, magenta down the page. */
.hl-sky { color: var(--acc-sky); }
.hl-royal { color: var(--acc-royal); }
.hl-magenta { color: var(--acc-magenta); }

/* The app's option rows (the Go Live sheet): soft tinted rounded rows with
   an icon chip, the last one the full CTA gradient. */
.app-sheet {
  display: grid;
  gap: 14px;
  max-width: 500px;
}
.app-row {
  position: relative;
  display: grid;
  grid-template-columns: 60px 1fr;
  align-items: center;
  gap: 18px;
  min-height: 88px;
  padding: 18px 22px;
  border-radius: 22px;
  background: var(--panel);
  border: 1px solid var(--row-line);
  box-shadow: 0 12px 30px rgba(20, 34, 70, 0.07);
}
.app-row .chip {
  width: 60px;
  height: 60px;
  border-radius: 17px;
  display: grid;
  place-items: center;
  background: rgba(30, 139, 254, 0.14);
  color: var(--acc-sky);
}
.app-row .chip svg { width: 27px; height: 27px; }

/* Timeline: a connector line down the left gutter with a node dot per card.
   Desktop only; the dots are hidden on the tight (mobile) layout. */
.app-sheet--timeline { position: relative; padding-left: 34px; }
.app-sheet--timeline::before {
  content: ""; position: absolute; left: 11px; top: 40px; bottom: 40px; width: 2px;
  background: linear-gradient(180deg, rgba(30, 139, 254, 0.85), rgba(30, 139, 254, 0.22));
  border-radius: 2px;
}
.app-sheet--timeline .app-row::before {
  content: ""; position: absolute; left: -29px; top: 50%; transform: translateY(-50%);
  width: 12px; height: 12px; border-radius: 50%; left: -28px;
  background: var(--panel); border: 2px solid var(--acc-sky);
  box-shadow: 0 0 0 3px rgba(30, 139, 254, 0.08);
}
.app-sheet--timeline .app-row--cta::before {
  background: var(--acc-sky); border-color: var(--acc-sky);
}

/* Keep the section from sprawling on wide screens (Adam 2026-08-06). */
#app .split--ui { max-width: 960px; margin-inline: auto; }

/* Download panel below the phone + cards: a compact, centred CTA card. */
.app-download {
  max-width: 680px;
  margin: clamp(30px, 4vw, 48px) auto 0;
  padding: clamp(24px, 2.4vw, 32px) clamp(22px, 3vw, 40px);
  border-radius: 28px;
  background: var(--panel);
  border: 1px solid var(--row-line);
  box-shadow: 0 16px 42px rgba(20, 34, 70, 0.07);
  text-align: center;
}
.app-download .widgets { justify-content: center; margin-top: 4px; }
.sheet-cap--c { text-align: center; }
.app-dl-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 11px;
  min-width: 300px;
  margin: 20px 0 6px;
  padding: 16px 36px; border-radius: 999px;
  background: linear-gradient(120deg, #6d3bef 0%, #a855f7 100%);
  color: #fff; font-weight: 700; font-size: 16px; letter-spacing: -0.01em;
  text-decoration: none;
  box-shadow: 0 14px 32px rgba(124, 58, 237, 0.32);
  transition: transform 0.14s ease, box-shadow 0.2s ease;
}
.app-dl-btn:hover { transform: translateY(-1px); box-shadow: 0 18px 38px rgba(124, 58, 237, 0.42); }
.app-dl-btn:active { transform: translateY(0); }
.app-dl-btn svg { width: 20px; height: 20px; }
.app-row .chip--alert {
  background: rgba(239, 59, 59, 0.14);
  color: var(--alarm);
}
.app-row b { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
.app-row span { display: block; color: var(--dim); font-size: 13px; margin-top: 2px; }
.app-row--cta {
  background: var(--grad-cta);
  border-color: transparent;
  box-shadow: 0 12px 28px rgba(27, 116, 240, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.3);
}
.app-row--cta b,
.app-row--cta span { color: #fff; }
.app-row--cta span { color: rgba(255, 255, 255, 0.8); }
.app-row--cta .chip {
  background: rgba(255, 255, 255, 0.2);
  color: #fff;
}
.sheet-cap {
  color: var(--soft);
  font-size: 13px;
  margin: 14px 0 0;
}
/* The widgets note gets a touch more presence (client 2026-08-07: emphasize
   the widgets): bold lead on the text line, slightly larger than a caption. */
.sheet-cap--widgets { max-width: 44ch; font-size: 14px; line-height: 1.55; }
.sheet-cap--widgets b { display: block; margin-bottom: 3px; color: var(--text); font-size: 15px; }

/* Lock Screen widget chips, from the store's Faster Access screen. */
.widgets {
  display: flex;
  align-items: center;
  gap: 12px;
}
.widget {
  width: 58px;
  height: 58px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(10, 12, 18, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.16);
  color: #fff;
}
html[data-theme="light"] .widget {
  background: rgba(17, 20, 26, 0.82);
  border-color: rgba(17, 20, 26, 0.2);
}
.widget svg { width: 24px; height: 24px; }
.widget b {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
/* Trigger-for-a-friend chip: a single horizontal lockup (small person glyph
   beside a compact SOS), centered as one unit - the stacked icon-over-text
   version read as broken (client, 2026-08-07 x2). */
.widget--stack {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
}
.widget--stack svg { width: 15px; height: 15px; flex: 0 0 auto; }
.widget--stack b { font-size: 10px; letter-spacing: 0.03em; }
.widget--stack svg { width: 14px; height: 14px; }
.widget--stack b { font-size: 9.5px; }

/* The Emergency Entry Pin plate, from the store's responder screen. */
.entry-mini {
  position: relative;
  margin: 16px 0 14px;
  border-radius: 14px;
  overflow: hidden;
  height: 132px;
  /* real map (dark by default), softened so the entry pin + tag stay legible */
  background:
    linear-gradient(rgba(17, 20, 27, 0.30), rgba(17, 20, 27, 0.05)),
    url("../brand/map-tile-dark-2.png") center / cover no-repeat,
    var(--panel-2);
  border: 1px solid var(--line);
}
html[data-theme="light"] .entry-mini {
  background:
    linear-gradient(rgba(255, 255, 255, 0.30), rgba(255, 255, 255, 0.06)),
    url("../brand/map-tile-light-2.png") center / cover no-repeat,
    var(--panel-2);
}
.entry-pin {
  position: absolute;
  left: 50%;
  top: 54%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--grad-cta);
  border: 3px solid #fff;
  color: #fff;
  box-shadow: 0 10px 24px rgba(27, 116, 240, 0.4);
}
.entry-pin svg { width: 22px; height: 22px; }
.entry-tag {
  position: absolute;
  left: 50%;
  top: 12px;
  transform: translateX(-50%);
  padding: 3px 12px;
  border-radius: var(--pill);
  background: var(--glass-solid);
  border: 1px solid var(--line);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
}
.entry-addr {
  display: grid;
  grid-template-columns: 16px 1fr;
  gap: 8px;
  align-items: baseline;
  font-size: 13px;
  color: var(--dim);
}
.entry-addr .dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--acc-sky);
  align-self: center;
}

/* Real phone renders. No boxy plate: the device floats on a soft brand glow so
   it reads as a product hero, not a screenshot in a frame. */
.phone-plate {
  position: relative;
  display: grid;
  place-items: center;
  padding: clamp(10px, 2vw, 22px);
}
.phone-plate::before {
  content: "";
  position: absolute;
  inset: 4% 0;
  z-index: 0;
  background:
    radial-gradient(closest-side, rgba(60, 158, 255, 0.24), transparent 72%),
    radial-gradient(closest-side at 66% 74%, rgba(242, 74, 170, 0.18), transparent 70%);
  filter: blur(13px);
  pointer-events: none;
}
.phone-plate img {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 300px;
  height: auto;
  filter: drop-shadow(0 42px 60px rgba(20, 34, 70, 0.3));
}
.versus.versus--media,
.fork.fork--media { grid-template-columns: 0.82fr 1.09fr 1.09fr; }

/* ---------- immersive device showcase (big phone + callouts) ------------ */

.nudge-grid.nudge-grid--media {
  grid-template-columns: 1.04fr 0.96fr;
  align-items: center;
  gap: clamp(28px, 5vw, 72px);
}
.nudge-side { display: grid; gap: clamp(16px, 2.2vw, 26px); }
.showcase { position: relative; z-index: 1; }
.showcase-phone {
  position: relative;
  width: min(310px, 82%);
  margin-inline: auto;
  /* scroll-linked scale lives here; JS sets --s, we ease to it */
  transform: scale(var(--s, 1));
  transition: transform 140ms linear;
  will-change: transform;
}
.showcase-glow {
  position: absolute;
  inset: -14% -20%;
  z-index: 0;
  background:
    radial-gradient(closest-side, rgba(60, 158, 255, 0.28), transparent 72%),
    radial-gradient(closest-side at 70% 74%, rgba(242, 74, 170, 0.22), transparent 70%);
  filter: blur(14px);
  pointer-events: none;
}
.showcase-phone img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 44px 66px rgba(20, 34, 70, 0.32));
}
/* Callouts: a dot pinned to a real feature at (--x,--y) with a pill beside it. */
.callout {
  position: absolute;
  left: var(--x);
  top: var(--y);
  z-index: 3;
}
.callout::before {
  /* Anchor dots + connector lines retired (client 2026-08-07: the dots sat on
     the app's own buttons - the SOS button, the viewer count). The pills alone
     carry the labels; their positions are unchanged. */
  display: none;
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  transform: translate(-50%, -50%);
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--grad);
  box-shadow: 0 0 0 4px rgba(73, 121, 239, 0.16), 0 4px 10px rgba(73, 121, 239, 0.45);
}
.callout::after {
  display: none;
  content: "";
  position: absolute;
  top: 0;
  width: 16px;
  height: 2px;
  border-radius: 2px;
  background: var(--line-hi);
}
/* The route spinner svg deliberately overflows its 20px wrapper when anchored
   to a dot; with the dots retired it just reads broken, so size it honestly
   inside every pill (same fix the mobile legend already carried). */
.callout b .i3s-route { width: 20px; height: 20px; background: none; box-shadow: none; }
.callout b .i3s-route .i3s-route__svg { width: 100%; height: 100%; }
.callout b {
  position: absolute;
  top: 0;
  transform: translateY(-50%);
  padding: 8px 14px;
  border-radius: var(--pill);
  background: var(--panel);
  box-shadow: var(--soft-shadow);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.callout--r::after { left: 5px; }
.callout--r b { left: 22px; }
.callout--l::after { right: 5px; }
.callout--l b { right: 22px; }
.callout--alarm::before {
  background: var(--alarm);
  box-shadow: 0 0 0 4px rgba(239, 59, 59, 0.16), 0 4px 10px rgba(239, 59, 59, 0.45);
}
.callout--alarm b { color: var(--alarm); }

.showcase--c { margin-top: clamp(20px, 4vw, 44px); }
.showcase--c .showcase-phone { width: min(320px, 76%); }
.ret-head--c { max-width: 760px; margin-inline: auto; text-align: center; }
.ret-head--c .lede { margin-inline: auto; }

/* Live "watching" card floating in the open space beside the centred phone: a
   real app surface showing who is on your live route, plus an incoming nudge.
   Only rendered on comfortable desktop widths (hidden <=980, see media query),
   where the centred phone leaves room on the left. */
.watch-card {
  position: absolute;
  left: clamp(0px, 3vw, 40px);
  top: 50%;
  transform: translateY(-50%);
  z-index: 6;
  width: min(268px, 30%);
  padding: 16px 16px 14px;
  border-radius: 20px;
  border: 1px solid var(--line-hi);
  background: var(--glass);
  box-shadow: var(--lift);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}
.watch-card-top {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
}
.watch-card-top .live {
  background: var(--magenta);
  animation: watch-pulse 2s ease-out infinite;
}
@keyframes watch-pulse {
  0% { box-shadow: 0 0 0 0 rgba(243, 26, 145, 0.4); }
  70% { box-shadow: 0 0 0 7px rgba(243, 26, 145, 0); }
  100% { box-shadow: 0 0 0 0 rgba(243, 26, 145, 0); }
}
.watch-time { margin-left: auto; color: var(--soft); font-weight: 600; }
.watch-people {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-top: 13px;
}
.watch-stack { display: flex; flex: 0 0 auto; }
.watch-stack .disc-s {
  width: 30px;
  height: 30px;
  font-size: 10px;
  margin-left: -8px;
  box-shadow: 0 4px 10px rgba(40, 64, 140, 0.18);
}
.watch-stack .disc-s:first-child { margin-left: 0; }
.watch-people b { font-size: 12.5px; line-height: 1.3; color: var(--text); }
.watch-people b span {
  display: block;
  margin-top: 2px;
  color: var(--soft);
  font-weight: 500;
  font-size: 11px;
}
.watch-nudge {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 13px;
  padding: 9px 11px;
  border-radius: 14px;
  border-bottom-left-radius: 5px;
  background: var(--panel);
  box-shadow: var(--soft-shadow);
}
.watch-nudge .disc-s { width: 26px; height: 26px; font-size: 9px; flex: 0 0 auto; }
.watch-nudge p { margin: 0; font-size: 12px; line-height: 1.35; color: var(--text); }
.watch-nudge p b { font-weight: 700; }

/* ---------- feature bento (grid on desktop, swipe slider on mobile) ------ */

.bento {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 1.6vw, 20px);
}

/* ---------- "One app for the walk home": two counter-scrolling rows -------
   All 15 feature tiles in two auto-drifting marquee rows (row A left, row B
   right), replacing the five-row grid (2026-08-07: too long on every screen).
   Seamless loop: each track holds two identical halves and slides exactly
   -50%; the trailing card margin makes the halves' widths exact. Hover or
   touch-hold pauses a row. Reduced motion: static, hand-scrollable, single
   half. */
.bento-rails {
  display: grid;
  gap: clamp(14px, 1.6vw, 20px);
}
.brow {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.brow-track {
  display: flex;
  width: max-content;
  animation: brow-scroll var(--dur, 60s) linear infinite;
}
.brow--b .brow-track { animation-direction: reverse; }
/* Interaction is JS-driven post-hydration (FeatureBento engine: drag, fling,
   auto-resume); the CSS animation is only the pre-hydration/no-JS state.
   pan-y keeps vertical page scrolling native while horizontal drags are ours. */
.brow { touch-action: pan-y; cursor: grab; }
.brow:active { cursor: grabbing; }
.brow-half { display: flex; }
.brow .feat {
  flex: 0 0 auto;
  width: clamp(240px, 22vw, 300px);
  margin-right: clamp(14px, 1.6vw, 20px);
}
.brow .feat-vis { height: 130px; }
@keyframes brow-scroll { to { transform: translateX(-50%); } }

@media (prefers-reduced-motion: reduce) {
  .brow-track { animation: none !important; width: auto; }
  .brow { overflow-x: auto; -webkit-mask-image: none; mask-image: none; }
  .brow-half[data-dup] { display: none; }
}
/* Life360-style tiles: a colour art panel with a small live scene on top, the
   label below. Each tile shows the feature, it does not just name it. */
.feat {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  border-radius: var(--r);
  background: var(--panel);
  box-shadow: var(--soft-shadow);
}
.route-passed .feat { box-shadow: var(--soft-shadow-lg); }
.feat-vis {
  position: relative;
  height: 172px;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--panel-2);
}
.feat-body { padding: 22px clamp(20px, 2.2vw, 28px) clamp(24px, 2.4vw, 30px); }
.feat h3 { margin-bottom: 7px; font-size: clamp(18px, 1.8vw, 21px); }
.feat p { margin: 0; color: var(--dim); font-size: 15px; line-height: 1.45; }

/* Tile art colours, layered over panel-2 so they adapt to light and dark. */
.feat--sky .feat-vis { background: linear-gradient(155deg, rgba(60, 158, 255, 0.22), rgba(60, 158, 255, 0.05) 72%), var(--panel-2); }
.feat--violet .feat-vis { background: linear-gradient(155deg, rgba(120, 96, 245, 0.22), rgba(120, 96, 245, 0.05) 72%), var(--panel-2); }
.feat--blue .feat-vis { background: linear-gradient(155deg, rgba(73, 121, 239, 0.2), rgba(73, 121, 239, 0.05) 72%), var(--panel-2); }
.feat--slate .feat-vis { background: linear-gradient(155deg, rgba(90, 104, 130, 0.18), rgba(90, 104, 130, 0.04) 72%), var(--panel-2); }
.feat--alarm .feat-vis { background: linear-gradient(155deg, rgba(239, 59, 59, 0.2), rgba(239, 59, 59, 0.05) 72%), var(--panel-2); }
.feat--alarm::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  z-index: 2;
  height: 3px;
  background: var(--grad);
}
@media (hover: hover) and (pointer: fine) {
  .feat { transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 320ms ease; }
  .feat:hover { transform: translateY(-6px) scale(1.012); box-shadow: var(--soft-shadow-lg); }
  /* On the Framer Motion bento, Framer owns transform per-frame; a CSS transform
     transition would lag/fight it, so keep only the shadow easing here. */
  .bento--motion .feat { transition: box-shadow 320ms ease; }
  .bento--motion .feat:hover { box-shadow: var(--soft-shadow-lg); }
}

/* Shared little "live" pill used inside tiles. */
.vis-tag {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  border-radius: var(--pill);
  background: var(--panel);
  box-shadow: var(--soft-shadow);
  font-size: 11px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
.dot-live { width: 7px; height: 7px; border-radius: 50%; background: var(--magenta); box-shadow: 0 0 0 3px rgba(243, 26, 145, 0.15); }

/* Go live: the app's blue camera button with a live ripple. */
.vis-golive {
  position: relative;
  width: 66px;
  height: 66px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: #fff;
  background: var(--grad-cta);
  box-shadow: 0 12px 26px rgba(27, 116, 240, 0.4);
}
.vis-golive svg { width: 30px; height: 30px; }
.vis-golive::before,
.vis-golive::after {
  content: "";
  position: absolute;
  inset: -9px;
  border-radius: 50%;
  border: 2px solid rgba(60, 158, 255, 0.5);
  animation: sos-ring 2.6s ease-out infinite;
}
.vis-golive::after { animation-delay: 1.3s; }
.feat--sky .vis-tag { bottom: 16px; right: 16px; }

/* Squad: overlapping avatars with a watching pill. */
.vis-squad { position: relative; display: flex; }
.vis-squad .disc-s { width: 52px; height: 52px; margin-left: -14px; font-size: 14px; box-shadow: 0 8px 20px rgba(40, 64, 140, 0.2); }
.vis-squad .disc-s:first-child { margin-left: 0; }
.vis-squad .vis-tag { bottom: -16px; left: 50%; transform: translateX(-50%); }

/* Nudges: two chat bubbles. */
.vis-bubbles { display: grid; gap: 9px; width: min(88%, 230px); }
.bub { padding: 9px 14px; border-radius: 16px; font-size: 13px; font-weight: 500; width: fit-content; }
.bub--in { justify-self: start; border-bottom-left-radius: 5px; background: var(--panel); box-shadow: var(--soft-shadow); color: var(--text); }
.bub--out { justify-self: end; border-bottom-right-radius: 5px; background: var(--grad-cta); color: #fff; box-shadow: 0 8px 18px rgba(27, 116, 240, 0.3); }

/* SOS: red button with pulse. */
.vis-sos {
  position: relative;
  width: 74px;
  height: 74px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--alarm);
  color: #fff;
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.06em;
  box-shadow: 0 12px 28px rgba(239, 59, 59, 0.45);
}
.vis-sos::before,
.vis-sos::after {
  content: "";
  position: absolute;
  inset: -10px;
  border-radius: 50%;
  border: 2px solid rgba(239, 59, 59, 0.5);
  animation: sos-ring 2.4s ease-out infinite;
}
.vis-sos::after { animation-delay: 1.2s; }
@keyframes sos-ring {
  0% { transform: scale(0.72); opacity: 0.9; }
  100% { transform: scale(1.28); opacity: 0; }
}

/* Ghost mode: a fading dot on a faint map. */
.vis-ghost {
  position: relative;
  width: 78%;
  height: 122px;
  border-radius: 14px;
  overflow: hidden;
  /* real map (dark by default), softened with a scrim so the fading dot reads */
  background:
    linear-gradient(rgba(17, 20, 27, 0.32), rgba(17, 20, 27, 0.06)),
    url("../brand/ghost-map-dark.webp") center / cover no-repeat,
    var(--panel);
  box-shadow: var(--soft-shadow);
}
html[data-theme="light"] .vis-ghost {
  background:
    linear-gradient(rgba(255, 255, 255, 0.34), rgba(255, 255, 255, 0.08)),
    url("../brand/ghost-map-light.webp") center / cover no-repeat,
    var(--panel);
}
.vis-ghost-dot {
  position: absolute;
  left: 34%;
  top: 50%;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--royal);
  opacity: 0.26;
  box-shadow: 0 0 0 6px rgba(73, 121, 239, 0.08);
}
.vis-ico-off { position: absolute; right: 12px; bottom: 10px; color: var(--soft); }
.vis-ico-off svg { width: 22px; height: 22px; }

/* Entry pin plate reused as a tile scene. */
.vis-entry { margin: 0; width: 78%; height: 124px; }
.quiet-map {
  position: relative;
  margin: 18px 0 0;
  border-radius: var(--r);
  overflow: hidden;
  box-shadow: var(--soft-shadow);
}
.quiet-map img {
  display: block;
  width: 100%;
  height: 218px;
  object-fit: cover;
}
/* The source map render is near-black; in the noon survey it is flipped to a
   soft daylight map so it belongs on the light, airy page instead of punching a
   dark hole in it. */
html[data-theme="light"] .quiet-map img {
  filter: invert(1) hue-rotate(185deg) saturate(0.5) brightness(1.08) contrast(0.92);
}
.quiet-map figcaption {
  position: absolute;
  left: 16px;
  bottom: 13px;
  padding: 7px 14px;
  border-radius: var(--pill);
  background: rgba(10, 13, 19, 0.74);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: #cfd6e2;
  font-size: 12px;
  backdrop-filter: blur(6px);
}
html[data-theme="light"] .quiet-map figcaption {
  background: rgba(255, 255, 255, 0.82);
  border-color: rgba(28, 40, 82, 0.1);
  color: var(--dim);
}

.btn-ghost {
  background: var(--panel);
  border-color: transparent;
  box-shadow: var(--soft-shadow);
}
.btn-ghost:hover { box-shadow: var(--soft-shadow-lg); }
.btn-sm { min-height: 36px; padding-inline: 16px; font-size: 13px; }
.btn-store { min-height: 50px; padding-inline: 17px; }
.btn-store .apple { width: 19px; height: 24px; fill: currentColor; }
.store-txt { display: grid; gap: 1px; text-align: left; }
.store-txt small { font-size: 9px; font-weight: 500; line-height: 1; }
.store-txt span { font-size: 16px; line-height: 1; letter-spacing: -0.02em; }
.cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 30px; }
.cta-row--c { justify-content: center; }
/* Label marker. Was a magenta dot inside a soft magenta halo, which is the
   single most generic "AI made this UI" motif going, and it read as a pulse.
   Now the brand notch from the hero eyebrow: one multi-coloured line, static.
   Sized a little narrower than .i3s-notch because these sit against 11-12px
   labels rather than a hero eyebrow. */
.live,
.pip {
  display: inline-block;
  width: 22px;
  height: 5px;
  flex: 0 0 auto;
  border-radius: 999px;
  vertical-align: middle;
  background: linear-gradient(90deg, #f52d8c, #8b5cf6 56%, #5678ff);
  box-shadow: 0 3px 9px rgba(139, 92, 246, 0.16);
}

/* ---------- home hero --------------------------------------------------- */

.hero {
  min-height: calc(100svh - 72px);
  padding: clamp(64px, 8vw, 116px) 0 clamp(88px, 10vw, 142px);
}
.hero-atlas {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(360px, 0.75fr);
  align-items: center;
  gap: clamp(48px, 7vw, 100px);
}
.hero-copy { position: relative; z-index: 3; text-align: left; }
.hero-copy .eyebrow { margin-bottom: 24px; }
.hero-copy h1 { max-width: 10.5ch; font-size: clamp(52px, 8.2vw, 116px); }
.hero-copy .lede { max-width: 39rem; margin: 28px 0 0; }
.hero-copy .proof { margin: 18px 0 0; display: flex; align-items: center; gap: 10px; }
.trip-window {
  position: relative;
  min-height: 660px;
  display: grid;
  place-items: center;
}
.trip-window::before {
  content: "";
  position: absolute;
  inset: 6% 0;
  border: 1px solid var(--line);
  border-radius: 30px;
  mask-image: linear-gradient(to bottom, transparent, #000 12%, #000 88%, transparent);
}
.trip-window::after {
  content: "";
  position: absolute;
  width: 360px;
  height: 360px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(73, 121, 239, 0.17), transparent 67%);
  filter: blur(10px);
}

/* The sonar rings double as the circle's orbit paths: returns radiating from
   the phone, with the people who watch riding them. */
.sonar {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 1060px;
  height: 1060px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  overflow: visible;
}
.sonar circle {
  fill: none;
  stroke-width: 1.2;
  vector-effect: non-scaling-stroke;
}
.sonar .s1 { stroke: rgba(92, 193, 246, 0.45); }
.sonar .s2 { stroke: url("#orbitGrad"); opacity: 0.62; }
.sonar .s3 { stroke: rgba(73, 121, 239, 0.34); }
.sonar .s4 { stroke: url("#orbitGrad"); opacity: 0.28; }
.sonar .ping {
  stroke: rgba(92, 193, 246, 0.5);
  transform-origin: center;
  animation: ping 5.6s cubic-bezier(0.2, 0.6, 0.4, 1) infinite;
}
@keyframes ping {
  0% { transform: scale(0.36); opacity: 0.9; }
  75% { transform: scale(1.04); opacity: 0; }
  100% { transform: scale(1.04); opacity: 0; }
}
html[data-theme="light"] .sonar .s1 { stroke: rgba(30, 139, 254, 0.3); }
html[data-theme="light"] .sonar .s3 { stroke: rgba(73, 121, 239, 0.22); }
html[data-theme="light"] .sonar .ping { stroke: rgba(30, 139, 254, 0.4); }

/* Initials discs riding the rings, with their nudges beside them (05). */
.orb {
  position: absolute;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: 9px;
}
.orb .disc-s {
  width: 42px;
  height: 42px;
  background: var(--glass-solid);
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.35), 0 0 0 1.5px rgba(92, 193, 246, 0.4);
}
.orb--b .disc-s { box-shadow: 0 8px 26px rgba(0, 0, 0, 0.35), 0 0 0 1.5px rgba(243, 26, 145, 0.38); }
.orb-quote {
  padding: 8px 13px;
  border-radius: 14px;
  background: var(--glass);
  border: 1px solid var(--line-hi);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  font-size: 13px;
}
.orb-quote small {
  display: block;
  color: var(--soft);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
/* Both discs sit ON the r=322 orbit: dx matches the chord at their height,
   in the gaps the trip chips leave free. */
.orb--a { left: calc(50% - 343px); top: 49%; }
.orb--b { right: calc(50% - 310px); top: 33%; flex-direction: row-reverse; }

/* The survey legend under the hero. */
.hero-legend {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 26px;
  margin: clamp(26px, 4vw, 54px) 0 0;
  color: var(--soft);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.hero-legend span { display: inline-flex; align-items: center; gap: 8px; }
.hero-legend i { display: inline-block; }
.lg-route { width: 18px; height: 2px; background: var(--sky); border-radius: 2px; }
.lg-you { width: 8px; height: 8px; border-radius: 50%; background: var(--royal); }
.lg-home { width: 8px; height: 8px; border-radius: 2px; background: var(--magenta); }
.lg-right { margin-left: auto; }
.device-clean {
  position: relative;
  z-index: 3;
  width: min(52vw, 270px);
  filter: drop-shadow(0 34px 50px rgba(0, 0, 0, 0.42));
}
.device-clean img { width: 100%; height: auto; }
.shot-light { display: none; }
html[data-theme="light"] .shot-dark { display: none; }
html[data-theme="light"] .shot-light { display: block; }
.trip-status,
.map-address,
.squad-float {
  position: absolute;
  z-index: 5;
  border: 1px solid var(--line-hi);
  background: var(--glass);
  box-shadow: var(--lift);
  backdrop-filter: blur(16px);
}
.trip-status {
  top: 13%;
  left: 1%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 15px;
  border-radius: var(--pill);
  font-size: 13px;
  font-weight: 600;
}
.map-address {
  right: -1%;
  bottom: 17%;
  width: 190px;
  padding: 15px 16px;
  border-radius: var(--r);
}
.map-address small,
.squad-float small {
  display: block;
  margin-bottom: 4px;
  color: var(--dim);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
}
.map-address b { font-size: 14px; }
.squad-float {
  left: -4%;
  bottom: 28%;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 13px 10px 10px;
  border-radius: var(--pill);
}
.squad-stack { display: flex; }
.squad-stack .disc-s { margin-left: -7px; }
.squad-stack .disc-s:first-child { margin-left: 0; }
.hero-street-key {
  position: absolute;
  right: 1%;
  top: 28%;
  z-index: 5;
  color: var(--dim);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
}

/* keep the older hero mechanisms hidden if a cached page reaches this CSS */
.city-svg,
.city-haze,
.city-veil,
.rings,
.orbit,
.stage-wrap,
.legend,
.origin-plate { display: none !important; }

/* ---------- inner heroes and section rhythm ---------------------------- */

.page-hero {
  min-height: 76svh;
  display: grid;
  align-items: center;
  padding: clamp(82px, 11vw, 150px) 0;
}
.page-hero .wrap { position: relative; }
.page-hero h1 { max-width: 12ch; }
.page-hero .lede { max-width: 43rem; margin: 28px 0 0; }
.page-hero .cta-row { justify-content: flex-start; }

.ret {
  position: relative;
  padding: clamp(96px, 11vw, 168px) 0;
}
/* Sections now breathe on the warm ground instead of sitting inside a bordered
   box. The route ribbon and the content give the structure. */
.ret-head { max-width: 820px; margin-bottom: clamp(44px, 6vw, 76px); }
.ret-dist { margin-bottom: 16px; }
.route-passed .ret-dist { color: var(--text); }
.ret-head h2 { max-width: 13ch; }
.ret-head .lede { max-width: 43rem; margin: 24px 0 0; }
/* Centred variant, restated AFTER the base rules: the earlier .ret-head--c
   block (line ~764) loses the cascade to the base .ret-head rules above, which
   left-anchored the capped h2 box and stripped the lede's auto margins, so
   "centred" heads sat visibly off the page axis (the sides section bug). */
.ret-head--c h2 { margin-inline: auto; }
.ret-head--c .lede { margin-inline: auto; }
.head { max-width: 760px; }
.head--c { margin-inline: auto; text-align: center; }
.head .lede { margin: 22px 0 0; }

/* ---------- shared surfaces -------------------------------------------- */

.card,
.vs-card,
.composer,
.returns,
.dcard,
.fork-card,
.plan,
.uni-card,
.stop,
.seen-col,
.form {
  border: 1px solid transparent;
  background: var(--panel);
  box-shadow: var(--soft-shadow);
}
.card,
.vs-card,
.composer,
.returns,
.dcard,
.fork-card,
.plan,
.uni-card,
.seen-col,
.form { border-radius: var(--r); }
.card,
.vs-card,
.composer,
.returns,
.dcard,
.fork-card,
.plan,
.uni-card,
.seen-col { padding: clamp(28px, 3.4vw, 44px); }
.route-passed .card,
.route-passed .vs-card,
.route-passed .composer,
.route-passed .returns,
.route-passed .dcard,
.route-passed .fork-card,
.route-passed .plan,
.route-passed .uni-card,
.route-passed .seen-col {
  box-shadow: var(--soft-shadow-lg);
}

/* Positive surfaces carry a whisper of brand light; the "lesser" option is a
   flat, recessed grey so the choice reads at a glance, not as two equal boxes. */
.vs-card--live,
.fork-card:not(.fork-card--ent),
.seen-col:not(.seen-col--no) {
  background: linear-gradient(168deg, rgba(60, 158, 255, 0.11), var(--panel) 44%);
}
.vs-card--flat,
.seen-col--no {
  background: var(--panel-2);
  box-shadow: none;
}
.card p,
.vs-card p,
.dcard p,
.fork-card p,
.plan p,
.uni-card p,
.stop p,
.seen-col p { color: var(--dim); }
.cols,
.watch,
.versus,
.nudge-grid,
.dispatch,
.fork,
.seen,
.split,
.uni-grid,
.plans,
.stops {
  display: grid;
  gap: clamp(16px, 2.2vw, 28px);
}
.cols,
.watch,
.versus,
.nudge-grid,
.fork,
.seen,
.split { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.dispatch { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* ---------- circle and privacy ----------------------------------------- */

.arc {
  position: relative;
  height: 190px;
  margin: 0 0 30px;
}
.arc-line { position: absolute; inset: 0; width: 100%; height: 100%; }
.arc-line path { stroke: var(--line-hi) !important; stroke-dasharray: 3 8; }
.watcher {
  position: absolute;
  display: grid;
  justify-items: center;
  transform: translate(-50%, -50%);
  font-size: 12px;
}
.watcher > b { margin-top: 8px; font-size: 12px; }
.watcher > span:last-child { color: var(--soft); font-size: 10px; }
.ring,
.disc,
.disc-s {
  position: relative;
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  border: 1px solid var(--line-hi);
  border-radius: 50%;
  background: var(--glass-solid);
  color: var(--text);
  font-size: 11px;
  font-weight: 600;
}
.ring { width: 44px; height: 44px; }
.disc { width: 44px; height: 44px; }
.disc-s { width: 38px; height: 38px; }
.ring::after,
.disc::after,
.disc-s::after { content: attr(data-i); }
.ring::before,
.disc::before,
.disc-s::before {
  content: "";
  position: absolute;
  inset: -2px;
  z-index: -1;
  border-radius: inherit;
  background: var(--grad);
}
.disc-s--off { opacity: 0.42; }

/* "Safety made social" - the phone sits inside a live sonar and your people
   ride the rings around it, swapping over time (circle.js). */
.social-stage {
  position: relative;
  --orbit: 300px;
  width: 100%;
  max-width: 600px;
  min-height: 660px;
  margin: clamp(24px, 4vw, 48px) auto 0;
  display: grid;
  place-items: center;
}
.soc-sonar {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 760px;
  height: 760px;
  transform: translate(-50%, -50%);
  overflow: visible;
  z-index: 0;
  pointer-events: none;
}
.soc-ring { fill: none; stroke-width: 1.2; vector-effect: non-scaling-stroke; }
.soc-ring--1 { stroke: rgba(92, 193, 246, 0.42); }
.soc-ring--2 { stroke: url("#socGrad"); opacity: 0.5; }
.soc-ring--3 { stroke: rgba(73, 121, 239, 0.26); }
html[data-theme="light"] .soc-ring--1 { stroke: rgba(30, 139, 254, 0.3); }
html[data-theme="light"] .soc-ring--3 { stroke: rgba(73, 121, 239, 0.2); }
.soc-ping {
  fill: none;
  stroke: rgba(92, 193, 246, 0.5);
  stroke-width: 1.4;
  vector-effect: non-scaling-stroke;
  transform-origin: 500px 500px;
  animation: socPing 5.2s cubic-bezier(0.2, 0.6, 0.4, 1) infinite;
}
@keyframes socPing {
  0% { transform: scale(0.42); opacity: 0.75; }
  75% { transform: scale(1.5); opacity: 0; }
  100% { transform: scale(1.5); opacity: 0; }
}
.soc-orbit {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0;
  height: 0;
  z-index: 1;
  animation: socSpin 64s linear infinite;
}
/* Each layer owns exactly one transform so the rotations cancel to zero and the
   names stay perfectly upright at every point of the orbit:
   friend rotate(a) -> fix rotate(-orbit) -> card rotate(-a) + centre. */
@keyframes socSpin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes socSpinRev { from { transform: rotate(0deg); } to { transform: rotate(-360deg); } }
.soc-friend {
  position: absolute;
  left: 0;
  top: 0;
  transform: rotate(var(--a)) translateX(calc(var(--rk) * var(--orbit)));
}
.soc-fix {
  display: block;
  transform-origin: 0 0;
  animation: socSpinRev 64s linear infinite;
}
.soc-card {
  display: grid;
  justify-items: center;
  transform: translate(-50%, -50%) rotate(calc(-1 * var(--a)));
}
.soc-face {
  display: grid;
  justify-items: center;
  gap: 7px;
  transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.34, 1.4, 0.5, 1);
}
.soc-friend.is-swapping .soc-face { opacity: 0; transform: scale(0.55); }
.soc-friend .ring {
  width: 46px;
  height: 46px;
  box-shadow: 0 10px 26px rgba(20, 34, 70, 0.22);
}
.soc-friend b { font-size: 12px; font-weight: 600; white-space: nowrap; }
/* The phone rides above the orbit, so people pass behind it at the back of the
   sonar and beside it on the way round. */
.social-stage .showcase--c { position: relative; z-index: 2; margin: 0; }
.social-stage .showcase-phone { width: min(292px, 62vw); }
.vs-card--flat { background: var(--panel-2); box-shadow: none; }
.vs-kind,
.fork-who,
.composer-head { display: flex; align-items: center; gap: 9px; color: var(--dim); font-size: 12px; }
.vs-card h3,
.dcard h3,
.fork-card h3 { margin: 14px 0 12px; }
.vs-card > p:not(.vs-kind),
.dcard > p:not(.who),
.fork-card > p:not(.fork-who):not(.fork-price) {
  font-size: 15px;
  line-height: 1.6;
}
.vs-facts,
.fork-card ul,
.seen-col ul,
.plan ul {
  display: grid;
  gap: 14px;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}
.vs-facts li,
.fork-card li,
.seen-col li,
.plan li {
  position: relative;
  padding-left: 26px;
  color: var(--dim);
  font-size: 14.5px;
  line-height: 1.5;
}
.vs-facts li::before,
.fork-card li::before,
.seen-col li::before,
.plan li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.5em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--grad);
  box-shadow: 0 2px 6px rgba(73, 121, 239, 0.35);
}
/* The cold "being tracked" card keeps a muted grey dot so it reads as the lesser
   option; only the positive lists get the live gradient dot. */
.vs-card--flat .vs-facts li::before { background: var(--soft); box-shadow: none; }
/* Demoted to clean fine print: no box, no accent bar. It is a reassurance, not a
   callout, so it sits quietly under the section and stays readable. */
.versus-note {
  max-width: 52rem;
  margin: 30px 0 0;
  color: var(--dim);
  font-size: 13.5px;
  line-height: 1.6;
}
.versus-note strong { color: var(--text); font-weight: 600; }

/* ---------- the duel: two live map panels (#already) ------------------- */
/* The comparison is SHOWN, not tabled: the same night twice, side by side at
   EVERY width. Left = Find My, a desaturated grey map with one stale ghost
   dot. Right = a 3rd-i trip, the same map lit with the gradient route, a
   walking traveller, the live pill, the watching circle and the Safety Agent.
   The lesser option is flat and recessed, the 3rd-i panel carries the brand
   light (same treatment as .vs-card--live). Theme-aware; light overrides at
   the end of this block. */
.duel {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(12px, 2.4vw, 28px);
  max-width: 980px;
  margin: 0 auto;
  align-items: stretch;
}
.duel-panel {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: clamp(14px, 2vw, 22px);
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--panel-2);
}
.duel-panel--us {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border: 1px solid transparent;
  background: var(--panel);
  box-shadow: var(--soft-shadow-lg);
}
/* the brand crown + bloom live on the 3rd-i panel only */
.duel-panel--us::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  z-index: 2;
  background: var(--grad);
  opacity: 0.92;
}
.duel-panel--us::after {
  content: "";
  position: absolute;
  z-index: -1;
  top: -30%;
  right: -14%;
  width: 70%;
  height: 120%;
  pointer-events: none;
  background: radial-gradient(60% 50% at 70% 40%, rgba(73, 121, 239, 0.15), rgba(243, 26, 145, 0.05) 52%, transparent 74%);
}

.duel-tag {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 13px;
  color: var(--dim);
  font-size: clamp(11.5px, 1.1vw, 14px);
  font-weight: 600;
  letter-spacing: -0.01em;
}
.duel-tag--live { color: var(--text); }
/* Same swap as .pip: this was a gradient dot with an expanding ring pulsing
   under a figure caption. The caption is a label, not video chrome, so it gets
   the brand notch and the pulse is gone. */
.duel-tag-dot { flex: 0 0 auto; width: 16px; height: 4px; border-radius: 999px; background: var(--soft); }
.duel-tag--live .duel-tag-dot {
  background: linear-gradient(90deg, #f52d8c, #8b5cf6 56%, #5678ff);
}

/* ---- the shared drawn-map scene ---- */
.duel-scene {
  position: relative;
  overflow: hidden;
  flex: 1;
  min-height: clamp(190px, 24vw, 300px);
  border-radius: calc(var(--r-lg) - 8px);
  border: 1px solid var(--line);
  background: linear-gradient(165deg, rgba(30, 36, 50, 0.55), rgba(18, 22, 32, 0.7));
  isolation: isolate;
}
.duel-scene::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset: 0;
  background-image: linear-gradient(90deg, rgba(122, 152, 214, 0.09) 1px, transparent 1px), linear-gradient(rgba(122, 152, 214, 0.09) 1px, transparent 1px);
  background-size: 38px 38px;
}
.duel-lot {
  position: absolute;
  z-index: 1;
  border: 1px solid rgba(150, 172, 214, 0.14);
  border-radius: 6px;
  background: rgba(122, 152, 214, 0.05);
}
/* Both scenes are portrait phone screens at the live clip's 9:16, so the
   3rd-i-trip video fills with no crop and no letterbox, and the Find My side is
   the same shape with the life turned off. (2026-08-08, Adam) */
.duel-scene {
  aspect-ratio: 9 / 16;
  min-height: 0;
  width: 100%;
  max-width: clamp(184px, 42vw, 248px);
  margin-inline: auto;
  flex: 0 0 auto;
}
.duel-scene--video { background: #080b16; }
.duel-video {
  position: absolute; z-index: 1; inset: 0;
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.duel-scene--video::before { display: none; }
.duel-scene--video::after {
  content: ""; position: absolute; z-index: 2; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, transparent 58%, rgba(6, 10, 22, 0.5) 100%);
}

/* the Find My side is a real (generic) map with the life turned off */
.duel-panel--them .duel-scene {
  filter: saturate(0.25);
  background-image: url("/assets/brand/findmy-map-dark.webp");
  background-size: cover;
  background-position: center;
}
.duel-panel--them .duel-scene::before,
.duel-panel--them .duel-lot { display: none; }
/* map data credit (OSM/CARTO tiles), small + muted */
.duel-osm {
  position: absolute;
  z-index: 3;
  right: 6px;
  top: 6px;
  padding: 2px 6px;
  border-radius: 6px;
  background: rgba(10, 14, 24, 0.42);
  color: rgba(255, 255, 255, 0.72);
  font-size: 7px;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

/* the stale ghost dot: alive-ish once, not now */
.duel-ghost {
  position: absolute;
  z-index: 2;
  left: 44%;
  top: 46%;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: rgba(122, 132, 152, 0.14);
}
.duel-ghost span {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 3px solid var(--panel);
  background: #8b93a6;
}
.duel-stale {
  position: absolute;
  z-index: 3;
  left: 50%;
  bottom: 12px;
  transform: translateX(-50%);
  white-space: nowrap;
  padding: 7px 12px;
  border-radius: var(--pill);
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--soft);
  font-size: 10.5px;
  font-weight: 600;
}

/* the 3rd-i side: route, traveller, live chrome */
.duel-route { position: absolute; z-index: 2; inset: 0; width: 100%; height: 100%; overflow: visible; }
.duel-route path { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.duel-route-track { stroke: rgba(120, 148, 200, 0.3); stroke-width: 3; stroke-dasharray: 2 10; }
.duel-route-live { stroke-width: 4.5; stroke-dasharray: 236 400; }
.duel-me {
  offset-path: path("M38 192 C 92 168 82 118 148 100 C 214 82 216 58 258 40");
  offset-rotate: 0deg;
  offset-distance: 62%;
}
.duel-me-core {
  fill: url(#duel-grad);
  stroke: #fff;
  stroke-width: 3.5;
  filter: drop-shadow(0 3px 7px rgba(60, 110, 210, 0.5));
}
.duel-me-halo {
  fill: none;
  stroke: rgba(73, 121, 239, 0.45);
  stroke-width: 2;
  transform-box: fill-box;
  transform-origin: center;
  animation: duel-wave 1.9s ease-out infinite;
}
@keyframes duel-wave {
  0% { opacity: 0.7; transform: scale(0.55); }
  80%, 100% { opacity: 0; transform: scale(1.25); }
}
.duel-home {
  position: absolute;
  z-index: 3;
  right: 11%;
  top: 14%;
  width: 12px;
  height: 12px;
  border: 3px solid var(--panel);
  border-radius: 50%;
  background: #22bd87;
  box-shadow: 0 0 0 2px rgba(34, 189, 135, 0.28);
}
.duel-live, .duel-watch, .duel-agent {
  position: absolute;
  z-index: 4;
  display: flex;
  align-items: center;
  border: 1px solid var(--line-hi);
  background: var(--panel);
  box-shadow: var(--soft-shadow);
}
.duel-live {
  top: 12px;
  left: 12px;
  gap: 7px;
  padding: 6px 12px;
  border-radius: var(--pill);
  color: var(--text);
  font-size: 11px;
  font-weight: 750;
}
/* This one stays a dot: it is the LIVE badge on a video scene, where a dot is
   a real convention rather than decoration. What goes is the soft halo ring
   and the breathing animation, which is what made it read as generated. */
.duel-live .rec {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--magenta);
}
.duel-watch {
  top: 12px;
  right: 12px;
  gap: 8px;
  padding: 6px 12px 6px 9px;
  border-radius: var(--pill);
  color: var(--text);
  font-size: 10.5px;
  font-weight: 700;
  white-space: nowrap;
}
.duel-avs { display: flex; padding-left: 7px; }
.duel-avs i {
  display: grid;
  place-items: center;
  width: 21px;
  height: 21px;
  margin-left: -7px;
  border: 2px solid var(--panel);
  border-radius: 50%;
  color: #fff;
  font-size: 6px;
  font-style: normal;
  font-weight: 820;
}
.duel-avs .a1 { background: linear-gradient(145deg, #ff9c80, #eb4d96); }
.duel-avs .a2 { background: linear-gradient(145deg, #45c9f5, #4278e5); }
.duel-avs .a3 { background: linear-gradient(145deg, #a87bf0, #e443b0); }
/* the agent chip is a dark dispatch surface in both themes, on purpose */
.duel-agent {
  left: 12px;
  right: 12px;
  bottom: 12px;
  gap: 9px;
  justify-content: center;
  padding: 9px 12px;
  border-radius: 14px;
  border-color: rgba(255, 255, 255, 0.09);
  background: rgba(14, 17, 24, 0.95);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}
.duel-agent svg { width: 16px; height: 16px; flex: 0 0 auto; color: #70c7ff; }
.duel-agent-short { display: none; }

.duel-cap {
  margin: 14px 2px 0;
  color: var(--dim);
  font-size: clamp(12.5px, 1.15vw, 14.5px);
  line-height: 1.5;
}
.duel-panel--us .duel-cap { color: var(--text); }

/* ---- light theme ---- */
html[data-theme="light"] .duel-scene {
  background: linear-gradient(165deg, #f4f7fe, #eaeffa);
}
html[data-theme="light"] .duel-panel--them .duel-scene {
  background-image: url("/assets/brand/findmy-map-light.webp");
  background-size: cover;
  background-position: center;
}
html[data-theme="light"] .duel-scene::before {
  background-image: linear-gradient(90deg, rgba(112, 144, 198, 0.1) 1px, transparent 1px), linear-gradient(rgba(112, 144, 198, 0.1) 1px, transparent 1px);
}
html[data-theme="light"] .duel-osm {
  background: rgba(255, 255, 255, 0.6);
  color: rgba(40, 52, 74, 0.72);
}
html[data-theme="light"] .duel-panel--us {
  background: linear-gradient(168deg, rgba(60, 158, 255, 0.09), var(--panel) 46%);
}

/* ---- handset: the two panels STAY side by side, smaller ---- */
@media (max-width: 700px) {
  .duel { gap: 10px; }
  .duel-panel { padding: 10px; border-radius: var(--r); }
  .duel-tag { gap: 6px; margin-bottom: 9px; font-size: 10px; }
  .duel-tag-dot { width: 13px; height: 3.5px; }
  .duel-scene { min-height: 210px; border-radius: calc(var(--r) - 5px); }
  /* the two top chips STACK on a narrow scene (side by side they eclipse
     each other and the home pin) */
  .duel-live { top: 8px; left: 8px; padding: 4px 9px; font-size: 9px; }
  .duel-watch { top: 36px; right: auto; left: 8px; padding: 4px 9px 4px 7px; font-size: 8px; gap: 5px; }
  .duel-avs i { width: 16px; height: 16px; margin-left: -6px; font-size: 5px; border-width: 1.5px; }
  .duel-agent { left: 8px; right: 8px; bottom: 8px; padding: 7px 6px; border-radius: 11px; font-size: 8.5px; gap: 5px; letter-spacing: -0.01em; }
  .duel-agent svg { width: 13px; height: 13px; }
  .duel-agent-full { display: none; }
  .duel-agent-short { display: inline; }
  .duel-stale { bottom: 8px; padding: 5px 9px; font-size: 8.5px; max-width: calc(100% - 16px); }
  .duel-ghost { width: 26px; height: 26px; }
  .duel-ghost span { width: 10px; height: 10px; border-width: 2.5px; }
  .duel-home { right: 9%; top: 12%; width: 10px; height: 10px; border-width: 2.5px; }
  .duel-cap { margin-top: 10px; font-size: 11.5px; line-height: 1.45; }
}

@media (prefers-reduced-motion: reduce) {
  .duel-tag--live .duel-tag-dot, .duel-me-halo, .duel-live .rec { animation: none; }
  .duel-me-halo { opacity: 0; }
}

/* punchline: one calm centred line, the essence of the old paragraph */
.already-punch {
  max-width: 40rem;
  margin: clamp(26px, 3vw, 40px) auto 0;
  text-align: center;
  color: var(--dim);
  font-size: clamp(17px, 1.5vw, 21px);
  line-height: 1.5;
  letter-spacing: -0.01em;
}
.already-punch strong { display: block; margin-top: 6px; color: var(--text); font-weight: 600; }

.card-hd {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
  color: var(--dim);
  font-size: 12px;
}
.card-hd b { color: var(--text); }
.rail { margin-top: 4px; }
.rail-item {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 14px;
  padding: 16px 0 16px 18px;
  border-bottom: 1px solid var(--line);
}
.rail-item:last-child { border-bottom: 0; }
.rail-item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 23px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--soft);
}
.rail-item--now::before { background: var(--sky); box-shadow: 0 0 0 4px rgba(92, 193, 246, 0.12); }
.rail-item--mag::before { background: var(--magenta); }
.rail-item h3 { font-size: 14px; letter-spacing: -0.01em; }
.rail-item p { margin: 3px 0 0; font-size: 12px; line-height: 1.45; }
.tstamp { color: var(--soft); font-size: 9px; white-space: nowrap; }
.people { display: grid; gap: 14px; margin-top: 18px; }
.person { display: flex; align-items: center; gap: 12px; }
.person-txt { display: grid; font-size: 13px; }
.person-txt > span { color: var(--soft); font-size: 11px; }
.watching { display: flex; align-items: center; gap: 6px; }
.watching i { width: 5px; height: 5px; border-radius: 50%; background: var(--sky); }
.nudge-note {
  display: flex;
  gap: 12px;
  margin: 20px 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--line);
  color: var(--dim);
  font-size: 12px;
}
.seen { margin-top: 28px; }
.seen-col:not(.seen-col--no) { box-shadow: var(--soft-shadow); }
.seen-col h3 { margin-bottom: 18px; }

/* ---------- nudge, dispatch, proof, fork ------------------------------- */

.chips { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }
/* The preset nudges read as friendly message bubbles: soft sky tint, rounded,
   a little lift. This is the most social moment on the page, so it looks it. */
.chip {
  padding: 11px 16px;
  border: 0;
  border-radius: var(--pill);
  color: var(--acc-sky);
  background: rgba(60, 158, 255, 0.12);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.chip--send {
  color: #fff;
  background: var(--grad);
  box-shadow: 0 8px 20px rgba(73, 121, 239, 0.3);
}
/* The composer chips are real buttons: tapping one lands the nudge on the phone. */
.composer .chip { cursor: pointer; transition: transform 0.12s ease, background 0.2s ease; }
.composer .chip:hover { background: rgba(60, 158, 255, 0.2); }
.composer .chip--send:hover { background: var(--grad); filter: brightness(1.05); }
.composer .chip:active { transform: scale(0.94); }
.composer .chip:focus-visible { outline: 2px solid var(--acc-sky); outline-offset: 2px; }

/* The nudge that lands: an iOS-style push banner that drops in near the top of
   the phone, holds, then slides away (nudge.js toggles .is-live). */
.nudge-toast {
  position: absolute;
  left: 50%;
  top: 5.5%;
  width: 87%;
  z-index: 5;
  display: grid;
  grid-template-columns: 34px 1fr;
  gap: 10px;
  align-items: center;
  padding: 9px 11px;
  border-radius: 17px;
  background: rgba(255, 255, 255, 0.86);
  border: 1px solid rgba(255, 255, 255, 0.7);
  box-shadow: 0 14px 30px rgba(20, 34, 70, 0.26);
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
  backdrop-filter: blur(12px) saturate(1.4);
  text-align: left;
  opacity: 0;
  pointer-events: none;
  transform: translateX(-50%) translateY(-150%) scale(0.96);
  transition: transform 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.25), opacity 0.35s ease;
}
.nudge-toast.is-live {
  opacity: 1;
  transform: translateX(-50%) translateY(0) scale(1);
}
.nt-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: var(--grad);
  color: #fff;
  font-size: 15px;
  font-weight: 700;
}
.nt-text { display: grid; gap: 1px; min-width: 0; }
.nt-title {
  font-size: 12.5px;
  font-weight: 700;
  color: #0e1830;
  letter-spacing: -0.01em;
}
.nt-body {
  font-size: 12.5px;
  color: #33405c;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (prefers-reduced-motion: reduce) {
  .nudge-toast { transition: opacity 0.2s ease; transform: translateX(-50%) translateY(0) scale(1); }
}
.returns { display: grid; align-content: center; gap: 10px; }
.rline {
  display: grid;
  grid-template-columns: 24px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.rline:last-child { border-bottom: 0; }
.rline > span { color: var(--soft); font-size: 11px; }
.mk { width: 24px; height: 24px; }
.mk .m1 { stroke: var(--magenta); fill: none; }
.mk .m2 { stroke: var(--royal); fill: none; }
.mk .mc { fill: var(--sky); }
.ret > .wrap > .note { margin: 26px auto 0; }
.dcard { display: flex; flex-direction: column; }
.dcard-top { display: flex; align-items: center; gap: 13px; margin-bottom: 16px; }
.dcard-top .who { margin: 0; }
.dcard-ico {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 13px;
  color: var(--acc-sky);
  background: rgba(30, 139, 254, 0.12);
  border: 1px solid rgba(30, 139, 254, 0.18);
}
.dcard-ico svg { width: 23px; height: 23px; }
.dcard-ico--alarm {
  color: var(--alarm);
  background: rgba(239, 59, 59, 0.12);
  border-color: rgba(239, 59, 59, 0.22);
}
.dcard-status {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 18px 0 0;
  padding-top: 16px;
  border-top: 1px solid rgba(239, 59, 59, 0.16);
  color: var(--alarm);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.dcard-status .live {
  background: var(--alarm);
  box-shadow: 0 0 0 0 rgba(239, 59, 59, 0.5);
  animation: pulse-dot 1.9s ease-out infinite;
}
@keyframes pulse-dot {
  0% { box-shadow: 0 0 0 0 rgba(239, 59, 59, 0.45); }
  70% { box-shadow: 0 0 0 8px rgba(239, 59, 59, 0); }
  100% { box-shadow: 0 0 0 0 rgba(239, 59, 59, 0); }
}
.dcard--alarm {
  border-color: rgba(239, 59, 59, 0.28);
  background:
    linear-gradient(160deg, rgba(239, 59, 59, 0.07), rgba(var(--panel-rgb), 0.92) 46%);
}
.dcard--alarm .who { color: var(--alarm); background: none; -webkit-text-fill-color: initial; }

/* ---------- premium interaction and accent layer ----------------------- */

/* One gradient hairline along the top of the "answer" card in each pair, so the
   eye lands on the 3rd-i side of every comparison. */
.vs-card--live,
.fork-card,
.dcard--alarm { position: relative; overflow: hidden; }
.vs-card--live::before,
.fork-card::before,
.dcard--alarm::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--grad);
  opacity: 0.9;
}
.fork-card--ent::before { opacity: 0.5; }

/* Feature cards lift on a real pointer, matching the app's own soft depth. */
@media (hover: hover) and (pointer: fine) {
  .vs-card,
  .dcard,
  .fork-card,
  .vid {
    transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1),
      border-color 320ms ease, box-shadow 320ms ease;
  }
  .vs-card:hover,
  .dcard:hover,
  .fork-card:hover {
    transform: translateY(-6px) scale(1.008);
    border-color: var(--line-hi);
    box-shadow: 0 34px 74px rgba(8, 12, 22, 0.16);
  }
  .dcard--alarm:hover { box-shadow: 0 34px 74px rgba(239, 59, 59, 0.14); }
}

/* Tactile press feedback on the interactive controls (works on touch + click),
   so the site feels like the app it is selling. Reduced-motion safe. */
@media (prefers-reduced-motion: no-preference) {
  .btn, .hh-store, .hh-watch, .btn-primary, .btn-ghost {
    transition: transform 200ms cubic-bezier(0.22, 1, 0.36, 1), background 180ms ease,
      border-color 180ms ease, box-shadow 200ms ease, filter 180ms ease;
  }
  .btn:active, .hh-store:active, .hh-watch:active,
  .btn-primary:active, .btn-ghost:active {
    transform: translateY(0) scale(0.965);
    transition-duration: 90ms;
  }
}
.press { text-align: center; }
.press-lead { margin: 0 0 22px; }

/* The press logos are light-knockout lockups built for dark backgrounds (South
   Florida Business Journal and U Miami are white artwork on solid bars), so the
   ribbon is one calm dark "featured in" panel rather than a row of white tiles.
   The track is two identical halves and the animation slides it exactly one
   half for a seamless loop; the edge gradients fade logos in and out. */
.marquee {
  position: relative;
  width: 100%;
  max-width: 1000px;
  margin: 0 auto;
  overflow: hidden;
  padding: 28px 0;
  border-radius: var(--r);
  background: linear-gradient(180deg, #141c2e, #0d1320);
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: 0 26px 64px rgba(10, 15, 28, 0.22);
}
.marquee::before,
.marquee::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 72px;
  z-index: 2;
  pointer-events: none;
}
.marquee::before { left: 0; background: linear-gradient(90deg, #0f1524, rgba(15, 21, 36, 0)); }
.marquee::after { right: 0; background: linear-gradient(270deg, #0f1524, rgba(15, 21, 36, 0)); }
.marquee-track {
  display: flex;
  width: max-content;
  animation: marquee 46s linear infinite;
}
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-half { display: flex; align-items: center; }
@keyframes marquee { to { transform: translateX(-50%); } }
.press-chip {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  height: 44px;
  margin: 0 28px;
}
.press-chip img {
  width: auto;
  max-width: 140px;
  max-height: 30px;
  object-fit: contain;
  /* The -mono assets are pre-normalised to white-knockout on transparency so
     the whole wall reads as one set on the dark panel. */
  opacity: 0.82;
  transition: opacity 240ms ease;
}
.marquee:hover .press-chip img { opacity: 1; }
.press-chip--txt {
  color: rgba(255, 255, 255, 0.82);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

/* The as-seen strip sits right below the home hero in the slot the LIVE+HUMAN
   rail used to occupy, and matches that rail's footprint: 1220px wide, one
   rail-height panel. The section that follows keeps a reduced top padding so
   hero -> press -> content reads as one flow instead of three distant blocks. */
.asseen-strip {
  position: relative;
  z-index: 8;
  margin: clamp(26px, 3.2vw, 44px) 0 0;
}
.asseen-strip .wrap { width: min(1220px, calc(100% - 40px)); }
.asseen-strip .marquee { max-width: none; padding: 24px 0; }
.asseen-strip + .ret { padding-top: clamp(56px, 7vw, 96px); }

/* One sourced line of press proof (index #say), sitting between the
   free-alternative statement and the marquee. Brand hairline over a centred
   quote; ret--tight closes the gap to the section above it. */
.ret--tight { padding-top: 0; }
.pull { max-width: 42ch; margin-inline: auto; text-align: center; }
.pull blockquote {
  margin: 0;
  font-size: clamp(22px, 3vw, 32px);
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--text);
}
.pull blockquote::before {
  content: "";
  display: block;
  width: 40px;
  height: 3px;
  margin: 0 auto 24px;
  border-radius: 2px;
  background: linear-gradient(90deg, #5cc1f6, #4979ef, #f31a91);
}
.pull figcaption {
  margin-top: 18px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--soft);
}

/* The free-alternative statement paragraph (index #already). */
.already-copy { max-width: 58ch; margin-inline: auto; }

/* Pricing justification line, directly above the plans grid (product). */
.plans-why {
  max-width: 46rem;
  margin: 0 0 clamp(38px, 5vw, 56px);
  color: var(--text);
  font-size: clamp(17px, 1.7vw, 20px);
  line-height: 1.5;
  font-weight: 500;
  letter-spacing: -0.012em;
}

/* Static press strip (enterprise page, inside a column) reuses the chip look. */
/* Same dark "featured in" treatment as the homepage marquee: the logos are
   light-knockout mono assets, so they sit on one dark panel instead of white
   tiles that boxed their baked-in backgrounds. */
.press-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: clamp(22px, 4vw, 44px);
  padding: 20px clamp(20px, 3vw, 30px);
  border-radius: var(--r);
  background: linear-gradient(180deg, #141c2e, #0d1320);
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: 0 22px 52px rgba(10, 15, 28, 0.2);
}
.press-row img {
  height: 27px;
  width: auto;
  max-width: 140px;
  object-fit: contain;
  opacity: 0.82;
  transition: opacity 220ms ease;
}
.press-row img:hover { opacity: 1; }

/* Theme-aware press strips. The panels + white-knockout logos above are the
   DARK-mode treatment. In light mode (the site default) a permanent dark box
   looked out of place, so the panel goes light and the mono logos invert to a
   soft dark grey. Applies to both the homepage marquee and the enterprise row. */
html[data-theme="light"] .marquee,
html[data-theme="light"] .press-row {
  background: linear-gradient(180deg, #ffffff, #eef2f9);
  border-color: rgba(28, 40, 82, 0.09);
  box-shadow: 0 20px 48px rgba(40, 60, 100, 0.1);
}
html[data-theme="light"] .marquee::before { background: linear-gradient(90deg, #f3f6fb, rgba(243, 246, 251, 0)); }
html[data-theme="light"] .marquee::after { background: linear-gradient(270deg, #f3f6fb, rgba(243, 246, 251, 0)); }
html[data-theme="light"] .press-chip img,
html[data-theme="light"] .press-row img { filter: invert(1); opacity: 0.6; }
html[data-theme="light"] .marquee:hover .press-chip img,
html[data-theme="light"] .press-row img:hover { opacity: 0.85; }
html[data-theme="light"] .press-chip--txt { color: rgba(28, 40, 82, 0.68); }

.videos {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin-top: 30px;
}
.vid {
  overflow: hidden;
  padding: 0;
  text-align: left;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--panel);
  cursor: pointer;
}
.vid-shot { position: relative; display: block; aspect-ratio: 16 / 9; background: var(--panel-2); }
.vid-shot img { width: 100%; height: 100%; object-fit: cover; opacity: 0.82; transition: opacity 180ms ease, transform 300ms ease; }
.vid:hover .vid-shot img { opacity: 1; transform: scale(1.02); }
.vid-play {
  position: absolute;
  left: 16px;
  bottom: 16px;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--grad);
  box-shadow: 0 10px 30px rgba(73, 121, 239, 0.3);
}
.vid-play svg { width: 17px; fill: #fff; }
.vid-meta { display: grid; gap: 3px; padding: 15px 17px 17px; }
.vid-meta b { font-size: 13px; }
.vid-meta span { color: var(--soft); font-size: 11px; }
.vid-frame { aspect-ratio: 16 / 9; }
.vid-frame iframe { width: 100%; height: 100%; border: 0; }
.fork-card { display: flex; flex-direction: column; }
.fork-card--ent { background: linear-gradient(145deg, rgba(73, 121, 239, 0.1), rgba(var(--panel-rgb), 0.92) 48%); }
.fork-card .cta-row { margin-top: auto; padding-top: 26px; }
.fork-price { margin: 20px 0 0; font-size: 13px; }

/* ---------- product page ----------------------------------------------- */

.trip-line { display: none; }
.stops { grid-template-columns: repeat(3, minmax(0, 1fr)); counter-reset: stop; }
.stop {
  position: relative;
  min-height: 240px;
  padding: 28px;
  border-radius: var(--r);
}
.stop::before {
  counter-increment: stop;
  content: "0" counter(stop);
  position: absolute;
  right: 24px;
  top: 20px;
  color: var(--line-hi);
  font-size: 46px;
  font-weight: 600;
  letter-spacing: -0.06em;
}
.stop .tstamp { display: block; margin-bottom: 56px; }
.stop h3 { max-width: 12ch; margin-bottom: 12px; }
.stop p { margin-bottom: 0; font-size: 14px; }
.split { align-items: center; }
/* #app "What is actually on the screen": the phone floats on a brand glow, no
   card plate. The render is a complete device with transparent corners, so it
   needs no crop mask; do not re-add one. */
.shot-plate { position: relative; display: grid; place-items: center; padding: clamp(12px, 2vw, 24px); }
.shot-plate::before {
  content: ""; position: absolute; inset: 6% 4%; z-index: 0;
  background:
    radial-gradient(closest-side, rgba(60, 158, 255, 0.24), transparent 72%),
    radial-gradient(closest-side at 66% 74%, rgba(242, 74, 170, 0.18), transparent 70%);
  filter: blur(13px); pointer-events: none;
}
.shot-plate img {
  position: relative; z-index: 1;
  /* height:auto so the image scales by aspect ratio from its width. Without it,
     the global `img { max-width:100% }` reset leaves height governed by the
     height="1895" attribute, which desktop hid behind max-height:680px but mobile
     (max-height:none) let blow up into a ~1895px void. */
  width: min(100%, 310px); height: auto; max-height: 680px; object-fit: contain;
  filter: drop-shadow(0 32px 48px rgba(20, 34, 70, 0.28));
}
.cols { gap: 0; }
.cols > div { padding: 22px 0; border-bottom: 1px solid var(--line); }
.cols > div:last-child { border-bottom: 0; }
.cols h3 { margin-bottom: 8px; }
.cols p { margin: 0; color: var(--dim); }
.plan-group + .plan-group { margin-top: 56px; }
.plan-group-hd {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 18px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
.plan-group-hd p { margin: 0; color: var(--dim); }
.plans { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.plan { position: relative; min-height: 420px; }
.plan--mid {
  transform: translateY(-8px);
  border-color: rgba(73, 121, 239, 0.44);
  background: linear-gradient(155deg, rgba(73, 121, 239, 0.11), rgba(var(--panel-rgb), 0.96) 42%);
}
.plan-badge {
  display: inline-flex;
  width: fit-content;
  margin-bottom: 18px;
  padding: 6px 9px;
  border-radius: 6px;
  color: #fff;
  background: var(--grad);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}
.plan-badge--quiet { color: var(--dim); background: var(--panel-2); }
.plan .price { margin: 24px 0 0; color: var(--text); font-size: 40px; font-weight: 600; letter-spacing: -0.05em; }
.plan .per { font-size: 12px; }

/* ---------- enterprise -------------------------------------------------- */

.uni-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.uni-card { min-height: 270px; }
.uni-card .mk { margin-bottom: 46px; }
.uni-card h3 { margin-bottom: 12px; }
.uni-card p { margin-bottom: 0; font-size: 14px; }
.tag-ph {
  display: inline-flex;
  margin-right: 6px;
  padding: 3px 7px;
  border: 1px solid var(--line-hi);
  border-radius: 5px;
  color: var(--dim);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.form {
  max-width: 720px;
  display: grid;
  gap: 18px;
  padding: clamp(24px, 4vw, 42px);
}
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.form .field { display: grid !important; gap: 7px; }
.form label { font-size: 13px; font-weight: 600; }
.form input,
.form select,
.form textarea {
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  color: var(--text);
  background: var(--void);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-size: 16px;
}
.form textarea { min-height: 120px; resize: vertical; }
.form input:focus,
.form select:focus,
.form textarea:focus { outline: 2px solid var(--royal); outline-offset: 2px; }
.form .btn { justify-self: start; }

/* ---------- close and footer ------------------------------------------- */

.close {
  position: relative;
  min-height: 74svh;
  display: grid;
  align-items: center;
  padding: clamp(110px, 14vw, 190px) 0;
  overflow: hidden;
}
/* A warm circle of light behind the send-off, so the page ends on people, not
   on another grey block. */
.close::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(120vw, 1100px);
  height: min(120vw, 1100px);
  transform: translate(-50%, -50%);
  z-index: -1;
  background:
    radial-gradient(circle at 30% 30%, rgba(60, 158, 255, 0.16), transparent 58%),
    radial-gradient(circle at 72% 66%, rgba(242, 74, 170, 0.13), transparent 58%);
  filter: blur(8px);
  pointer-events: none;
}
.close-stage,
.close-scrim { display: none; }
.close .wrap { text-align: left; }
.close h2 { max-width: 13ch; }
.close .lede { max-width: 42rem; margin: 26px 0 0; }
.close .cta-row { justify-content: flex-start; }

/* The chosen circle, revealed: overlapping friendly discs above the send-off. */
.circle-row {
  display: flex;
  align-items: center;
  margin-bottom: 30px;
}
.circle-row .disc {
  width: 54px;
  height: 54px;
  margin-left: -12px;
  font-size: 14px;
  box-shadow: 0 10px 26px rgba(40, 64, 140, 0.2);
}
.circle-row .disc:first-child { margin-left: 0; }
.circle-row .disc--empty { background: var(--panel-2); }
.circle-row .disc--empty::after { content: "+"; color: var(--soft); font-size: 20px; font-weight: 400; }
.foot {
  padding: 56px 0 34px;
  border-top: 1px solid var(--line);
  background: rgba(var(--void-rgb), 0.9);
}
.foot-in { display: flex; align-items: flex-start; justify-content: space-between; gap: 34px; }
.foot-brand img { width: 72px; }
.foot-brand p { max-width: 400px; margin: 14px 0 0; color: var(--dim); font-size: 13px; }
.foot-nav { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 14px 24px; }
.foot-legal { margin: 38px 0 0; padding-top: 22px; border-top: 1px solid var(--line); color: var(--soft); font-size: 11px; }
/* Footer social row (2026-08-07): verified official 3rd-i accounts. */
.foot-social { display: flex; align-items: center; gap: 12px; margin: 26px 0 0; }
.foot-social-label { color: var(--dim); font-size: 12px; font-weight: 600; letter-spacing: 0.02em; margin-right: 2px; }
.foot-soc {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--dim);
  box-shadow: var(--soft-shadow);
  transition: color 160ms ease, border-color 160ms ease, transform 160ms ease;
}
.foot-soc:hover { color: var(--text); border-color: var(--line-hi); transform: translateY(-2px); }
.foot-soc svg { width: 19px; height: 19px; }

/* ---------- reveal ------------------------------------------------------ */

.rv {
  opacity: 0;
  transform: translateY(24px);
  /* Opacity settles a touch faster than the rise for a softer, more premium
     glide. Transform stays translate-only: road.js revealShift() compensates
     translate but not scale, so a scaled reveal would drift heading anchors. */
  transition: opacity 560ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 720ms cubic-bezier(0.16, 1, 0.3, 1);
}
.rv.in { opacity: 1; transform: none; }
.d1 { transition-delay: 80ms; }
.d2 { transition-delay: 160ms; }
.d3 { transition-delay: 240ms; }

/* ---------- responsive -------------------------------------------------- */

@media (max-width: 980px) {
  /* The centred phone no longer leaves clean room on the left, so the floating
     watch card would crowd it - drop it below desktop. */
  .watch-card { display: none; }
  /* -- Mobile menu: full-viewport brand sheet ---------------------------- */
  /* An opaque glass surface (nothing bleeds through) with large staggered rows,
     a chevron affordance, a gradient-text active state and a pinned footer
     (appearance toggle + full-width CTA + trust line). The burger morphs to an
     X; body scroll locks while it is open.
     The sheet covers the WHOLE viewport, including the band the floating
     capsule sits in, and takes a negative z-index so it passes BEHIND the
     capsule while staying above the page. That is what removes the strip of
     page that would otherwise show around a pill-shaped bar. Its rows start
     below the capsule. Do not reinstate the old top: var(--header-h) box. */
  .hdr-nav {
    position: fixed;
    inset: 0;
    z-index: -1;
    height: 100vh;
    height: 100dvh;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0;
    padding: calc(var(--header-h) + 14px) 22px calc(24px + env(safe-area-inset-bottom, 0px));
    background:
      radial-gradient(120% 46% at 50% 0%, rgba(73, 121, 239, 0.14), transparent 62%),
      var(--glass-solid);
    -webkit-backdrop-filter: blur(26px) saturate(150%);
    backdrop-filter: blur(26px) saturate(150%);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-12px);
    transition: opacity 0.3s ease, transform 0.4s cubic-bezier(0.16, 1, 0.3, 1),
      visibility 0s linear 0.4s;
  }
  .hdr-nav.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity 0.3s ease, transform 0.44s cubic-bezier(0.16, 1, 0.3, 1),
      visibility 0s;
  }
  /* Staggered reveal of the top-level rows + the footer. */
  .hdr-nav.is-open > * { animation: navRowIn 0.5s cubic-bezier(0.16, 1, 0.3, 1) both; }
  .hdr-nav.is-open > :nth-child(1) { animation-delay: 0.05s; }
  .hdr-nav.is-open > :nth-child(2) { animation-delay: 0.1s; }
  .hdr-nav.is-open > :nth-child(3) { animation-delay: 0.15s; }
  .hdr-nav.is-open > :nth-child(4) { animation-delay: 0.22s; }
  @keyframes navRowIn {
    from { opacity: 0; transform: translateY(12px); }
    to { opacity: 1; transform: none; }
  }
  /* Home appears on mobile; the nested group/sub become stacked blocks. */
  .nav-home { display: block; }
  .nav-group,
  .nav-sub { display: block; }
  /* Primary rows: label left, chevron right, generous tap height. */
  .hdr-nav > a,
  .nav-group > a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    width: 100%;
    padding: 20px 4px;
    border-bottom: 1px solid var(--line);
    font-size: 22px;
    font-weight: 640;
    letter-spacing: -0.022em;
    color: var(--text);
  }
  .hdr-nav > a::after,
  .nav-group > a::after,
  .nav-sub a::after {
    content: "";
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    margin-right: 3px;
    border-right: 2px solid var(--dim);
    border-top: 2px solid var(--dim);
    border-radius: 1px;
    transform: rotate(45deg);
    transition: border-color 0.2s ease;
    background: none;
    position: static;
    inset: auto;
  }
  /* Plans nested under How it Works: indented, lighter, with a vertical
     gradient hairline standing in for the old corner connector. */
  .nav-sub a {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 16px 4px 16px 22px;
    border-bottom: 1px solid var(--line);
    font-size: 17px;
    font-weight: 540;
    color: var(--dim);
  }
  .nav-sub a::before {
    content: "";
    position: absolute;
    left: 6px;
    top: 12px;
    bottom: 12px;
    width: 2px;
    border-radius: 2px;
    background: var(--grad);
    opacity: 0.55;
  }
  /* Active page: gradient-text label + royal chevron (overriding the desktop
     underline geometry inherited from the base rule). */
  .hdr-nav > a[aria-current="page"],
  .nav-group > a[aria-current="page"],
  .nav-sub a[aria-current="page"] {
    color: transparent;
    background: var(--grad);
    -webkit-background-clip: text;
    background-clip: text;
  }
  .hdr-nav a[aria-current="page"]::after {
    position: static;
    inset: auto;
    left: auto;
    right: auto;
    bottom: auto;
    width: 7px;
    height: 7px;
    border-right: 2px solid var(--royal);
    border-top: 2px solid var(--royal);
    background: none;
    transform: rotate(45deg);
  }
  /* Footer pinned to the base of the sheet. */
  .nav-foot {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin-top: auto;
    padding-top: 24px;
  }
  .nav-appearance {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 2px;
    color: var(--dim);
    font-size: 14px;
    font-weight: 600;
  }
  .nav-foot .nav-theme { display: inline-flex; flex: 0 0 auto; }
  .nav-foot .nav-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 54px;
    font-size: 16px;
    font-weight: 640;
    /* Beat the .hdr-nav a descendant colour so the gradient pill keeps white
       text (it otherwise inherits --dim and reads as grey on the gradient). */
    color: #fff;
  }
  .nav-trust {
    margin: 2px 0 0;
    color: var(--dim);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: -0.01em;
    line-height: 1.5;
    text-align: center;
    opacity: 0.85;
  }
  .nav-btn { display: inline-flex; justify-self: end; }
  .hdr .hdr-in {
    grid-template-columns: auto 1fr auto;
    gap: 14px;
    padding-inline: 16px 8px;
  }
  .hdr-end .theme-toggle { display: none; }
  .hero-atlas { grid-template-columns: 1fr; }
  .hero-copy h1 { max-width: 11ch; }
  .trip-window { width: min(100%, 600px); margin-inline: auto; min-height: 600px; }
  .uni-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* The menu still opens/closes for reduced-motion users, just without the
   slide and staggered reveal (the burger->X state change is kept). */
@media (prefers-reduced-motion: reduce) {
  .hdr-nav { transition: opacity 0.01s linear, visibility 0s; transform: none; }
  .hdr-nav.is-open > * { animation: none; }
  .nav-bar { transition: none; }
  .hdr::after { transition: none; }
}

@media (max-width: 760px) {
  .wrap { width: min(calc(100% - 36px), var(--wrap)); }
  /* The road now uses the SAME serpentine-underline format as desktop (it
     underlines each heading and weaves down past the subtitle on alternating
     sides), so the old reserved left rail lane is gone - the copy is centred and
     the road's descents live in the side gutters. */
  /* On a handset the road runs close to the text, so the wide glow would bleed
     over the glyphs. Tighten the halo to a hairline and thin the stroke so it
     reads as a map route, not a bar laid over the words. */
  html { --route-shadow: 0 0 2px rgba(73, 121, 239, 0.22); }
  .route-live,
  .route-ink { stroke-width: 2; }
  /* Same 64px to the bar's bottom edge as before the capsule, now split into a
     12px float and a 52px pill so the mobile sheet and the pinned indoor-map
     stage keep their existing seat. */
  :root {
    --header-gap: 12px;
    --header-h: 64px;
    --header-w: min(calc(100% - 28px), var(--wrap));
  }
  .hdr-end .btn { min-height: 34px; padding-inline: 13px; }
  h1 { font-size: clamp(45px, 14.5vw, 66px); }
  h2 { font-size: clamp(34px, 10.5vw, 48px); }
  .on-wide { display: none; }
  /* Copy leads on a handset. The eyebrow, headline, download button and proof
     line are the first things in view; the phone follows as supporting proof
     rather than eating the whole top of the screen (which pushed the download
     button below the fold). The headline is sized to hold to ~two lines so the
     CTA lands above the fold on a short handset. */
  .hero { min-height: auto; padding: 0; }
  .hero-atlas {
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 20px 0 44px;
  }
  .hero-copy { order: 0; flex: 0 0 auto; }
  .hero-copy .eyebrow { margin-bottom: 12px; }
  .hero-copy h1 { font-size: clamp(34px, 9.6vw, 46px); max-width: 15ch; }
  .hero-copy .lede { font-size: 17px; margin-top: 16px; max-width: 42ch; }
  .hero-copy .cta-row { margin-top: 22px; }
  .hero-copy .proof { margin-top: 16px; }
  .trip-window {
    order: 1;
    width: 100%;
    min-height: 0;
    margin: 28px auto 0;
  }
  .trip-window::before { inset: 5% 6%; }
  /* Compact supporting visual: sized to the column width, not the viewport
     height, so it never balloons to fill the screen. */
  .device-clean { width: min(58vw, 258px); }
  .sonar { width: min(112vw, 520px); height: min(112vw, 520px); }
  /* The orbit discs and the loose corner chips become collisions in a narrow
     column, so the handset hero keeps just the live badge and destination. */
  .orb,
  .hero-street-key,
  .squad-float { display: none; }
  .hero-legend { display: none; }
  .trip-status { top: 8%; left: 2%; }
  .map-address { right: 2%; bottom: 12%; width: 168px; }
  .page-hero { min-height: auto; padding: 92px 0 110px; }
  .page-hero .lede { font-size: 18px; }
  .ret { padding: 100px 0; }
  .ret::before { inset: 22px 8px; }
  .ret-head { margin-bottom: 40px; }
  .ret-head .lede { font-size: 18px; }
  .cols,
  .watch,
  .versus,
  .nudge-grid,
  .dispatch,
  .fork,
  .seen,
  .split,
  .plans,
  .uni-grid,
  .stops,
  .versus.versus--media,
  .nudge-grid.nudge-grid--media,
  .fork.fork--media { grid-template-columns: 1fr; }
  /* Screenshot sections on a handset: the phone reads as a compact, centred
     screenshot paired tightly with its UI, not a full-width plate that
     dominates the screen. The plate chrome is dropped (the screenshot keeps its
     own drop-shadow) and the gap to the copy/UI is tightened so the two read as
     one unit. */
  .shot-plate {
    padding: 4px;
    overflow: visible;
    background: transparent;
    border: 0;
    box-shadow: none;
  }
  .shot-plate img { width: min(56vw, 216px); max-height: none; }
  .phone-plate { padding: 4px; }
  .phone-plate img { max-width: 216px; }
  .split { gap: 14px; }
  .fork.fork--media { gap: 20px; }
  /* The app-sheet split keeps the desktop side-by-side on a handset: the
     screenshot sits beside its real UI rows so they read as one demonstration.
     Rows and chips compress so the copy still fits the narrower column. */
  /* Handset (Adam 2026-08-06): the phone sits BEHIND the cards, which stack in
     front over its lower half. Flatter cards (reduced "glass") so they read
     cleanly over the screenshot. */
  .split--ui {
    display: flex; flex-direction: column; align-items: center;
    position: relative;
  }
  .split--ui .shot-plate {
    z-index: 0; padding: 0; margin: 0; width: min(66vw, 264px);
  }
  .split--ui .shot-plate img { width: 100%; max-width: none; }
  .split--ui > .rv.d1 { position: relative; z-index: 1; width: 100%; margin-top: -78px; }
  .split--ui .app-sheet { gap: 12px; }
  /* Tight side: drop the timeline connector + node dots (Adam 2026-08-06). */
  .split--ui .app-sheet--timeline { padding-left: 0; }
  .split--ui .app-sheet--timeline::before,
  .split--ui .app-sheet--timeline .app-row::before { display: none; }
  .split--ui .app-row {
    grid-template-columns: 54px 1fr;
    min-height: 0;
    gap: 15px;
    padding: 16px 18px;
    border-radius: 18px;
    box-shadow: 0 4px 14px rgba(20, 34, 70, 0.10);
  }
  .split--ui .app-row .chip { width: 54px; height: 54px; border-radius: 15px; }
  .split--ui .app-row .chip svg { width: 25px; height: 25px; }
  .split--ui .app-row b { font-size: 15.5px; }
  .split--ui .app-row span { font-size: 13px; line-height: 1.4; }
  .split--ui .sheet-cap { font-size: 12px; }
  .split--ui .widgets { flex-wrap: wrap; gap: 9px; }
  .split--ui .widget { width: 48px; height: 48px; }
  /* The device becomes the moment: it runs oversized and bleeds off the right
     edge so you see most of the screen, with the callouts naming real features
     in the space on the left. */
  .nudge-grid.nudge-grid--media { gap: 30px; }
  .showcase {
    order: -1;
    margin: 6px calc(-1 * (50vw - 50%)) 34px 0;
    padding-left: 8px;
  }
  .showcase-phone {
    width: 74vw;
    max-width: 360px;
    margin: 0 0 0 auto;
    transform: translateX(16%) scale(var(--s, 1));
  }
  .showcase-glow { inset: -6% -4% -6% -18%; }
  .callout b { font-size: 12px; padding: 7px 12px; }
  /* On a handset the right-hand callouts would sit on the bled-off part, so the
     pill flips to the left of its dot and reaches back into the visible space. */
  .callout--r::after { left: auto; right: 5px; }
  .callout--r b { left: auto; right: 22px; }
  .callout--l { --x: 8%; }
  /* #nudge on a handset: the phone and the "nudges your squad can send" composer
     sit side by side (the chips are short enough to share the row), instead of a
     bled-off phone with the composer stacked underneath. The floating callouts
     are dropped here since there is no room for them beside the composer. */
  /* #nudge on a handset mirrors desktop: the phone keeps all four callouts, and
     the composer drops to a normal card below it (the responsive form of the
     desktop side-by-side). The callout pills reach INWARD onto the phone so the
     same four labels fit the handset width instead of running off the edges. */
  .nudge-grid.nudge-grid--media {
    display: block;
    position: relative;
  }
  .nudge-grid--media .showcase {
    order: 0;
    margin: 0 auto;
    padding: 0;
    /* Wider than the phone artwork itself: the legend pills under the image
       need the room (the img is capped separately at 66vw). */
    width: min(92vw, 380px);
  }
  .nudge-grid--media .showcase-phone { width: 100%; margin: 0 auto; transform: none; }
  .nudge-grid--media .showcase-glow { inset: -8%; }
  .nudge-grid--media .nudge-side { margin: 22px auto 0; max-width: 440px; }
  .nudge-grid--media .chips { gap: 9px; margin-top: 16px; }
  .nudge-grid--media .chip { font-size: 13px; padding: 8px 13px; }
  .nudge-grid--media .callout b { font-size: 10.5px; padding: 5px 9px; }
  .nudge-grid--media .callout::after { width: 11px; }
  .nudge-grid--media .callout--l { --x: 11%; }
  .nudge-grid--media .callout--l::after { left: 4px; right: auto; }
  .nudge-grid--media .callout--l b { left: 15px; right: auto; }
  .nudge-grid--media .callout--r { --x: 89%; }
  .nudge-grid--media .callout--r::after { right: 4px; left: auto; }
  .nudge-grid--media .callout--r b { right: 15px; left: auto; }
  /* On a handset the floating callouts come OFF the artwork entirely (Adam
     2026-08-06: chips overlaid on a 300px phone read as clutter). The phone
     shows clean, and the four labels become a small legend of static-position
     pills underneath it; their dot anchors and connector lines disappear with
     them. The tap-triggered nudge toast still lands on the phone itself. */
  .nudge-grid--media .showcase-phone {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, auto));
    justify-content: center;
    align-items: center;
    column-gap: 9px;
    row-gap: 9px;
    transform: none;
  }
  .nudge-grid--media .showcase-phone img {
    grid-column: 1 / -1;
    width: min(300px, 66vw);
    justify-self: center;
    margin-bottom: 8px;
  }
  .nudge-grid--media .callout { position: static; }
  .nudge-grid--media .callout::before,
  .nudge-grid--media .callout::after { display: none; }
  .nudge-grid--media .callout b {
    position: static;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    width: 100%;
    transform: none;
    padding: 8px 12px;
    font-size: 12px;
  }
  /* The route spinner's svg is a fixed 44px that deliberately overflows its
     shrunken 20px wrapper in the floating chips; inside a static legend pill
     that reads as a broken icon, so size it honestly here. */
  .nudge-grid--media .callout b .i3s-route { width: 20px; height: 20px; background: none; box-shadow: none; }
  .nudge-grid--media .callout b .i3s-route .i3s-route__svg { width: 100%; height: 100%; }
  /* The centred device (circle) stays centred, it does not bleed. */
  .showcase--c { order: 0; margin: 10px auto 0; padding: 0; }
  .showcase--c .showcase-phone {
    width: 78vw;
    max-width: 320px;
    margin-inline: auto;
    transform: scale(var(--s, 1));
  }
  /* Social sonar tightens on a handset: smaller orbit so the names ride just
     off the phone edges and stay inside the screen. */
  /* The orbit spins on mobile too. Like desktop, the phone rides ABOVE the ring:
     people are visible circling on the left and right, then pass behind the phone
     at the top and bottom of the sonar - they never ride over the screen. The
     orbit radius is tuned so the side avatars clear the phone edges yet stay on a
     handset screen (phone half-width ~128px, radius 162px, avatar half ~21px). */
  /* Client (2026-08-07): the orbiting profile pictures must stay VISIBLE, not
     tuck behind the phone or clip at the viewport. Numbers that satisfy both:
     narrower phone (56vw <= 240px), 146px orbit, 38px rings -> outermost
     extent ~171px fits the ~173px half-column, and the inner pass rides the
     phone's edge instead of vanishing behind it. */
  .social-stage { --orbit: 146px; max-width: 400px; min-height: 600px; }
  .social-stage .showcase--c { margin: 0; }
  .social-stage .showcase-phone { width: min(240px, 56vw); margin-inline: auto; transform: none; }
  .soc-sonar { width: 540px; height: 540px; }
  .soc-friend .ring { width: 38px; height: 38px; }
  .soc-friend b { font-size: 12px; }
  /* Bento stays a grid on mobile: a 2x2 of smaller tiles with the SOS tile as a
     bigger full-width feature at the bottom. No swiper. */
  /* Marquee tiles tighten on a handset (rows themselves live in .bento-rails,
     defined with the desktop rules; only the sizes change here). */
  .brow .feat { width: min(62vw, 240px); }
  .brow .feat-vis { height: 96px; }
  .brow .feat-body { padding: 13px 14px 15px; }
  .brow .feat h3 { margin-bottom: 4px; font-size: 14.5px; }
  .brow .feat-body p { font-size: 12.5px; line-height: 1.45; }
  .brow .feat-vis .vis-golive svg { width: 22px; height: 22px; }
  .brow .feat-vis .vis-sos { font-size: 15px; }
  .feat p { font-size: 13px; line-height: 1.4; }
  .feat--alarm h3 { font-size: 19px; }
  .vis-golive { width: 52px; height: 52px; }
  .vis-golive svg { width: 24px; height: 24px; }
  .vis-sos { width: 74px; height: 74px; }
  .vis-squad .disc-s { width: 42px; height: 42px; margin-left: -12px; font-size: 12px; }
  .vis-tag { font-size: 10px; padding: 5px 9px; }
  .feat--sky .vis-tag { bottom: 12px; right: 12px; }
  .vis-bubbles { width: 90%; }
  .bub { font-size: 12px; padding: 8px 12px; }
  .vis-ghost { height: 90px; width: 82%; }
  .vis-entry { height: 90px; }
  .arc { height: 150px; margin-inline: -12px; }
  .watcher { transform: translate(-50%, -50%) scale(0.82); }
  .plan--mid { transform: none; }
  .plan { min-height: auto; }
  .videos { grid-template-columns: 1fr; gap: 14px; }
  /* The lead video keeps the full card; the news segments compress into
     rows so three videos stop costing three screens of scrolling. */
  .vid:nth-child(n + 2):not(.is-playing) {
    display: grid;
    grid-template-columns: 136px 1fr;
    align-items: stretch;
  }
  .vid:nth-child(n + 2):not(.is-playing) .vid-shot {
    height: 100%;
    min-height: 86px;
    aspect-ratio: auto;
  }
  .vid:nth-child(n + 2):not(.is-playing) .vid-play {
    left: 50%;
    top: 50%;
    bottom: auto;
    transform: translate(-50%, -50%);
    width: 32px;
    height: 32px;
    box-shadow: none;
  }
  .vid:nth-child(n + 2):not(.is-playing) .vid-play svg { width: 13px; }
  .vid:nth-child(n + 2):not(.is-playing) .vid-meta {
    align-self: center;
    padding: 12px 14px;
  }
  .form-row { grid-template-columns: 1fr; }
  .marquee-track { animation-duration: 30s; }
  .marquee { padding: 22px 0; }
  .marquee::before, .marquee::after { width: 44px; }
  .press-chip { height: 34px; margin: 0 18px; }
  .press-chip img { max-width: 116px; max-height: 26px; }
  .press-chip--txt { font-size: 15px; }
  .dcard-status { font-size: 11px; }
  .close { min-height: auto; padding: 120px 0; }
  .foot-in { display: grid; }
  .foot-nav { justify-content: flex-start; }
}

/* Legend pills need one more notch down on the very smallest phones. */
@media (max-width: 360px) {
  .nudge-grid--media .callout b { font-size: 11px; padding: 7px 9px; gap: 5px; }
}


@media (max-width: 480px) {
  .hdr-logo,
  .hdr-logo img { width: 65px; }
  .theme-toggle { display: none; }
  .cta-row { align-items: stretch; }
  .cta-row .btn { flex: 1 1 auto; }
  .hero .cta-row .btn { flex-basis: 100%; }
  .trip-status { font-size: 11px; }
  .map-address { bottom: 10%; }
  .arc { height: 130px; }
  .watcher > b { font-size: 10px; }
  .watcher > span:last-child { display: none; }
  .ring { width: 36px; height: 36px; }
  .rline { grid-template-columns: 22px 1fr; }
  .rline > span { grid-column: 2; }
  .press-row { gap: 20px; padding: 18px 20px; }
  .press-row img { height: 22px; width: auto; max-width: 108px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .rv { opacity: 1; transform: none; }
  .marquee-track { animation: none !important; transform: none !important; }
  .dcard-status .live { animation: none !important; }
  .route-live { stroke-dashoffset: 0 !important; }
  .route-ink { stroke-dashoffset: 0 !important; }
  .route-tip { display: none; }
  .sonar .ping { display: none; }
}

/* Floating CTA: mobile only, bottom-right, appears after the first viewport
   (once the header CTA has scrolled away). Created by app.js from the header
   CTA so the label/href stay page-appropriate. Sits under the header/menu
   layers (z 30+) and hides while the menu sheet is open. */
.float-cta {
  position: fixed;
  right: 16px;
  bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  z-index: 26;
  display: none;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 0 24px;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 999px;
  background: var(--grad);
  background-origin: border-box;
  box-shadow: 0 16px 34px rgba(60, 110, 210, 0.35);
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  text-decoration: none;
  opacity: 0;
  transform: translateY(14px);
  pointer-events: none;
  transition: opacity 240ms ease, transform 280ms cubic-bezier(0.2, 0.82, 0.2, 1);
}
@media (max-width: 900px) { .float-cta { display: inline-flex; } }
.float-cta.is-in { opacity: 1; transform: none; pointer-events: auto; }
body.nav-open .float-cta { opacity: 0; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .float-cta { transition-duration: 0.01ms; } }

/* enterprise #who: the campus render is a complete device on transparent
   corners, so the column no longer has to hide a cropped right edge. The old
   negative margin + mask fade are gone; do not re-add them. */
.fork--media .phone-plate img { justify-self: center; }
.fork--media .fork-card { position: relative; z-index: 1; }

/* Safety Agent panel on /product: the dispatcher art beside the agent story
   (client 2026-08-07: show the human watching over the stream). */
.agent-pair {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  align-items: center;
  gap: clamp(24px, 4vw, 56px);
  margin-top: clamp(56px, 7vw, 96px);
  padding: clamp(22px, 2.6vw, 34px) clamp(24px, 3vw, 44px);
  border-radius: var(--r-lg);
  background: linear-gradient(168deg, rgba(60, 158, 255, 0.1), var(--panel) 46%);
  box-shadow: var(--soft-shadow);
}
.agent-art { margin: 0; }
.agent-art img { display: block; width: 100%; height: auto; border-radius: var(--r); }
.agent-copy h3 { margin: 12px 0 12px; font-size: clamp(22px, 2.2vw, 30px); letter-spacing: -0.025em; }
.agent-copy p:last-child { margin: 0; color: var(--dim); font-size: 15.5px; line-height: 1.62; max-width: 46rem; }
@media (max-width: 860px) {
  .agent-pair { grid-template-columns: 1fr; }
  .agent-art { max-width: 420px; margin-inline: auto; }
}

/* ===========================================================================
   Large monitors (2026-08-07, Adam): the capped column gets breathing room at
   1720px+ and once more at 2400px+, instead of floating in giant margins.
   Deliberately NOT continuous vw scaling: line lengths stay readable, the
   raster app screenshots stay within their sharpness budget, and the
   hand-tuned decorative layer (route ribbon, pins, marquees) keeps its
   proportions. Nothing below 1720px changes.
   ======================================================================== */
@media (min-width: 1720px) {
  :root { --wrap: 1350px; }
  h1 { font-size: clamp(50px, 7vw, 108px); }
  h2 { font-size: clamp(36px, 4.6vw, 71px); }
  h3 { font-size: clamp(19px, 2vw, 27px); }
  .lede { font-size: clamp(18px, 2vw, 25px); }
  .asseen-strip .wrap { width: min(1380px, calc(100% - 40px)); }
  .marquee { max-width: none; }
  .brow .feat { width: clamp(240px, 22vw, 332px); }
  .brow .feat-vis { height: 146px; }
  .feat h3 { font-size: clamp(19px, 1.2vw, 24px); }
}

@media (min-width: 2400px) {
  :root { --wrap: 1480px; }
  .asseen-strip .wrap { width: min(1510px, calc(100% - 40px)); }
}

/* RapidSOS official-partner lockup (client 2026-08-07): a quiet caption row
   under the dispatch story on /product and /enterprise. */
.rsos-partner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin: 18px 0 0;
  color: var(--soft);
  font-size: 13.5px;
}
.rsos-partner img { display: block; height: 24px; width: auto; }
html[data-theme="dark"] .rsos-partner img { content: url("/assets/brand/rapidsos-logo-white.svg"); }
.rsos-partner-tag {
  padding: 4px 10px;
  border: 1px solid var(--line-hi);
  border-radius: var(--pill);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--dim);
}

/* ---------- featured autoplay commercial (home #press, 2026-08-07) --------- */
.vid-feature {
  position: relative;
  margin: 30px 0 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: #05070f;
  box-shadow: var(--soft-shadow-lg);
  aspect-ratio: 16 / 9;
}
.vid-feature-el { display: block; width: 100%; height: 100%; object-fit: cover; }
.vid-feature-cap {
  position: absolute;
  left: 18px;
  bottom: 16px;
  margin: 0;
  padding: 7px 14px;
  border-radius: var(--pill);
  background: rgba(6, 9, 20, 0.5);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: #fff;
  font-size: 12.5px;
}
.vid-feature-cap b { font-weight: 600; }
.vid-sound {
  position: absolute;
  top: 16px;
  right: 16px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px 9px 12px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: var(--pill);
  background: rgba(6, 9, 20, 0.46);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: #fff;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease;
}
.vid-sound:hover { background: rgba(6, 9, 20, 0.66); border-color: rgba(255, 255, 255, 0.5); }
.vid-sound svg { width: 18px; height: 18px; flex: 0 0 auto; }
.vid-sound .vid-sound-on { display: none; }
.vid-sound[aria-pressed="true"] .vid-sound-off { display: none; }
.vid-sound[aria-pressed="true"] .vid-sound-on { display: block; }
.videos--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 760px; margin-inline: auto; }
@media (max-width: 620px) {
  .videos--pair { grid-template-columns: 1fr; }
}

/* ---------- home Instagram feed (#social, 2026-08-07) --------------------- */
.social-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 20px;
  margin-bottom: clamp(26px, 3.4vw, 40px);
}
.social-cta { display: flex; align-items: center; gap: 10px; }
.soc-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 44px;
  padding: 0 14px;
  border: 1px solid var(--line-hi);
  border-radius: var(--pill);
  background: var(--panel);
  box-shadow: var(--soft-shadow);
  color: var(--text);
  font-size: 14px;
  font-weight: 600;
  transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
}
.soc-btn:hover { transform: translateY(-2px); border-color: var(--line-hi); box-shadow: var(--soft-shadow-lg); }
.soc-btn svg { width: 20px; height: 20px; flex: 0 0 auto; }
.soc-btn:not(.soc-btn--ig) { width: 44px; padding: 0; justify-content: center; }
.soc-btn--ig {
  border-color: transparent;
  color: #fff;
  background: linear-gradient(120deg, #f9a03f, #f52c8f 46%, #7a48e8);
  box-shadow: 0 10px 26px rgba(224, 63, 143, 0.28);
}

/* A uniform tile grid of the real posts: each tile is a cover-cropped
   thumbnail linking out to the post, so reels and posts of different native
   shapes read as one neat feed. 3 across desktop, 2 across phones. */
.ig-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(9px, 1.3vw, 15px);
  max-width: 920px;
  margin-inline: auto;
}
.ig-tile {
  position: relative;
  display: block;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: clamp(14px, 1.6vw, 20px);
  background: var(--panel-2);
  box-shadow: var(--soft-shadow);
  isolation: isolate;
}
.ig-tile img,
.ig-tile .ig-vid {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ig-tile img { transition: transform 0.55s cubic-bezier(0.2, 0.6, 0.2, 1); }
/* the preview clip sits over the poster and fades in once it is the active tile */
.ig-vid {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.35s ease;
}
/* gradient progress bar for the active tile */
.ig-prog {
  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: rgba(255, 255, 255, 0.24);
  opacity: 0;
  transition: opacity 0.2s ease;
}
.ig-prog i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--grad);
}
.ig-tile.is-playing .ig-prog { opacity: 1; }
.ig-tile.is-playing .ig-badge { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .ig-prog { display: none; } }
.ig-tile::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(6, 10, 22, 0) 52%, rgba(6, 10, 22, 0.4));
}
.ig-badge {
  position: absolute;
  z-index: 2;
  top: 9px;
  right: 9px;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(10, 14, 24, 0.42);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: #fff;
}
.ig-badge svg { width: 14px; height: 14px; }
.ig-tile:hover img { transform: scale(1.06); }
@media (hover: none) { .ig-tile:hover img { transform: none; } }
@media (max-width: 640px) {
  .ig-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 440px; }
  .social-head { align-items: flex-start; }
}

/* Home #fork audience toggle (segmented control, one card at a time). */
.fork-seg { margin: 0 auto clamp(22px, 3vw, 34px); }
.plans-seg { margin: clamp(6px, 1vw, 14px) auto clamp(18px, 2.4vw, 26px); }
/* the campus/company note now sits directly under the Solo/Family toggle */
.note--plans-top { margin: 0 auto clamp(24px, 3.2vw, 36px); }
#forkPanes { grid-template-columns: 1fr; max-width: 760px; margin-inline: auto; }
#forkPanes > [data-seg-pane][hidden] { display: none; }

/* ============ partner strip — named response & location partners ============
   RapidSOS / GeoComm / CRG / ELI. Each logo sits on a fixed-white chip so the
   real brand colours stay legible in BOTH themes (the chip is white even in
   dark mode, reading as a clean logo card). Hairline border, no heavy shadow —
   matches the calm marketing surface. */
.partner-strip { margin: clamp(28px, 4vw, 48px) 0; }
.partner-strip .partner-lead { color: var(--dim); max-width: 46rem; margin: 10px 0 22px; }
.partner-logos {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; align-items: stretch;
}
.partner-logo {
  display: grid; place-items: center;
  min-height: 84px; padding: 18px 20px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  transition: border-color 200ms ease, transform 200ms ease;
}
.partner-logo:hover { border-color: var(--line-hi); transform: translateY(-2px); }
.partner-logo img { width: auto; max-width: 100%; max-height: 32px; object-fit: contain; display: block; }
@media (max-width: 620px) {
  .partner-logos { grid-template-columns: repeat(2, 1fr); }
  .partner-logo { min-height: 72px; padding: 14px 14px; }
  .partner-logo img { max-height: 26px; }
}
