/* ============================================================
   NUMUS — Design System
   One stylesheet for the whole marketing site.
   Sections: 1 Tokens · 2 Reset · 3 Type · 4 Buttons · 5 Layout
             6 Nav · 7 Components · 8 Device frames · 9 Motion
             10 Footer · 11 Responsive
   ============================================================ */

/* ── 1. TOKENS ─────────────────────────────────────────────── */
:root {
  /* Brand */
  --teal: #00b3a4;
  --teal-deep: #00766a; /* text-safe on white: 4.7:1 */
  --teal-light: #2fe0ce;
  --teal-wash: #eefbf9;
  --teal-line: rgba(0, 179, 164, 0.22);

  --amber: #f5a524;
  --amber-deep: #8a5200; /* text-safe on white */
  --amber-wash: #fff8ec;

  --ink: #0a1826; /* page-dark background */
  --ink-2: #10263b; /* raised dark surface */
  --ink-3: #1c3549; /* hover / hairline-lifted dark surface */

  /* Neutrals */
  --white: #fff;
  --surface: #ffffff;
  --surface-2: #f6f9fb;
  --surface-3: #edf3f6;
  --border: #e3eaf0;
  --border-strong: #cfdae3;

  /* Text */
  --text: #0a1826;
  --text-2: #3d5468;
  /* 5.6:1 on white, 5.3:1 on --surface-2, 5.0:1 on --surface-3 — meta text
     sits on all three, so it has to clear AA against the darkest of them. */
  --text-3: #58697b;
  --on-dark: #ffffff;
  --on-dark-2: rgba(255, 255, 255, 0.72);
  --on-dark-3: rgba(255, 255, 255, 0.46);
  --on-dark-line: rgba(255, 255, 255, 0.12);

  /* Status */
  --green: #16a34a;
  --red: #e5484d;

  /* Elevation — one scale, used everywhere */
  --e1: 0 1px 2px rgba(10, 24, 38, 0.06), 0 1px 3px rgba(10, 24, 38, 0.05);
  --e2: 0 2px 6px rgba(10, 24, 38, 0.06), 0 8px 20px rgba(10, 24, 38, 0.07);
  --e3: 0 4px 12px rgba(10, 24, 38, 0.07), 0 18px 44px rgba(10, 24, 38, 0.1);
  --e4: 0 8px 24px rgba(10, 24, 38, 0.09), 0 32px 70px rgba(10, 24, 38, 0.14);

  /* Radius */
  --r-sm: 8px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 28px;
  --r-pill: 999px;

  /* Motion — built-in easings are too soft; these have intent */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
  --d-press: 140ms;
  --d-hover: 180ms;
  --d-pop: 200ms;
  --d-panel: 260ms;
  --d-reveal: 520ms;

  /* Layout */
  --gutter: 24px;
  --max: 1200px;
  --max-narrow: 760px;
  --nav-h: 68px;

  /* Z-scale */
  --z-nav: 100;
  --z-menu: 110;
  --z-overlay: 900;
  --z-modal: 1000;
}

/* ── 2. RESET ──────────────────────────────────────────────── */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 16px);
}
body {
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 17px;
  line-height: 1.62;
  color: var(--text);
  background: var(--surface);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img,
svg,
video {
  display: block;
  max-width: 100%;
}
/* Domains like `yourbusiness.numuslogistics.com` have no break opportunity,
   so at 320px they set the min-content width of whatever grid track they sit
   in and push the whole column past the viewport. `anywhere` (not
   `break-word`) is the one that also lowers the min-content contribution,
   which is the half that stops the layout blowing out. */
code {
  overflow-wrap: anywhere;
}
img {
  height: auto;
}
a {
  color: inherit;
  text-decoration: none;
}
button,
input,
select {
  font: inherit;
  color: inherit;
}
button {
  background: none;
  border: 0;
  cursor: pointer;
  touch-action: manipulation;
}
ul,
ol {
  list-style: none;
}
:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 3px;
  border-radius: 4px;
}
.dark :focus-visible,
[data-theme="dark"] :focus-visible {
  outline-color: var(--teal-light);
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.skip-link {
  position: absolute;
  left: 16px;
  top: -100px;
  z-index: 999;
  background: var(--ink);
  color: #fff;
  padding: 12px 20px;
  border-radius: var(--r-sm);
  font-weight: 600;
  transition: top var(--d-pop) var(--ease-out);
}
.skip-link:focus {
  top: 16px;
}

/* ── 3. TYPE ───────────────────────────────────────────────── */
h1,
h2,
h3,
h4,
h5 {
  font-family: "DM Sans", "Inter", sans-serif;
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -0.032em;
  text-wrap: balance;
}
.display {
  font-size: clamp(2.5rem, 6.4vw, 4.5rem);
  line-height: 1.02;
  letter-spacing: -0.038em;
}
.h2 {
  font-size: clamp(1.9rem, 4.2vw, 3rem);
}
.h3 {
  font-size: clamp(1.35rem, 2.4vw, 1.75rem);
  letter-spacing: -0.026em;
}
.h4 {
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: -0.018em;
  line-height: 1.3;
}
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--teal-deep);
}
.eyebrow::before {
  content: "";
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  opacity: 0.65;
}
.on-dark .eyebrow,
.eyebrow.light {
  color: var(--teal-light);
}
.lede {
  font-size: clamp(1.02rem, 1.5vw, 1.2rem);
  line-height: 1.58;
  color: var(--text-2);
  max-width: 56ch;
}
.on-dark .lede {
  color: var(--on-dark-2);
}
.muted {
  color: var(--text-3);
}
.tnum {
  font-variant-numeric: tabular-nums;
}
.grad {
  background: linear-gradient(96deg, var(--teal) 0%, var(--teal-light) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ── 4. BUTTONS ────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 48px;
  padding: 0 24px;
  border-radius: var(--r-pill);
  font-family: "DM Sans", sans-serif;
  font-size: 0.98rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap;
  transition:
    transform var(--d-press) var(--ease-out),
    background-color var(--d-hover) ease,
    border-color var(--d-hover) ease,
    color var(--d-hover) ease,
    box-shadow var(--d-hover) ease;
}
.btn:active {
  transform: scale(0.97);
}
.btn svg {
  width: 18px;
  height: 18px;
  flex: none;
}

.btn-primary {
  background: var(--teal);
  color: #04231f;
  box-shadow: 0 2px 8px rgba(0, 179, 164, 0.28);
}
.btn-dark {
  background: var(--ink);
  color: #fff;
  box-shadow: var(--e1);
}
.btn-ghost {
  border: 1.5px solid var(--border-strong);
  color: var(--text);
  background: var(--white);
}
.on-dark .btn-ghost {
  border-color: var(--on-dark-line);
  color: #fff;
  background: rgba(255, 255, 255, 0.06);
}
.btn-lg {
  min-height: 56px;
  padding: 0 30px;
  font-size: 1.05rem;
}
.btn-sm {
  min-height: 40px;
  padding: 0 16px;
  font-size: 0.88rem;
}
.btn-block {
  width: 100%;
}

@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover {
    background: var(--teal-light);
    box-shadow: 0 4px 18px rgba(0, 179, 164, 0.36);
  }
  .btn-dark:hover {
    background: var(--ink-3);
  }
  .btn-ghost:hover {
    border-color: var(--teal);
    color: var(--teal-deep);
  }
  .on-dark .btn-ghost:hover {
    background: rgba(255, 255, 255, 0.13);
    border-color: rgba(255, 255, 255, 0.3);
    color: #fff;
  }
}

/* Arrow that nudges — the only hover flourish on CTAs */
.btn .arw {
  transition: transform var(--d-hover) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .btn:hover .arw {
    transform: translateX(3px);
  }
}

.link-arw {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 650;
  color: var(--teal-deep);
  border-bottom: 1.5px solid transparent;
  transition:
    border-color var(--d-hover) ease,
    gap var(--d-hover) var(--ease-out);
}
/* The link is 27px tall, which is a fine line of text and a poor thumb
   target. This extends the hit area to 47px without moving the underline a
   pixel — padding would have pushed the border away from the words. */
.link-arw::after {
  content: "";
  position: absolute;
  inset: -10px -6px;
}
@media (hover: hover) and (pointer: fine) {
  .link-arw:hover {
    border-color: currentColor;
    gap: 10px;
  }
}
.on-dark .link-arw {
  color: var(--teal-light);
}

/* ── 5. LAYOUT ─────────────────────────────────────────────── */
.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap-narrow {
  max-width: var(--max-narrow);
}
section {
  position: relative;
}
.pad {
  padding-block: clamp(64px, 9vw, 116px);
}
.pad-sm {
  padding-block: clamp(48px, 6vw, 76px);
}
.on-dark {
  background: var(--ink);
  color: var(--on-dark);
}
.on-wash {
  background: var(--surface-2);
}
.sec-head {
  max-width: 640px;
  margin-bottom: clamp(36px, 5vw, 56px);
}
.sec-head.center {
  margin-inline: auto;
  text-align: center;
}
.sec-head.center .lede {
  margin-inline: auto;
}
.sec-head .h2 {
  margin-top: 14px;
}
.sec-head .lede {
  margin-top: 16px;
}
.hr {
  height: 1px;
  background: var(--border);
  border: 0;
}
.on-dark .hr {
  background: var(--on-dark-line);
}

/* ── 6. NAV ────────────────────────────────────────────────── */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-nav);
  height: var(--nav-h);
  display: flex;
  align-items: center;
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid transparent;
  transition:
    border-color var(--d-panel) ease,
    background-color var(--d-panel) ease,
    box-shadow var(--d-panel) ease;
}
.nav[data-stuck="true"] {
  border-bottom-color: var(--border);
  box-shadow: 0 1px 12px rgba(10, 24, 38, 0.05);
}
.nav-inner {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  align-items: center;
  gap: 10px;
}
.nav-logo {
  display: flex;
  align-items: center;
  min-height: 44px;
  line-height: 0;
}
.nav-logo img {
  height: 34px;
  width: auto;
}
.nav-logo .on-light {
  display: block;
}
.nav-logo .on-ink {
  display: none;
}

/* Pages whose hero is dark: the bar disappears until you scroll.
   Everything inside flips to the light-on-dark set at the same moment. */
.nav-over-dark:not([data-stuck="true"]) {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.nav-over-dark:not([data-stuck="true"]) .nav-logo .on-light {
  display: none;
}
.nav-over-dark:not([data-stuck="true"]) .nav-logo .on-ink {
  display: block;
}
.nav-over-dark:not([data-stuck="true"]) .nav-link,
.nav-over-dark:not([data-stuck="true"]) .nav-burger {
  color: var(--on-dark-2);
}
@media (hover: hover) and (pointer: fine) {
  .nav-over-dark:not([data-stuck="true"]) .nav-link:hover {
    color: #fff;
    background: rgba(255, 255, 255, 0.08);
  }
}
.nav-over-dark:not([data-stuck="true"]) .nav-link[aria-current="page"],
.nav-over-dark:not([data-stuck="true"]) .nav-link[aria-expanded="true"] {
  color: #fff;
}
.nav-over-dark:not([data-stuck="true"]) .btn-ghost {
  border-color: rgba(255, 255, 255, 0.2);
  color: #fff;
  background: rgba(255, 255, 255, 0.07);
}
@media (hover: hover) and (pointer: fine) {
  .nav-over-dark:not([data-stuck="true"]) .btn-ghost:hover {
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.32);
    color: #fff;
  }
}
.nav-links {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-left: 22px;
}
.nav-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 40px;
  padding: 0 13px;
  border-radius: var(--r-sm);
  font-size: 0.93rem;
  font-weight: 600;
  color: var(--text-2);
  transition:
    color var(--d-hover) ease,
    background-color var(--d-hover) ease;
}
.nav-link svg {
  width: 15px;
  height: 15px;
  transition: transform var(--d-pop) var(--ease-out);
}
.nav-link[aria-expanded="true"] svg {
  transform: rotate(180deg);
}
@media (hover: hover) and (pointer: fine) {
  .nav-link:hover {
    color: var(--text);
    background: var(--surface-3);
  }
}
.nav-link[aria-current="page"] {
  color: var(--text);
}
.nav-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Mega menu */
.nav-pop {
  position: absolute;
  top: calc(var(--nav-h) - 6px);
  left: 50%;
  z-index: var(--z-menu);
  width: min(720px, calc(100vw - 32px));
  padding: 14px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--e4);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  transform-origin: top center;
  transition:
    opacity var(--d-pop) var(--ease-out),
    transform var(--d-pop) var(--ease-out),
    visibility var(--d-pop);
}
.nav-pop[data-open="false"] {
  opacity: 0;
  visibility: hidden;
  transform: translateX(-50%) translateY(-6px) scale(0.97);
  pointer-events: none;
}
.nav-pop[data-open="true"] {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0) scale(1);
}
.nav-pop-item {
  display: flex;
  gap: 12px;
  padding: 11px 12px;
  border-radius: var(--r-md);
  transition: background-color var(--d-hover) ease;
}
@media (hover: hover) and (pointer: fine) {
  .nav-pop-item:hover {
    background: var(--surface-2);
  }
}
.nav-pop-item .ic {
  flex: none;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: var(--teal-wash);
  color: var(--teal-deep);
}
.nav-pop-item .ic svg {
  width: 18px;
  height: 18px;
}
.nav-pop-item.amber .ic {
  background: var(--amber-wash);
  color: var(--amber-deep);
}
.nav-pop-item strong {
  display: block;
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: -0.012em;
}
.nav-pop-item small {
  display: block;
  font-size: 0.79rem;
  line-height: 1.4;
  color: var(--text-3);
  margin-top: 1px;
}
.nav-pop-head {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  padding: 2px 12px 8px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
}

/* Mobile nav */
.nav-burger {
  display: none;
  width: 44px;
  height: 44px;
  place-items: center;
  border-radius: var(--r-sm);
  color: var(--text);
}
.nav-burger span {
  display: block;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform var(--d-pop) var(--ease-out), opacity 120ms ease;
}
.nav-burger span + span {
  margin-top: 5px;
}
.nav-burger[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.nav-burger[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}
.nav-burger[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}
.nav-sheet {
  position: fixed;
  inset: var(--nav-h) 0 0 0;
  z-index: var(--z-overlay);
  background: var(--white);
  padding: 20px var(--gutter) 40px;
  overflow-y: auto;
  overscroll-behavior: contain;
  transition:
    opacity var(--d-panel) var(--ease-out),
    transform var(--d-panel) var(--ease-drawer),
    visibility var(--d-panel);
}
.nav-sheet[data-open="false"] {
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  pointer-events: none;
}
.nav-sheet[data-open="true"] {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
/* Scoped to the link list, never to every anchor in the sheet. It used to be
   `.nav-sheet a`, which also claimed the two CTAs and the audience switcher:
   `display: block` beat `.btn`'s `inline-flex`, so the label lost its
   centring and sat against the top-left corner of a 56px-tall pill. */
.sheet-links a {
  display: block;
  padding: 14px 4px;
  font-family: "DM Sans", sans-serif;
  font-size: 1.1rem;
  font-weight: 650;
  border-bottom: 1px solid var(--border);
}
.nav-sheet .sheet-label {
  padding: 22px 4px 6px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
}
.nav-sheet .sheet-switch {
  margin-top: 22px;
}
.nav-sheet .sheet-cta {
  display: grid;
  gap: 10px;
  margin-top: 22px;
}

/* ── 7. COMPONENTS ─────────────────────────────────────────── */

/* Pill / badge */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 14px;
  border-radius: var(--r-pill);
  font-size: 0.8rem;
  font-weight: 650;
  letter-spacing: -0.005em;
  background: var(--teal-wash);
  color: var(--teal-deep);
  border: 1px solid var(--teal-line);
}
.on-dark .pill {
  background: rgba(47, 224, 206, 0.1);
  color: var(--teal-light);
  border-color: rgba(47, 224, 206, 0.24);
}
.pill .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 0 currentColor;
  animation: ping 2.4s var(--ease-out) infinite;
}
@keyframes ping {
  0% {
    box-shadow: 0 0 0 0 rgba(0, 179, 164, 0.5);
  }
  70%,
  100% {
    box-shadow: 0 0 0 7px rgba(0, 179, 164, 0);
  }
}

/* Card */
.card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 24px;
  box-shadow: var(--e1);
}
.on-dark .card {
  background: var(--ink-2);
  border-color: var(--on-dark-line);
  box-shadow: none;
}

/* Segmented control — the industry / plan switcher */
.seg {
  display: flex;
  gap: 6px;
  padding: 5px;
  background: var(--surface-3);
  border-radius: var(--r-pill);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.seg::-webkit-scrollbar {
  display: none;
}
.on-dark .seg {
  background: rgba(255, 255, 255, 0.07);
}
.seg-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding: 0 17px;
  border-radius: var(--r-pill);
  font-size: 0.9rem;
  font-weight: 650;
  white-space: nowrap;
  color: var(--text-2);
  transition:
    color var(--d-hover) ease,
    transform var(--d-press) var(--ease-out);
}
.seg-btn svg {
  width: 17px;
  height: 17px;
  flex: none;
}
.seg-btn:active {
  transform: scale(0.97);
}
.on-dark .seg-btn {
  color: var(--on-dark-2);
}
.seg-btn[aria-selected="true"] {
  color: var(--text);
  background: var(--white);
  box-shadow: var(--e1);
}
.on-dark .seg-btn[aria-selected="true"] {
  background: var(--teal);
  color: #04231f;
  box-shadow: none;
}
@media (hover: hover) and (pointer: fine) {
  .seg-btn:hover {
    color: var(--text);
  }
  .on-dark .seg-btn:hover {
    color: #fff;
  }
  .on-dark .seg-btn[aria-selected="true"]:hover {
    color: #04231f;
  }
}
/* Two-option switches carry sentence-length labels, which overflow the
   scrollable pill on a phone and leave the second option half-cut with no
   hint that it scrolls. Below 600px they become a full-width pair instead —
   both options visible, nothing to discover. */
@media (max-width: 600px) {
  .seg-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    width: 100%;
    overflow: visible;
  }
  .seg-2 .seg-btn {
    justify-content: center;
    padding: 9px 10px;
    font-size: 0.85rem;
    line-height: 1.25;
    text-align: center;
    white-space: normal;
  }
  .seg-2 .seg-btn svg {
    display: none;
  }
}

/* Accordion */
.acc-item {
  border-bottom: 1px solid var(--border);
}
.acc-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 22px 4px;
  text-align: left;
  font-family: "DM Sans", sans-serif;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.018em;
  color: var(--text);
  transition: color var(--d-hover) ease;
}
@media (hover: hover) and (pointer: fine) {
  .acc-btn:hover {
    color: var(--teal-deep);
  }
}
.acc-ic {
  flex: none;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--surface-3);
  transition:
    transform var(--d-panel) var(--ease-out),
    background-color var(--d-hover) ease;
}
.acc-ic svg {
  width: 14px;
  height: 14px;
}
.acc-btn[aria-expanded="true"] .acc-ic {
  transform: rotate(45deg);
  background: var(--teal);
  /* white on teal is only 2.6:1 — the dark glyph gets 6.3:1 */
  color: #04231f;
}
.acc-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--d-panel) var(--ease-out);
}
.acc-panel[data-open="true"] {
  grid-template-rows: 1fr;
}
.acc-panel > div {
  overflow: hidden;
}
.acc-panel p {
  padding: 0 4px 22px;
  color: var(--text-2);
  max-width: 62ch;
}

/* Stat */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  /* Row gap has to clear the label of the tile above once the row wraps to
     two lines on a phone — 8px reads as one run-on block. */
  gap: 32px 24px;
}
.stat .n {
  font-family: "DM Sans", sans-serif;
  font-size: clamp(2rem, 4vw, 2.9rem);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.stat .l {
  margin-top: 8px;
  font-size: 0.86rem;
  color: var(--text-3);
}
.on-dark .stat .l {
  color: var(--on-dark-3);
}

/* Range slider */
.range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 34px;
  background: transparent;
  cursor: pointer;
}
.range::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(
    to right,
    var(--teal) 0%,
    var(--teal) var(--pct, 30%),
    var(--surface-3) var(--pct, 30%),
    var(--surface-3) 100%
  );
}
.range::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: var(--surface-3);
}
.range::-moz-range-progress {
  height: 6px;
  border-radius: 3px;
  background: var(--teal);
}
.range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 26px;
  height: 26px;
  margin-top: -10px;
  border-radius: 50%;
  background: var(--white);
  border: 2.5px solid var(--teal);
  box-shadow: var(--e2);
  transition: transform var(--d-press) var(--ease-out);
}
.range::-moz-range-thumb {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--white);
  border: 2.5px solid var(--teal);
  box-shadow: var(--e2);
}
.range:active::-webkit-slider-thumb {
  transform: scale(1.12);
}
/* Fingers need more than the 34px the track needs. */
@media (pointer: coarse) {
  .range {
    height: 46px;
  }
  .range::-webkit-slider-thumb {
    margin-top: -16px;
  }
}

/* Store buttons */
.store-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.store-btn {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  min-height: 52px;
  padding: 0 20px 0 17px;
  border-radius: 13px;
  background: var(--ink);
  color: #fff;
  border: 1px solid var(--ink);
  transition:
    transform var(--d-press) var(--ease-out),
    background-color var(--d-hover) ease;
}
.store-btn:active {
  transform: scale(0.97);
}
@media (hover: hover) and (pointer: fine) {
  .store-btn:hover {
    background: var(--ink-3);
  }
}
.store-btn svg {
  width: 23px;
  height: 23px;
  flex: none;
}
.store-btn .t {
  line-height: 1.15;
}
/* Was 10.1px at 66% opacity, which is below every legibility floor going and
   the smallest type on the site by a clear margin. The badge still reads as a
   store badge two steps up. */
.store-btn .t small {
  display: block;
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  opacity: 0.8;
}
.store-btn .t strong {
  display: block;
  font-family: "DM Sans", sans-serif;
  font-size: 0.98rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.on-dark .store-btn {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--on-dark-line);
}
@media (hover: hover) and (pointer: fine) {
  .on-dark .store-btn:hover {
    background: rgba(255, 255, 255, 0.15);
  }
}
.store-btn.light {
  background: var(--white);
  color: var(--ink);
  border-color: var(--border-strong);
}
@media (hover: hover) and (pointer: fine) {
  .store-btn.light:hover {
    background: var(--surface-2);
  }
}

/* ── 8. DEVICE FRAMES ──────────────────────────────────────── */
/* Corner radius and bezel are percentages, not pixels.
   A 34px corner is right on a 268px phone and a caricature on an 80px one —
   the hero's secondary phone is that small now, and a fixed radius turned it
   into a lozenge. Percentages hold the same proportions at every size.
   The pair is `horizontal / vertical` because the frame is twice as tall as
   it is wide: a single percentage would give an oval corner. */
.phone {
  position: relative;
  width: 100%;
  max-width: 268px;
  aspect-ratio: 1206 / 2622;
  border-radius: 12.7% / 5.8%;
  padding: 2.6%;
  background: linear-gradient(160deg, #2b3f52 0%, #0d1c2b 42%, #24384a 100%);
  box-shadow: var(--e4);
}
.phone::after {
  /* screen glare — one soft diagonal, not a plastic sheen. `inset: 0` on an
     absolute child resolves against the padding box, so this lands exactly
     over the screen without restating the bezel. */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 10.4% / 4.8%;
  background: linear-gradient(
    148deg,
    rgba(255, 255, 255, 0.14) 0%,
    rgba(255, 255, 255, 0) 42%
  );
  pointer-events: none;
}
.phone img,
.phone .screen {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  border-radius: 10.4% / 4.8%;
  background: var(--surface-2);
}
.phone-sm {
  max-width: 208px;
}

/* Browser frame */
.browser {
  /* Without an explicit width the frame shrink-to-fits around a 1475px
     screenshot and overflows whatever column it was put in. It fills its
     slot instead, and the image scales to match. */
  width: 100%;
  max-width: 100%;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--white);
  border: 1px solid var(--border);
  box-shadow: var(--e4);
}
.browser-bar {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 11px 14px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}
.browser-bar i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--border-strong);
}
.browser-bar .url {
  margin-left: 10px;
  flex: 1;
  height: 24px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 12px;
  border-radius: var(--r-pill);
  background: var(--white);
  border: 1px solid var(--border);
  font-size: 0.72rem;
  color: var(--text-3);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  white-space: nowrap;
  /* Narrow frames — the hero's secondary one is ~300px — used to slice the
     address off mid-word against a hard edge, which reads as a broken
     screenshot rather than a small one. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.browser-bar .url svg {
  width: 11px;
  height: 11px;
  flex: none;
  color: var(--teal-deep);
}
/* The dashboard captures are all ~1475x770. Pinning the ratio here means the
   frame reserves its height before the image decodes — no layout shift. */
.browser img,
.browser .screen {
  width: 100%;
  aspect-ratio: 1475 / 770;
  object-fit: cover;
  object-position: top center;
  background: var(--surface-2);
}
.browser.tall img {
  aspect-ratio: 1363 / 810;
}
.on-dark .browser {
  border-color: var(--on-dark-line);
}
.on-dark .browser-bar {
  background: var(--ink-3);
  border-bottom-color: var(--on-dark-line);
}
.on-dark .browser-bar i {
  background: rgba(255, 255, 255, 0.24);
}
.on-dark .browser-bar .url {
  background: var(--ink-2);
  border-color: var(--on-dark-line);
  color: var(--on-dark-3);
}

/* Browser + phone together — the product is a web app you can also carry.
   The phone overlaps the lower-right corner rather than sitting beside it, so
   the pair reads as one object at any width. */
.shot-duo {
  position: relative;
  /* The gutter has to be *almost* as wide as the phone. Any narrower and the
     phone buries the browser's right edge, which reads as a cropped
     screenshot rather than two things layered. ~30px of overlap is enough to
     say "in front of" and little enough to keep the frame legible. */
  padding-right: clamp(52px, 8.6vw, 128px);
  padding-bottom: clamp(0px, 3vw, 40px);
}
.shot-duo .phone,
.shot-duo .phone-sm {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 2;
  max-width: clamp(84px, 10.8vw, 158px);
}
/* Below 720px the overlay covers too much of the dashboard to be worth it. */
@media (max-width: 720px) {
  .shot-duo {
    padding: 0;
  }
  .shot-duo .phone,
  .shot-duo .phone-sm {
    display: none;
  }
}

/* ── 9. MOTION ─────────────────────────────────────────────── */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity var(--d-reveal) var(--ease-out),
    transform var(--d-reveal) var(--ease-out);
}
.reveal.in {
  opacity: 1;
  transform: none;
}
.reveal[data-delay="1"] {
  transition-delay: 60ms;
}
.reveal[data-delay="2"] {
  transition-delay: 120ms;
}
.reveal[data-delay="3"] {
  transition-delay: 180ms;
}
.reveal[data-delay="4"] {
  transition-delay: 240ms;
}
.reveal[data-delay="5"] {
  transition-delay: 300ms;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal {
    opacity: 1;
    transform: none;
  }
}

/* ── 9b. INNER-PAGE COMPONENTS ─────────────────────────────── */

/* Breadcrumb — sits inside the dark page hero */
.crumbs {
  display: flex;
  gap: 9px;
  align-items: center;
  margin-bottom: 22px;
  font-size: 0.82rem;
  color: var(--on-dark-3);
}
.page-hero.center .crumbs {
  justify-content: center;
}
.crumbs span[aria-hidden] {
  opacity: 0.45;
}
.crumbs a {
  color: var(--on-dark-2);
  border-bottom: 1px solid transparent;
  transition: border-color var(--d-hover) ease, color var(--d-hover) ease;
}
@media (hover: hover) and (pointer: fine) {
  .crumbs a:hover {
    color: #fff;
    border-color: currentColor;
  }
}

/* Page hero (inner pages) */
.page-hero {
  position: relative;
  overflow: hidden;
  background: var(--ink);
  color: var(--on-dark);
  padding-top: calc(var(--nav-h) + clamp(48px, 6vw, 82px));
  padding-bottom: clamp(48px, 6vw, 82px);
}
.page-hero::before {
  content: "";
  position: absolute;
  top: -40%;
  left: 50%;
  width: min(900px, 120vw);
  aspect-ratio: 1;
  transform: translateX(-50%);
  background: radial-gradient(circle, rgba(0, 179, 164, 0.17), transparent 62%);
  pointer-events: none;
}
.page-hero .wrap {
  position: relative;
  z-index: 1;
}
.page-hero h1 {
  font-size: clamp(2.3rem, 5.4vw, 3.9rem);
  letter-spacing: -0.04em;
  margin-top: 18px;
  max-width: 18ch;
}
.page-hero .lede {
  margin-top: 18px;
  color: var(--on-dark-2);
}
.page-hero.center {
  text-align: center;
}
.page-hero.center h1,
.page-hero.center .lede {
  margin-inline: auto;
}

/* CTA row */
.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 30px;
}
.final .cta-row {
  justify-content: center;
  margin-top: 34px;
}
.final-note {
  margin-top: 18px;
  font-size: 0.86rem;
  color: var(--on-dark-3);
}

/* Alternating feature rows — the image does the talking */
.frow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}
.frow + .frow {
  margin-top: clamp(48px, 5.5vw, 76px);
}
.frow.flip .frow-media {
  order: -1;
}
/* For rows whose copy runs long: centring leaves the image marooned in the
   middle of a column of text, so it starts at the top instead — and gets a
   wider column, because on this row the photograph carries the product. */
.frow.top {
  align-items: start;
}
/* Both of these only hold while the row is genuinely two columns, and both
   are written as min-width for the same reason: the collapse rule further
   down targets `.frow`, so anything set here on `.frow.top` outranks it and
   would survive into the one-column layout. The wider media column would
   strangle the copy to a 140px ribbon, and the sticky would pin the photo
   over the text — .frow-media moves *above* the copy when it collapses. */
@media (min-width: 981px) {
  .frow.top {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  }
  .frow.top .frow-media {
    position: sticky;
    top: calc(var(--nav-h) + 28px);
  }
}
.frow-media {
  display: flex;
  justify-content: center;
}
/* Screenshots on inner pages sit smaller than the hero's — the copy leads here. */
.frow-media .phone {
  max-width: 228px;
}
/* A person holding the app rather than a bare device frame. The photograph
   is shot on a warm studio backdrop, so it needs a container of its own or
   it reads as a hole in the page.

   It takes whatever width the column gives it — the screen in her hand is
   about a sixth of the frame, so every pixel the container gives up comes
   off the one thing this image exists to show. Capped at 560px, which is
   where its own resolution runs out. */
.held-out {
  overflow: hidden;
  width: 100%;
  max-width: 560px;
  margin-inline: auto;
  border-radius: var(--r-xl);
  background: var(--surface-2);
  border: 1px solid var(--border);
  box-shadow: var(--e2);
}
.held-out img {
  width: 100%;
  filter: saturate(1.03) contrast(1.02);
}
.frow h2 {
  font-size: clamp(1.7rem, 3.2vw, 2.4rem);
  margin-top: 14px;
}
.frow p {
  margin-top: 14px;
  color: var(--text-2);
  max-width: 46ch;
}
.on-dark .frow p {
  color: var(--on-dark-2);
}
.flist {
  display: grid;
  gap: 12px;
  margin-top: 22px;
}
.flist li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  font-size: 0.96rem;
  color: var(--text-2);
}
.on-dark .flist li {
  color: var(--on-dark-2);
}
.flist .tick {
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 2px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--teal-wash);
  color: var(--teal-deep);
}
.on-dark .flist .tick {
  background: rgba(47, 224, 206, 0.12);
  color: var(--teal-light);
}
.flist .tick svg {
  width: 13px;
  height: 13px;
}

/* Icon card grid */
.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
}
.icard .ic {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: var(--teal-wash);
  color: var(--teal-deep);
  margin-bottom: 16px;
}
.icard.amber .ic {
  background: var(--amber-wash);
  color: var(--amber-deep);
}
.on-dark .icard .ic {
  background: rgba(47, 224, 206, 0.12);
  color: var(--teal-light);
}
.icard .ic svg {
  width: 21px;
  height: 21px;
}
.icard h3 {
  font-size: 1.06rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}
.icard p {
  margin-top: 8px;
  font-size: 0.93rem;
  color: var(--text-3);
}
.on-dark .icard p {
  color: var(--on-dark-2);
}

/* Industry explorer (solutions page) */
.ind-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.ind-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 20px 18px;
  border-radius: var(--r-md);
  background: var(--white);
  border: 1px solid var(--border);
  text-align: left;
  scroll-margin-top: calc(var(--nav-h) + 24px);
  transition:
    transform var(--d-hover) var(--ease-out),
    box-shadow var(--d-hover) ease,
    border-color var(--d-hover) ease;
}
.ind-card:active {
  transform: scale(0.985);
}
@media (hover: hover) and (pointer: fine) {
  .ind-card:hover {
    border-color: var(--teal);
    box-shadow: var(--e2);
  }
}
.ind-card .ic {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 11px;
  background: var(--teal-wash);
  color: var(--teal-deep);
}
.ind-card.amber .ic {
  background: var(--amber-wash);
  color: var(--amber-deep);
}
.ind-card .ic svg {
  width: 19px;
  height: 19px;
}
.ind-card strong {
  font-family: "DM Sans", sans-serif;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}
.ind-card span {
  font-size: 0.88rem;
  color: var(--text-3);
  line-height: 1.5;
}

/* Pricing table */
.ptable-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--white);
}
.ptable {
  width: 100%;
  min-width: 760px;
  border-collapse: collapse;
  font-size: 0.92rem;
}
.ptable th,
.ptable td {
  padding: 14px 18px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.ptable thead th {
  position: sticky;
  top: 0;
  background: var(--surface-2);
  font-family: "DM Sans", sans-serif;
  font-weight: 700;
  font-size: 0.9rem;
  white-space: nowrap;
  z-index: 1;
}
.ptable tbody th {
  font-weight: 600;
  color: var(--text-2);
}
.ptable td {
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.ptable tr:last-child th,
.ptable tr:last-child td {
  border-bottom: 0;
}
.ptable .yes {
  color: var(--teal-deep);
  font-weight: 700;
}
.ptable .no {
  color: var(--text-3);
}
.ptable col.hi,
.ptable .hi {
  background: var(--teal-wash);
}

/* Pricing cards */
.plans {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  align-items: stretch;
}
.plan {
  display: flex;
  flex-direction: column;
  padding: 28px 26px;
  border-radius: var(--r-lg);
  background: var(--white);
  border: 1px solid var(--border);
  box-shadow: var(--e1);
}
.plan.pop {
  position: relative;
  border-color: var(--teal);
  box-shadow: var(--e3);
}
.plan.pop::before {
  content: "Most popular";
  position: absolute;
  top: -11px;
  left: 26px;
  padding: 4px 12px;
  border-radius: var(--r-pill);
  background: var(--teal);
  color: #04231f;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.plan .pname {
  font-family: "DM Sans", sans-serif;
  font-weight: 700;
  font-size: 1.02rem;
}
.plan .pprice {
  margin-top: 12px;
  font-family: "DM Sans", sans-serif;
  font-size: 2.2rem;
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1;
}
.plan .pper {
  font-size: 0.85rem;
  color: var(--text-3);
  margin-top: 6px;
  min-height: 2.4em;
}
.plan ul {
  margin: 20px 0 26px;
  display: grid;
  gap: 10px;
  flex: 1;
}
/* Audience switch — both bullet lists share one grid cell, so the card is
   already as tall as the taller list and swapping is a pure crossfade with
   no reflow. Exit is quicker than enter; the incoming list carries the eye. */
.plan-points {
  display: grid;
  flex: 1;
}
.plan-points > ul {
  grid-area: 1 / 1;
  align-content: start;
  transition:
    opacity 160ms var(--ease-out),
    transform 160ms var(--ease-out);
}
.plan-points > ul[data-active="false"] {
  opacity: 0;
  transform: translateY(4px);
  pointer-events: none;
  transition-duration: 110ms;
}
@media (prefers-reduced-motion: reduce) {
  .plan-points > ul {
    transition-property: opacity;
  }
  .plan-points > ul[data-active="false"] {
    transform: none;
  }
}
.plan li {
  display: flex;
  gap: 10px;
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--text-2);
}
.plan li svg {
  width: 16px;
  height: 16px;
  flex: none;
  margin-top: 3px;
  color: var(--teal-deep);
}
@media (max-width: 1080px) {
  .plans {
    grid-template-columns: repeat(2, 1fr) !important;
  }
}
@media (max-width: 640px) {
  .plans {
    grid-template-columns: 1fr !important;
  }
  .plan.pop {
    margin-top: 12px;
  }
}

/* Form */
.form-card {
  display: grid;
  gap: 20px;
  padding: clamp(24px, 3vw, 34px);
  border-radius: var(--r-xl);
  background: var(--white);
  border: 1px solid var(--border);
  box-shadow: var(--e2);
}
.field label {
  display: block;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: 7px;
}
.field .req {
  color: var(--red);
}
.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  border-radius: var(--r-sm);
  border: 1.5px solid var(--border-strong);
  background: var(--white);
  font-size: 16px; /* below 16px iOS zooms the page on focus */
  transition:
    border-color var(--d-hover) ease,
    box-shadow var(--d-hover) ease;
}
.field textarea {
  min-height: 130px;
  resize: vertical;
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--teal);
  box-shadow: 0 0 0 3px rgba(0, 179, 164, 0.16);
}
.field .help {
  margin-top: 7px;
  font-size: 0.82rem;
  color: var(--text-3);
}

/* Blog listing */
.post-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
.post {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 28px 26px;
  border-radius: var(--r-lg);
  background: var(--white);
  border: 1px solid var(--border);
  box-shadow: var(--e1);
  transition:
    transform var(--d-hover) var(--ease-out),
    box-shadow var(--d-hover) ease,
    border-color var(--d-hover) ease;
}
.post:active {
  transform: scale(0.99);
}
@media (hover: hover) and (pointer: fine) {
  .post:hover {
    border-color: var(--teal);
    box-shadow: var(--e3);
  }
  .post:hover .arw {
    transform: translateX(3px);
  }
}
.post-ic {
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 13px;
  background: var(--teal-wash);
  color: var(--teal-deep);
  margin-bottom: 6px;
}
.post-ic svg {
  width: 22px;
  height: 22px;
}
.post-tag {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
}
.post-title {
  font-family: "DM Sans", sans-serif;
  font-size: 1.18rem;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.22;
}
.post-blurb {
  font-size: 0.93rem;
  color: var(--text-3);
  flex: 1;
}
.post-read {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 6px;
  font-weight: 650;
  font-size: 0.92rem;
  color: var(--teal-deep);
}
.post-read .arw {
  transition: transform var(--d-hover) var(--ease-out);
}
@media (max-width: 900px) {
  .post-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Long-form prose (about, blog) */
.prose {
  max-width: 68ch;
}
.prose h3 {
  font-size: 1.12rem;
  margin-top: 30px;
}
.prose ol {
  margin-top: 16px;
  display: grid;
  gap: 12px;
  padding-left: 22px;
  list-style: decimal;
  color: var(--text-2);
}
.prose table {
  width: 100%;
  margin-top: 22px;
  border-collapse: collapse;
  font-size: 0.92rem;
}
.prose th,
.prose td {
  padding: 11px 14px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.prose th {
  background: var(--surface-2);
  font-weight: 700;
}
.prose h2 {
  font-size: clamp(1.4rem, 2.6vw, 1.85rem);
  margin-top: 44px;
}
.prose h2:first-child {
  margin-top: 0;
}
.prose p,
.prose ul {
  margin-top: 16px;
  color: var(--text-2);
}
.prose ul {
  display: grid;
  gap: 12px;
  padding-left: 22px;
  list-style: disc;
}
.prose li::marker {
  color: var(--teal);
}
.prose strong {
  color: var(--text);
}
.prose blockquote {
  margin-top: 32px;
  padding: 22px 26px;
  border-left: 3px solid var(--teal);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  background: var(--teal-wash);
  color: var(--text-2);
}
.prose a {
  color: var(--teal-deep);
  border-bottom: 1.5px solid transparent;
  transition: border-color var(--d-hover) ease;
}
@media (hover: hover) and (pointer: fine) {
  .prose a:hover {
    border-color: currentColor;
  }
}

/* Final CTA (inner pages) */
.final {
  text-align: center;
  background: var(--ink);
  color: #fff;
  position: relative;
  overflow: hidden;
}
.final::before {
  content: "";
  position: absolute;
  bottom: -55%;
  left: 50%;
  transform: translateX(-50%);
  width: min(900px, 120vw);
  aspect-ratio: 1;
  background: radial-gradient(circle, rgba(0, 179, 164, 0.24), transparent 62%);
  pointer-events: none;
}
.final .wrap {
  position: relative;
  z-index: 1;
}
.final h2 {
  font-size: clamp(2rem, 4.6vw, 3.2rem);
  letter-spacing: -0.038em;
}

@media (max-width: 980px) {
  .frow,
  .grid-3 {
    grid-template-columns: minmax(0, 1fr);
  }
  .frow-media,
  .frow.flip .frow-media {
    order: -1;
  }
  .ind-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 640px) {
  .grid-2,
  .ind-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── 10. FOOTER ────────────────────────────────────────────── */
.footer {
  background: var(--ink);
  color: var(--on-dark-2);
  padding-block: clamp(56px, 7vw, 88px) 32px;
  font-size: 0.92rem;
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.6fr repeat(4, 1fr);
  gap: 40px 28px;
}
.footer h2 {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
  margin-bottom: 14px;
}
.footer li + li {
  margin-top: 9px;
}
.footer a {
  color: var(--on-dark-2);
  transition: color var(--d-hover) ease;
}
@media (hover: hover) and (pointer: fine) {
  .footer a:hover {
    color: var(--teal-light);
  }
}
.footer-brand img {
  height: 38px;
  width: auto;
  margin-bottom: 16px;
}
.footer-brand p {
  max-width: 34ch;
  color: var(--on-dark-3);
  font-size: 0.9rem;
}
.footer-soc {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 18px;
}
.footer-soc a {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--on-dark-line);
  color: var(--on-dark-2);
  transition:
    background-color var(--d-hover) ease,
    border-color var(--d-hover) ease,
    color var(--d-hover) ease,
    transform var(--d-press) var(--ease-out);
}
.footer-soc a:active {
  transform: scale(0.94);
}
.footer-soc svg {
  width: 17px;
  height: 17px;
}
@media (hover: hover) and (pointer: fine) {
  .footer-soc a:hover {
    background: rgba(255, 255, 255, 0.09);
    border-color: rgba(255, 255, 255, 0.28);
    color: var(--on-dark);
  }
}
.footer-bot {
  margin-top: 52px;
  padding-top: 24px;
  border-top: 1px solid var(--on-dark-line);
  display: flex;
  flex-wrap: wrap;
  gap: 12px 24px;
  align-items: center;
  justify-content: space-between;
  font-size: 0.84rem;
  color: var(--on-dark-3);
}
.footer-bot nav {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
}

/* ── 11. RESPONSIVE ────────────────────────────────────────── */

/* A note on `minmax(0, 1fr)` throughout this file, including every rule that
   collapses a two-column grid to one:
   a plain `1fr` track is `minmax(auto, 1fr)`, and that `auto` minimum is the
   item's min-content — so any descendant that cannot wrap sets the floor for
   the whole column. One unbreakable string was enough: the address in the
   browser frame's chrome, `swiftrun.usenumus.com`, gave the industry panel a
   280px floor and pushed /logistics/ 18px past a 320px viewport. `minmax(0,
   1fr)` lets the track shrink and the frame clip its own chrome instead. */
@media (max-width: 1080px) {
  .footer-grid {
    grid-template-columns: 1fr 1fr 1fr;
  }
  .footer-brand {
    grid-column: 1 / -1;
  }
}
@media (max-width: 900px) {
  .nav-links,
  .nav-actions .btn-ghost {
    display: none;
  }
  /* The mega menu's trigger is inside .nav-links, so it is unreachable here —
     but `visibility: hidden` still leaves it laid out, and at 320px its
     720px-capped box was pushing the document 18px wider than the viewport
     and giving every page a horizontal scrollbar. */
  .nav-pop {
    display: none;
  }
  .nav-burger {
    display: grid;
  }
  .nav-actions {
    gap: 6px;
  }
}
@media (max-width: 640px) {
  :root {
    --gutter: 18px;
  }
  body {
    font-size: 16px;
  }
  .footer-grid {
    grid-template-columns: 1fr 1fr;
    gap: 32px 20px;
  }
  .footer-bot {
    flex-direction: column;
    align-items: flex-start;
  }
  .btn {
    width: 100%;
  }
  .btn.btn-auto,
  .nav .btn {
    width: auto;
  }
  /* Stacked store buttons look ragged at different widths — match them. */
  .store-btns {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
  }
  .store-btn {
    width: 100%;
  }
}

/* ── 12. HOME & SECTION LANDINGS ───────────────────────────────
   Hero, journey, bento, estimator and proof. These used to be an inline
   <style> block in a hand-written index.html. Now that /logistics/ and
   /business/ both stamp out a homepage from _build/home.py — and the chooser
   at / reuses the same pieces — they live here so all three share one
   cached stylesheet. */


/* ── HERO ─────────────────────────────────────────────── */
.hero {
  position: relative;
  overflow: hidden;
  padding-top: calc(var(--nav-h) + clamp(44px, 6vw, 80px));
  padding-bottom: clamp(56px, 8vw, 100px);
  background: var(--ink);
  color: var(--on-dark);
}
.hero::before {
  /* teal bloom behind the copy */
  content: "";
  position: absolute;
  top: -20%;
  left: 50%;
  width: min(1100px, 130vw);
  aspect-ratio: 1;
  transform: translateX(-60%);
  background: radial-gradient(
    circle,
    rgba(0, 179, 164, 0.2) 0%,
    rgba(0, 179, 164, 0.05) 38%,
    transparent 66%
  );
  pointer-events: none;
}
.hero::after {
  /* fine grid, barely there */
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
  background-size: 62px 62px;
  mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 20%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 20%, transparent 75%);
  pointer-events: none;
}
.hero .wrap {
  position: relative;
  z-index: 1;
}
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  gap: clamp(32px, 5vw, 64px);
  align-items: center;
}
.hero h1 {
  font-size: clamp(2.7rem, 6.4vw, 4.5rem);
  line-height: 1;
  letter-spacing: -0.042em;
  margin: 20px 0 0;
}
.hero-sub {
  margin-top: 22px;
  font-size: clamp(1.05rem, 1.6vw, 1.24rem);
  line-height: 1.55;
  color: var(--on-dark-2);
  max-width: 32ch;
}
.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 32px;
}
.hero-note {
  margin-top: 16px;
  font-size: 0.86rem;
  color: var(--on-dark-3);
}
.hero-trust {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  margin-top: 34px;
  padding-top: 26px;
  border-top: 1px solid var(--on-dark-line);
}
.hero-trust li {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.88rem;
  color: var(--on-dark-2);
}
.hero-trust svg {
  width: 16px;
  height: 16px;
  color: var(--teal-light);
  flex: none;
}

/* Hero visual: the customer, what she is saying, and the product behind her.
   Three items on a two-by-two grid that deliberately overlap:

     ┌──────────────┬──────────┐
     │              │ dashboard│   row 1  the product, secondary
     │   customer   │ + phone  │
     │   (4:5)      ├──────────┤
     │ ┌────────────┴───┐      │   row 2  what she says, over her and
     └─┴────────────────┴──────┘          out past the photo's edge

   The photograph spans both rows and is the largest object in the frame by
   some distance. That is the point of the change: a dashboard says what the
   software does, and a person says who it is for, and only one of those is
   the question a visitor is asking in the first two seconds. */
.hero-visual {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr);
  grid-template-rows: 1fr auto;
  column-gap: clamp(10px, 1.6vw, 22px);
}
.hero-phone-main {
  max-width: 258px;
  z-index: 2;
}
.hero-phone-back {
  position: absolute;
  left: 0;
  bottom: 40px;
  max-width: 190px;
  z-index: 1;
  transform: rotate(-6deg);
}
.proof-card {
  position: absolute;
  right: -8px;
  bottom: 74px;
  z-index: 3;
  width: 226px;
  padding: 14px 16px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.97);
  color: var(--text);
  box-shadow: var(--e4);
}
.proof-card .row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.proof-card .tick {
  width: 30px;
  height: 30px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--teal);
  color: #fff;
}
.proof-card .tick svg {
  width: 16px;
  height: 16px;
}
.proof-card strong {
  display: block;
  font-family: "DM Sans", sans-serif;
  font-size: 0.9rem;
  letter-spacing: -0.015em;
}
.proof-card small {
  display: block;
  font-size: 0.75rem;
  color: var(--text-3);
}
.proof-card .bar {
  margin-top: 12px;
  height: 5px;
  border-radius: 3px;
  background: var(--surface-3);
  overflow: hidden;
}
.proof-card .bar i {
  display: block;
  height: 100%;
  width: 100%;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--teal), var(--teal-light));
  transform-origin: left;
  animation: fill 3.4s var(--ease-out) infinite;
}
@keyframes fill {
  0% {
    transform: scaleX(0.08);
  }
  60%,
  100% {
    transform: scaleX(1);
  }
}

/* ── THE HERO SCENE ───────────────────────────────────────
   A customer standing in the bottom-left corner of the hero composition,
   with what she is saying — or what she has open — beside her. It replaces
   the floating "delivered" receipt that used to sit here, which said the same
   kind of thing with nobody attached to it.

   It is visible from the start rather than on hover: most of this traffic is
   on a phone, where a hover-only card is a card nobody ever sees. Hover on a
   pointer device lifts the card and the screen it refers to together, which
   is what ties the sentence to the product. */
.hero-human {
  grid-area: 1 / 1 / 3 / 2;
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 5;
  border-radius: var(--r-xl);
  background: var(--ink-2);
  box-shadow:
    var(--e4),
    inset 0 0 0 1px rgba(255, 255, 255, 0.09);
  transition: transform var(--d-panel) var(--ease-out);
}
/* The photographs are shot in daylight and the hero is ink. A scrim on the
   lower third settles the photo into the band and gives the card underneath
   something to sit against. */
.hero-human::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 46%;
  background: linear-gradient(to top, rgba(10, 24, 38, 0.62), transparent);
  pointer-events: none;
}
/* Already square and already composed for a circle — see PORTRAITS in
   _build/compose_phone.py. `cover` is belt and braces. */
.hero-human img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(1.04) contrast(1.02);
}

/* Sits in row 2, which the photograph also occupies, and runs out past its
   right-hand edge — so it belongs to her and to the page at the same time. */
.hero-say {
  grid-area: 2 / 1 / 3 / 3;
  position: relative;
  z-index: 3;
  align-self: end;
  justify-self: start;
  width: min(100%, 360px);
  margin: 0 0 clamp(16px, 2.2vw, 28px) clamp(14px, 2vw, 26px);
  padding: 15px 17px;
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, 0.98);
  color: var(--text);
  box-shadow: var(--e4);
  transition:
    transform var(--d-panel) var(--ease-out),
    box-shadow var(--d-panel) var(--ease-out);
}
/* The tail points up into the photograph rather than sideways at it, now
   that the card overlaps her. A rotated square rather than a border
   triangle, so it inherits the card's own background. */
.hero-say::before {
  content: "";
  position: absolute;
  left: 34px;
  top: -5px;
  width: 12px;
  height: 12px;
  border-radius: 2px;
  background: inherit;
  transform: rotate(45deg);
}
.say-q {
  font-size: 0.95rem;
  line-height: 1.45;
  letter-spacing: -0.005em;
  text-wrap: pretty;
}
.say-who {
  margin-top: 9px;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--text-3);
}

/* The order the shopkeeper has open, lifted off her tablet. `lit` is the
   projection: a teal bloom around the card so it reads as thrown from the
   screen beside it rather than pasted onto the photograph. A spread shadow
   rather than a pseudo-element, because the card carries a z-index of its
   own and a negative-z child would paint over its background, not under. */
.hero-say.lit {
  box-shadow:
    var(--e4),
    0 0 36px 6px rgba(0, 179, 164, 0.32);
}
.say-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--teal-deep);
}
.say-chip .dot {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: var(--teal);
  animation: ping 2.4s var(--ease-out) infinite;
}
.say-ref {
  margin-top: 8px;
  font-family: "DM Sans", sans-serif;
  font-size: 0.98rem;
  font-weight: 700;
  letter-spacing: -0.015em;
}
.say-meta {
  margin-top: 3px;
  font-size: 0.79rem;
  color: var(--text-3);
}
.say-bar {
  margin-top: 10px;
  height: 5px;
  border-radius: 3px;
  background: var(--surface-3);
  overflow: hidden;
}
.say-bar i {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--teal), var(--teal-light));
  transform-origin: left;
  animation: fill 3.4s var(--ease-out) infinite;
}

/* The product, now the supporting act — but a 220px dashboard is a smudge,
   not a smaller dashboard. So it reaches back over the photograph rather
   than sharing the width with it: the negative margin buys the frame about
   60px it would not otherwise have. In front, not behind — a dashboard
   half-hidden under a photo reads as a mistake, where one laid over the
   corner of it reads as a stack. */
.hero-visual .shot-duo {
  grid-area: 1 / 2 / 2 / 3;
  align-self: start;
  z-index: 2;
  margin-top: clamp(4px, 1.2vw, 20px);
  margin-left: clamp(-66px, -4.6vw, -28px);
  padding-right: clamp(34px, 3vw, 50px);
  padding-bottom: 0;
}
.hero-human {
  z-index: 1;
}
/* Small, but never so small it stops reading as a phone — the vw term alone
   put it at 39px on a tablet, which is a sliver hanging off a browser. */
.hero-visual .shot-duo .phone-sm {
  max-width: clamp(60px, 5.4vw, 82px);
  transition: transform var(--d-panel) var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  /* The sentence and the screen it is about move together, which is the whole
     point of putting them in the same frame. */
  .hero-visual:hover .hero-say {
    transform: translateY(-4px);
    box-shadow:
      var(--e4),
      0 0 0 1px rgba(0, 179, 164, 0.28);
  }
  .hero-visual:hover .hero-say.lit {
    box-shadow:
      var(--e4),
      0 0 44px 8px rgba(0, 179, 164, 0.4);
  }
  .hero-visual:hover .shot-duo .phone-sm {
    transform: translateY(-5px);
  }
}

@media (max-width: 980px) {
  /* The hero grid has collapsed to one column, so the visual has the full
     page width to itself — which would give the photograph a 600px tile.
     It keeps its proportions and stops growing instead. */
  .hero-visual {
    max-width: 700px;
    margin-inline: auto;
  }
}
@media (max-width: 720px) {
  /* One column: the customer and what she says first, the product under
     them. The two still overlap — she is the reason the card is there. */
  .hero-visual {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: 1fr auto auto;
    max-width: 520px;
  }
  /* Square rather than 4:5 — a portrait tile at full mobile width is taller
     than the fold. Square also keeps the card down to about a third of the
     photo instead of half of it. */
  .hero-human {
    grid-area: 1 / 1 / 3 / 2;
    aspect-ratio: 1;
  }
  .hero-say {
    grid-area: 2 / 1 / 3 / 2;
    width: min(100%, 330px);
  }
  .hero-visual .shot-duo {
    grid-area: 3 / 1 / 4 / 2;
    margin-top: 22px;
    margin-left: 0;
  }
}

/* Platform strip */
.strip {
  border-top: 1px solid var(--on-dark-line);
  background: var(--ink);
  color: var(--on-dark-3);
  padding-block: 22px;
}
.strip-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px 34px;
  font-size: 0.84rem;
}
.strip-inner span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.strip-inner svg {
  width: 16px;
  height: 16px;
  color: var(--on-dark-2);
  flex: none;
}

/* ── INDUSTRY SWITCHER ────────────────────────────────── */
.ind-panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.7fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: center;
  margin-top: 34px;
  padding: clamp(24px, 3.4vw, 40px);
  border-radius: var(--r-xl);
  background: var(--white);
  border: 1px solid var(--border);
  box-shadow: var(--e3);
}
.ind-panel h3 {
  font-size: clamp(1.5rem, 2.9vw, 2.05rem);
  letter-spacing: -0.03em;
  margin-top: 12px;
}
.ind-wins {
  display: grid;
  gap: 14px;
  margin-top: 24px;
}
.ind-wins li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  font-size: 0.98rem;
  color: var(--text-2);
}
.ind-wins .tick {
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 2px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--teal-wash);
  color: var(--teal-deep);
}
.ind-wins .tick svg {
  width: 13px;
  height: 13px;
}
.ind-shot {
  display: flex;
  justify-content: center;
}
/* Content swap: fade + micro-lift, never a jump */
.swap {
  animation: swapIn var(--d-panel) var(--ease-out) both;
}
@keyframes swapIn {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

/* ── JOURNEY (the interactive explainer) ──────────────── */
.journey {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.6fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}
.j-steps {
  display: grid;
  gap: 6px;
}
.j-step {
  position: relative;
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 16px;
  align-items: start;
  width: 100%;
  padding: 16px 18px 20px;
  text-align: left;
  border-radius: var(--r-md);
  border: 1px solid transparent;
  color: var(--on-dark-2);
  transition:
    background-color var(--d-panel) ease,
    border-color var(--d-panel) ease,
    transform var(--d-press) var(--ease-out);
}
.j-step:active {
  transform: scale(0.99);
}
.j-step[aria-selected="true"] {
  background: rgba(255, 255, 255, 0.05);
  border-color: var(--on-dark-line);
  color: #fff;
}
@media (hover: hover) and (pointer: fine) {
  .j-step:hover {
    background: rgba(255, 255, 255, 0.04);
  }
}
.j-num {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1.5px solid var(--on-dark-line);
  font-family: "DM Sans", sans-serif;
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--on-dark-3);
  transition:
    background-color var(--d-panel) ease,
    color var(--d-panel) ease,
    border-color var(--d-panel) ease;
}
.j-step[aria-selected="true"] .j-num {
  background: var(--teal);
  border-color: var(--teal);
  color: #04231f;
}
.j-step .j-title {
  display: block;
  font-family: "DM Sans", sans-serif;
  font-size: 1.12rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.25;
  color: #fff;
}
.j-step .j-desc {
  display: block;
  margin-top: 5px;
  font-size: 0.93rem;
  line-height: 1.5;
}
/* Hairline that fills while a step is active */
.j-prog {
  position: absolute;
  left: 18px;
  right: 18px;
  bottom: 9px;
  height: 2px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
  opacity: 0;
  transition: opacity var(--d-pop) ease;
}
.j-step[aria-selected="true"] .j-prog {
  opacity: 1;
}
.j-prog i {
  display: block;
  height: 100%;
  background: var(--teal-light);
  transform: scaleX(0);
  transform-origin: left;
}
.j-step[aria-selected="true"] .j-prog i {
  animation: jfill 5.5s linear forwards;
}
.journey[data-paused="true"] .j-prog {
  opacity: 0;
}
@keyframes jfill {
  to {
    transform: scaleX(1);
  }
}
@media (prefers-reduced-motion: reduce) {
  .j-prog {
    display: none;
  }
}
.j-visual {
  position: relative;
  display: flex;
  justify-content: center;
}
.j-visual .phone {
  max-width: 256px;
}
.j-chip {
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 15px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.97);
  color: var(--ink);
  font-size: 0.8rem;
  font-weight: 700;
  white-space: nowrap;
  box-shadow: var(--e3);
}
.j-chip .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--teal);
  flex: none;
}

/* ── BENTO GALLERY ────────────────────────────────────── */
.bento {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
.tile {
  position: relative;
  display: block;
  width: 100%;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--white);
  border: 1px solid var(--border);
  text-align: left;
  transition:
    transform var(--d-hover) var(--ease-out),
    box-shadow var(--d-hover) ease,
    border-color var(--d-hover) ease;
}
.tile:active {
  transform: scale(0.985);
}
@media (hover: hover) and (pointer: fine) {
  .tile:hover {
    box-shadow: var(--e3);
    border-color: var(--border-strong);
  }
  .tile:hover .tile-media img {
    transform: translateY(-8px) scale(1.015);
  }
  .tile:hover .tile-zoom {
    opacity: 1;
    transform: scale(1);
  }
}
.tile-media {
  position: relative;
  display: flex;
  justify-content: center;
  overflow: hidden;
  padding: 26px 26px 0;
  background:
    radial-gradient(ellipse 70% 60% at 50% 0%, rgba(0, 179, 164, 0.09), transparent 70%),
    var(--surface-2);
}
.tile-media img {
  width: 100%;
  max-width: 200px;
  border-radius: 16px 16px 0 0;
  box-shadow: var(--e3);
  transition: transform var(--d-panel) var(--ease-out);
}
/* This is a <span> inside a <button>. Without an explicit display it
   lays out inline, and an inline box ignores vertical padding — which
   is why the caption used to sit flush against the border. */
.tile-body {
  display: block;
  padding: 20px 22px 22px;
  border-top: 1px solid var(--border);
}
.tile-body .t {
  display: block;
  font-family: "DM Sans", sans-serif;
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
}
.tile-body .d {
  display: block;
  margin-top: 4px;
  font-size: 0.88rem;
  color: var(--text-3);
}
.tile-zoom {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.94);
  color: var(--ink);
  box-shadow: var(--e2);
  opacity: 0;
  transform: scale(0.9);
  transition:
    opacity var(--d-hover) ease,
    transform var(--d-hover) var(--ease-out);
}
.tile-zoom svg {
  width: 16px;
  height: 16px;
}

/* Lightbox */
.lb {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(6, 15, 25, 0.84);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  /* visibility is a *discrete* property: transitioning it over 260ms flips it
     at the halfway mark, which left the dialog unfocusable for the first
     130ms — so opening it with the keyboard dropped focus on the floor.
     Opening now reveals it instantly; only closing waits, so the fade-out
     still plays before the element is taken out of the tree. */
  transition:
    opacity var(--d-panel) var(--ease-out),
    visibility 0s;
}
.lb[data-open="false"] {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity var(--d-panel) var(--ease-out),
    visibility 0s var(--d-panel);
}
.lb-inner {
  text-align: center;
  transition: transform var(--d-panel) var(--ease-out);
}
.lb[data-open="false"] .lb-inner {
  transform: scale(0.95);
}
.lb img {
  max-height: 72vh;
  width: auto;
  margin-inline: auto;
  border-radius: 20px;
  box-shadow: var(--e4);
}
.lb p {
  margin-top: 16px;
  color: #fff;
  font-family: "DM Sans", sans-serif;
  font-weight: 700;
}
.lb-close {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  transition:
    background-color var(--d-hover) ease,
    transform var(--d-press) var(--ease-out);
}
.lb-close:active {
  transform: scale(0.94);
}
@media (hover: hover) and (pointer: fine) {
  .lb-close:hover {
    background: rgba(255, 255, 255, 0.22);
  }
}
.lb-close svg {
  width: 20px;
  height: 20px;
}

/* ── APPS ─────────────────────────────────────────────── */
.apps-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(20px, 3vw, 32px);
}
.app-card {
  display: flex;
  flex-direction: column;
  padding: clamp(26px, 3vw, 36px);
  border-radius: var(--r-xl);
  border: 1px solid var(--on-dark-line);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.02));
  overflow: hidden;
}
.app-card.driver {
  background: linear-gradient(180deg, rgba(245, 165, 36, 0.11), rgba(255, 255, 255, 0.02));
}
.app-card.driver .pill {
  background: rgba(245, 165, 36, 0.14);
  color: var(--amber);
  border-color: rgba(245, 165, 36, 0.3);
}
.app-card h3 {
  font-size: clamp(1.45rem, 2.4vw, 1.85rem);
  margin-top: 16px;
}
.app-card p {
  margin-top: 12px;
  color: var(--on-dark-2);
  font-size: 0.98rem;
  max-width: 38ch;
}
.app-card .store-btns {
  margin-top: 24px;
}
.app-shots {
  display: flex;
  gap: 14px;
  justify-content: center;
  margin-top: 36px;
  margin-bottom: -88px;
  /* the phones sink out of the card rather than being sliced off */
  mask-image: linear-gradient(to bottom, #000 62%, transparent 99%);
  -webkit-mask-image: linear-gradient(to bottom, #000 62%, transparent 99%);
}
.app-shots .phone {
  max-width: 158px;
}
.app-shots .phone:nth-child(2) {
  transform: translateY(-20px);
}

/* ── ESTIMATOR ────────────────────────────────────────── */
.est {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.84fr);
  gap: clamp(24px, 3.5vw, 44px);
  align-items: start;
}
.est-controls {
  display: grid;
  gap: 24px;
}
.est-field label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  font-size: 0.94rem;
  font-weight: 600;
  color: var(--text-2);
}
.est-field .val {
  font-family: "DM Sans", sans-serif;
  font-size: 1.2rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.est-field .hint {
  font-size: 0.8rem;
  color: var(--text-3);
  margin-top: -4px;
}
.est-out {
  padding: clamp(24px, 3vw, 34px);
  border-radius: var(--r-xl);
  background: var(--ink);
  color: #fff;
  box-shadow: var(--e4);
}
.est-hero-num {
  font-family: "DM Sans", sans-serif;
  font-size: clamp(2.6rem, 6vw, 3.6rem);
  font-weight: 800;
  letter-spacing: -0.045em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--teal-light);
}
.est-out .cap {
  margin-top: 10px;
  color: var(--on-dark-2);
  font-size: 0.95rem;
}
.est-out .cap b {
  color: #fff;
}
.est-rows {
  margin-top: 26px;
  padding-top: 20px;
  border-top: 1px solid var(--on-dark-line);
  display: grid;
  gap: 13px;
}
.est-rows div {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: 0.93rem;
  color: var(--on-dark-2);
}
.est-rows b {
  color: #fff;
  font-variant-numeric: tabular-nums;
  font-weight: 650;
  text-align: right;
}
.est-out .btn {
  margin-top: 26px;
}
.est-foot {
  margin-top: 14px;
  font-size: 0.78rem;
  color: var(--on-dark-3);
  text-align: center;
}

/* ── PROOF ────────────────────────────────────────────────
   One customer, one card. Three columns of quotes would look busier,
   but a single account given room to actually say something is worth
   more than a wall of one-liners. */
.quote-solo {
  position: relative;
  max-width: 780px;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: clamp(28px, 4vw, 46px);
  border-radius: var(--r-xl);
  background: var(--white);
  border: 1px solid var(--border);
  box-shadow: var(--e2);
}
/* Decorative, so it sits behind the text and never fights it. */
.quote-solo::before {
  content: "\201C";
  position: absolute;
  top: clamp(-6px, 0.4vw, 2px);
  right: clamp(20px, 3vw, 40px);
  font-family: "DM Sans", sans-serif;
  font-size: clamp(96px, 12vw, 150px);
  font-weight: 800;
  line-height: 1;
  color: var(--teal);
  opacity: 0.11;
  pointer-events: none;
}
.quote-solo .stars {
  display: flex;
  gap: 3px;
  color: var(--amber);
}
.quote-solo .stars svg {
  width: 17px;
  height: 17px;
}
.quote-solo blockquote {
  display: grid;
  gap: 14px;
  max-width: 62ch;
}
.quote-solo .q-lead {
  font-family: "DM Sans", sans-serif;
  font-size: clamp(1.15rem, 2vw, 1.4rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.3;
  color: var(--text);
}
.quote-solo blockquote p {
  font-size: 1rem;
  line-height: 1.68;
  color: var(--text-2);
}
.quote-solo figcaption {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 6px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
}
.quote-solo .av {
  width: 46px;
  height: 46px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--teal-deep), var(--teal));
  color: #fff;
  font-family: "DM Sans", sans-serif;
  font-size: 0.92rem;
  font-weight: 700;
}
.quote-solo .who {
  display: block;
  font-size: 0.98rem;
  font-weight: 650;
}
.quote-solo .role {
  display: block;
  margin-top: 2px;
  font-size: 0.86rem;
  color: var(--text-3);
}

/* Pricing cards, the final CTA and the .final band all live in
   assets/numus.css — the inner pages use them too. */

/* ── PAGE RESPONSIVE ──────────────────────────────────── */
@media (max-width: 980px) {
  .hero-grid,
  .journey,
  .est,
  .ind-panel {
    grid-template-columns: minmax(0, 1fr);
  }
  .hero-sub {
    max-width: 46ch;
  }
  .hero-visual {
    min-height: 0;
    margin-top: 16px;
  }
  .hero-phone-back {
    left: 3%;
  }
  .journey {
    gap: 36px;
  }
  .j-visual,
  .ind-shot {
    order: -1;
  }
  .apps-grid,
  .bento,
  .plans {
    grid-template-columns: 1fr 1fr;
  }
  .app-shots {
    margin-bottom: -60px;
  }
}
@media (max-width: 720px) {
  .bento,
  .plans,
  .apps-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .hero-visual {
    justify-content: flex-start;
    padding-left: 6%;
  }
  .hero-phone-back {
    display: none;
  }
  .proof-card {
    right: auto;
    left: 44%;
    bottom: 30px;
    width: min(210px, 52vw);
  }
  .j-step {
    grid-template-columns: 36px 1fr;
    gap: 12px;
    padding: 14px 14px 18px;
  }
  .j-num {
    width: 36px;
    height: 36px;
    font-size: 0.85rem;
  }
  .plan.pop {
    margin-top: 12px;
  }
}
@media (min-width: 981px) {
  .est-out {
    position: sticky;
    top: calc(var(--nav-h) + 24px);
  }
}
/* ── 13. AUDIENCE FORK ─────────────────────────────────────────
   Numus is sold to two kinds of business: companies where delivery *is* the
   product (couriers, fleets, 3PLs) and companies where delivery is the last
   step of the product (restaurants, pharmacies, shops). The chooser at / asks
   which one you are, then every page inside /logistics/ or /business/ argues
   the case for that one only. */

/* ── The chooser ──────────────────────────────────────────── */
.chooser {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  padding-top: calc(var(--nav-h) + clamp(36px, 5vw, 64px));
  padding-bottom: clamp(48px, 7vw, 88px);
  background: var(--ink);
  color: var(--on-dark);
}
.chooser::before {
  content: "";
  position: absolute;
  top: -30%;
  left: 50%;
  width: min(1200px, 140vw);
  aspect-ratio: 1;
  transform: translateX(-50%);
  background: radial-gradient(
    circle,
    rgba(0, 179, 164, 0.17) 0%,
    rgba(0, 179, 164, 0.045) 40%,
    transparent 68%
  );
  pointer-events: none;
}
.chooser::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
  background-size: 62px 62px;
  mask-image: radial-gradient(ellipse 80% 70% at 50% 0%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 0%, #000 20%, transparent 78%);
  pointer-events: none;
}
.chooser .wrap {
  position: relative;
  z-index: 1;
  width: 100%;
}
/* The claim on the left, a person using the product on the right. The doors
   sit under both, still equal in weight — the photograph argues that Numus is
   real software somebody already runs, not which door you belong to. */
.chooser-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  gap: clamp(28px, 4vw, 52px);
  align-items: center;
}
/* Sized so "Smarter. Faster. Better." holds one line at every width: the
   headline is a two-line phrase and reads as nonsense broken anywhere else. */
.chooser-head h1 {
  font-size: clamp(1.95rem, 3.85vw, 2.95rem);
  line-height: 1.06;
  letter-spacing: -0.04em;
  margin-top: 18px;
  text-wrap: balance;
}
.chooser-head p {
  margin-top: 18px;
  max-width: 42ch;
  font-size: clamp(1rem, 1.5vw, 1.15rem);
  line-height: 1.55;
  color: var(--on-dark-2);
  text-wrap: pretty;
}

/* The photograph. Its native width is 1224px and it is never shown above
   ~560px, so it stays sharp on a 2× screen — which matters here more than
   anywhere else on the site, because the whole point is the app inside it. */
.chooser-visual {
  position: relative;
  justify-self: end;
  width: 100%;
  max-width: 560px;
}
.in-hand {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-xl);
  background: var(--ink-2);
  box-shadow:
    var(--e4),
    inset 0 0 0 1px rgba(255, 255, 255, 0.07);
}
.in-hand img {
  width: 100%;
  filter: saturate(1.03) contrast(1.02);
}
/* The photo is warm and the page is cold. A teal wash across the shadows ties
   it to the rest of the band without touching the screen, which sits in the
   upper right where the gradient has already faded out. */
.in-hand::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    128deg,
    rgba(0, 179, 164, 0.22) 0%,
    rgba(0, 179, 164, 0.06) 34%,
    transparent 62%
  );
  pointer-events: none;
}
.chooser .proof-card {
  right: auto;
  left: -22px;
  bottom: 26px;
}

/* The fork. A line, a sentence, a line — the page changes subject here, and
   the doors underneath read as an answer to it. */
.fork-head {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(14px, 3vw, 28px);
  margin-top: clamp(36px, 4.5vw, 60px);
}
.fork-head span {
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--on-dark-line));
}
.fork-head span:last-child {
  background: linear-gradient(90deg, var(--on-dark-line), transparent);
}
.fork-head p {
  font-size: clamp(0.94rem, 1.3vw, 1.04rem);
  line-height: 1.5;
  color: var(--on-dark-2);
  text-align: center;
  max-width: 46ch;
}

/* Two doors, deliberately identical in weight. This is a fork, not an
   upsell — the moment one card looks "recommended", the other reads as the
   lesser product and half the audience second-guesses itself. */
.doors {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(16px, 2.4vw, 28px);
  margin-top: clamp(36px, 5vw, 56px);
  align-items: stretch;
}
.door {
  display: flex;
  flex-direction: column;
  padding: clamp(26px, 3.2vw, 38px);
  border-radius: var(--r-xl);
  border: 1px solid var(--on-dark-line);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.02));
  color: var(--on-dark);
  transition:
    transform var(--d-hover) var(--ease-out),
    border-color var(--d-hover) ease,
    background-color var(--d-hover) ease;
}
.door:active {
  transform: scale(0.985);
}
@media (hover: hover) and (pointer: fine) {
  .door:hover {
    transform: translateY(-4px);
    border-color: rgba(0, 179, 164, 0.5);
  }
  .door.amber:hover {
    border-color: rgba(245, 165, 36, 0.5);
  }
  .door:hover .door-enter {
    gap: 12px;
  }
}
.door .ic {
  width: 52px;
  height: 52px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 15px;
  background: rgba(0, 179, 164, 0.16);
  color: var(--teal-light);
}
.door.amber .ic {
  background: rgba(245, 165, 36, 0.16);
  color: var(--amber);
}
.door .ic svg {
  width: 25px;
  height: 25px;
}
.door h2 {
  margin-top: 22px;
  font-size: clamp(1.5rem, 2.6vw, 1.95rem);
  letter-spacing: -0.03em;
  line-height: 1.15;
}
.door .says {
  margin-top: 14px;
  font-size: clamp(1rem, 1.4vw, 1.08rem);
  line-height: 1.55;
  color: var(--on-dark-2);
}
.door .who {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--on-dark-line);
  font-size: 0.87rem;
  line-height: 1.6;
  color: var(--on-dark-3);
}
/* Pushes the button to the bottom so both cards line their CTAs up even when
   one has a longer industry list. */
.door .door-spacer {
  flex: 1;
  min-height: 22px;
}
.door-enter {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 50px;
  padding: 0 26px;
  border-radius: var(--r-pill);
  background: var(--teal);
  color: #04231f;
  font-family: "DM Sans", sans-serif;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  transition: gap var(--d-hover) var(--ease-out);
}
.door.amber .door-enter {
  background: var(--amber);
  color: #3d2600;
}
.door-enter svg {
  width: 17px;
  height: 17px;
  flex: none;
}

@media (max-width: 980px) {
  /* Stacked, the copy still leads and the photo still comes before the doors —
     a visitor should meet a person before they are asked to pick a side. */
  .chooser-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .chooser-visual {
    justify-self: center;
    max-width: 520px;
  }
  .chooser .proof-card {
    left: -10px;
    bottom: -16px;
  }
}
@media (max-width: 760px) {
  .doors {
    grid-template-columns: minmax(0, 1fr);
  }
  .chooser .proof-card {
    position: static;
    width: 100%;
    margin-top: 20px;
  }
  .fork-head {
    grid-template-columns: minmax(0, 1fr);
  }
  .fork-head span {
    display: none;
  }
  .door .door-spacer {
    display: none;
  }
  .door-enter {
    margin-top: 22px;
    width: 100%;
  }
}

/* ── The switcher that lives in the nav ───────────────────────
   Someone who picks the wrong door must never feel trapped. This sits beside
   Sign in, states which section you're in, and says where the other one goes. */
.aud-switch {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 14px;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  background: var(--surface-2);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-2);
  white-space: nowrap;
  transition:
    border-color var(--d-hover) ease,
    color var(--d-hover) ease,
    transform var(--d-press) var(--ease-out);
}
.aud-switch:active {
  transform: scale(0.97);
}
@media (hover: hover) and (pointer: fine) {
  .aud-switch:hover {
    border-color: var(--teal);
    color: var(--text);
  }
}
.aud-switch .now {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
  color: var(--text);
}
.aud-switch .now::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--teal);
}
.aud-switch.amber .now::before {
  background: var(--amber);
}
.aud-switch svg {
  width: 14px;
  height: 14px;
  flex: none;
  opacity: 0.6;
}
.nav-over-dark:not([data-stuck="true"]) .aud-switch {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--on-dark-line);
  color: var(--on-dark-2);
}
.nav-over-dark:not([data-stuck="true"]) .aud-switch .now {
  color: #fff;
}
/* Below 1100px the nav has to choose between this and the CTA. The CTA wins;
   the mobile sheet carries the switch instead. */
@media (max-width: 1100px) {
  .aud-switch {
    display: none;
  }
}
/* The sheet is the only place it survives below 1100px, so it has to opt back
   in past the rule above. It also has to be allowed to wrap: "Logistics ⇄
   Switch to Delivery-driven" on one nowrap line is 291px, which does not fit
   a 320px screen's content column. */
.nav-sheet .aud-switch {
  display: inline-flex;
  flex-wrap: wrap;
  max-width: 100%;
  white-space: normal;
  padding-block: 8px;
}

/* ── Wide tiles in the bento ──────────────────────────────────
   The gallery was six phone screenshots in a 3-up grid. Numus is a web
   product first, so four of the six are now dashboard captures.

   That forces the grid down to two columns. A dashboard tile needs roughly
   half the row to be legible, and in a 3-up grid a run of half-row tiles
   leaves the third column orphaned on every line. Two columns takes the six
   tiles as three clean rows: dashboard, dashboard / dashboard, dashboard /
   phone, phone. */
.bento {
  grid-template-columns: repeat(2, 1fr);
}
.tile.wide .tile-media {
  padding: 22px 22px 0;
}
/* A 520x1130 phone in a half-row cell is twice the height of a dashboard, so
   the phone row towered over the other two. Pinning every media box to the
   dashboard's ratio evens the rows out; .tile-media already clips, so the
   phone simply carries on past the caption the way the design intends. */
.bento .tile-media {
  aspect-ratio: 1475 / 770;
  align-items: flex-start;
}
.tile.wide .tile-media img {
  max-width: none;
  aspect-ratio: 1475 / 770;
  object-fit: cover;
  object-position: top center;
  border-radius: 12px 12px 0 0;
}
@media (max-width: 720px) {
  .bento {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── Storefront proof ─────────────────────────────────────────
   Real published customer sites, web and mobile side by side. */
.store-proof {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr);
  gap: clamp(28px, 4vw, 60px);
  align-items: center;
}
@media (max-width: 980px) {
  .store-proof {
    grid-template-columns: minmax(0, 1fr);
  }
  .store-proof .store-proof-media {
    order: -1;
  }
}

/* The chooser is its own dark band rather than a .on-dark section, so the
   handful of components that sit on it need the dark treatment by hand. */
.chooser .pill {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--on-dark-line);
  color: var(--on-dark-2);
}

/* One-audience popover: a single caption instead of the two-column header
   that contrasted the sections against each other. */
.nav-pop-head.one {
  grid-template-columns: minmax(0, 1fr);
}

/* The explanatory paragraph the industry switcher gained — the panel used to
   jump straight from headline to tick list, which read as a slogan. */
.ind-body {
  margin-top: 16px;
  font-size: 1rem;
  line-height: 1.62;
  color: var(--text-2);
  max-width: 46ch;
}

/* The switcher's shot is a browser frame now, so it needs room to breathe
   rather than the narrow column a phone wanted. */
.ind-panel {
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.95fr);
}
.ind-shot .browser,
.j-visual .browser {
  width: 100%;
}
.j-visual > div:not(.j-chip) {
  width: 100%;
}
@media (max-width: 980px) {
  .ind-panel {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* The journey chip sat over a centred phone. Over a full-width browser frame
   it belongs at the top-left of the capture, clear of the window chrome. */
.j-visual .j-chip {
  top: -14px;
  left: 18px;
  transform: none;
}

.store-body code,
.lede code {
  padding: 2px 7px;
  border-radius: var(--r-sm);
  background: var(--surface-3);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.86em;
  color: var(--teal-deep);
}
.on-dark .lede code {
  background: rgba(255, 255, 255, 0.09);
  color: var(--teal-light);
}

/* The door you came through last time. A hairline and a word — enough to help
   a returning visitor, not enough to make the other door look like a mistake. */
.door[data-last="true"] {
  border-color: rgba(255, 255, 255, 0.28);
}
.door[data-last="true"] .ic::after {
  content: "Last time";
  position: absolute;
  margin: -46px 0 0 58px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.1);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--on-dark-3);
  white-space: nowrap;
}
.door .ic {
  position: relative;
}

/* ── 14. WEB-FRAME LAYOUT FIXES ────────────────────────────────
   The row and hero layouts were both proportioned around a 268px phone.
   A dashboard capture needs roughly twice that, so rows carrying one say so
   and get a wider media column. */
.frow.wide {
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
}
@media (max-width: 980px) {
  .frow.wide {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* The visual takes the larger share of the hero. It held a 268px phone
   once, then a dashboard, and now a person at 4:5 with the dashboard behind
   her — each of which needed more room than the last. */
.hero-grid {
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
}
@media (max-width: 980px) {
  .hero-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── 15. PEOPLE ────────────────────────────────────────────────
   The site was all dashboards and phones — true to the product, but it read
   like software rather than like a business anyone runs. These are real
   photographs of the people who actually do this work.

   Every one of them is a small file (201px to 800px wide). The sizes below are
   capped at each photo's native width: shown any larger they go soft, and a
   blown-up stock photo cheapens a page faster than no photo at all. */
.people {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}

/* Mosaic: one tall frame, one wide one, two squares, plus two circular
   insets that overlap the seams so the block reads as a scene rather than a
   contact sheet. */
.people-mosaic {
  position: relative;
  display: grid;
  grid-template-columns: 1.05fr 0.85fr 0.85fr;
  grid-template-rows: auto auto;
  gap: 14px;
}
.people-mosaic figure {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--surface-3);
  box-shadow: var(--e2);
}
.people-mosaic img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The photographs are candid and warm but shot in wildly different light.
     A whisper of saturation and contrast pulls them into one set without
     making them look filtered. */
  filter: saturate(1.04) contrast(1.02);
}
.people-mosaic .tall {
  grid-column: 1;
  grid-row: 1 / 3;
  aspect-ratio: 3 / 4.4;
}
.people-mosaic .wide {
  grid-column: 2 / 4;
  grid-row: 1;
  aspect-ratio: 16 / 10;
}
.people-mosaic .sq-a {
  grid-column: 2;
  grid-row: 2;
  aspect-ratio: 1;
}
.people-mosaic .sq-b {
  grid-column: 3;
  grid-row: 2;
  aspect-ratio: 1;
}

/* The two smallest photos (201px and 275px wide) can only ever be tiny, so
   they become circular insets rather than tiles — a size at which they stay
   perfectly sharp. */
.people-mosaic .inset {
  position: absolute;
  border-radius: 50%;
  border: 4px solid var(--white);
  box-shadow: var(--e3);
  overflow: hidden;
  z-index: 2;
}
.people-mosaic .inset img {
  aspect-ratio: 1;
}
.people-mosaic .inset-a {
  width: clamp(64px, 9vw, 104px);
  left: -18px;
  bottom: 16%;
}
.people-mosaic .inset-b {
  width: clamp(58px, 8vw, 92px);
  right: -14px;
  top: 34%;
}
.on-dark .people-mosaic .inset {
  border-color: var(--ink-2);
}

.people-stat {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 30px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  font-size: 0.92rem;
  color: var(--text-3);
}
/* The glyph is a flex item in an `align-items: center` row: an SVG carrying
   only a viewBox has no intrinsic size here and stretches to the row's
   height, so it states one rather than relying on inline width/height. */
.people-stat svg {
  flex: none;
  width: 18px;
  height: 18px;
}
.on-dark .people-stat {
  border-top-color: var(--on-dark-line);
  color: var(--on-dark-3);
}

@media (max-width: 980px) {
  .people {
    grid-template-columns: minmax(0, 1fr);
  }
  /* Full width, the square tiles ask for 255px from a 225px photograph and
     go soft. Capped so no tile is ever shown above its own pixels. */
  .people-mosaic {
    order: -1;
    max-width: 760px;
    margin-inline: auto;
  }
}
@media (max-width: 560px) {
  /* Three columns of photographs at 375px would be postage stamps. Two tiles
     and the insets carry the idea just as well. */
  .people-mosaic {
    grid-template-columns: 1fr 1fr;
  }
  .people-mosaic .tall {
    aspect-ratio: 3 / 4;
  }
  .people-mosaic .wide {
    grid-column: 2;
    grid-row: 1;
    aspect-ratio: 1;
  }
  .people-mosaic .sq-a {
    grid-column: 1 / 3;
    grid-row: 2;
    aspect-ratio: 16 / 9;
  }
  .people-mosaic .sq-b {
    display: none;
  }
}

/* ── Faces on the industry switcher ────────────────────────────
   A circular portrait tucked onto the corner of the screenshot: the person
   this screen belongs to, next to the screen itself. */
.ind-shot {
  position: relative;
}
.ind-face {
  position: absolute;
  left: -14px;
  bottom: -14px;
  z-index: 3;
  width: clamp(72px, 9vw, 108px);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  border: 4px solid var(--white);
  box-shadow: var(--e3);
}
.ind-face img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(1.04) contrast(1.02);
}
@media (max-width: 720px) {
  .ind-face {
    left: 0;
    width: 72px;
  }
}

/* ── Faces on the chooser doors ────────────────────────────────
   Three overlapping portraits per door. At 60px they stay sharp, and they
   answer "who is this for" faster than the sentence underneath does. */
.door-faces {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 20px;
}
.face-stack {
  display: flex;
}
.face-stack span {
  width: clamp(52px, 6.4vw, 72px);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  border: 3px solid var(--ink);
  background: var(--ink-3);
  margin-left: -16px;
  transition: transform var(--d-hover) var(--ease-out);
}
.face-stack span:first-child {
  margin-left: 0;
}
.face-stack img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(1.04) contrast(1.02);
}
/* On hover the stack fans out — the photos stop being a texture and become
   three separate people. Transform only, so it costs nothing. */
@media (hover: hover) and (pointer: fine) {
  .door:hover .face-stack span:nth-child(2) {
    transform: translateX(5px);
  }
  .door:hover .face-stack span:nth-child(3) {
    transform: translateX(10px);
  }
}
.door-faces small {
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--on-dark-3);
}

/* Subject positions. `object-fit: cover` centres by default, which works for
   the photos where the person is mid-frame — but in the kitchen shot the
   staff member stands low and right, so a centred circular crop lands on the
   ceiling lights instead of on him. */
.people-mosaic .inset-b img {
  object-position: 62% 88%;
}
.people-mosaic .sq-a img {
  object-position: 60% center;
}
.ind-face img[src*="kitchen"] {
  object-position: 62% 88%;
}

/* ── 16. THE ROUTE RAIL ────────────────────────────────────────
   One delivery, running down the page margin. The rider leaves the hero as
   you start reading and reaches the pin as you reach the footer; the only
   input is how far down the page you are, so the motion is never something
   that happens *at* you — it tracks your hand the whole way.

   It sits in the gutter beside the content column rather than over it, is
   `pointer-events: none` so it can never take a tap, is `aria-hidden` in the
   markup, and is gone entirely under reduced motion. Nothing here is
   information a reader can't get from the scrollbar.

   `--p` (0→1) and `--lean` are written by numus.js on this element and read
   by the children, which is two custom properties on a subtree of four — the
   style recalculation that normally makes this pattern expensive doesn't
   apply at this size. */
.route {
  position: fixed;
  /* Below the nav and its menu, above the page. */
  z-index: 90;
  top: calc(var(--nav-h) + 54px);
  bottom: 104px;
  /* Tracks the outside edge of the content column, never overlapping it. */
  right: max(8px, calc(50vw - var(--max) / 2 - 46px));
  width: 40px;
  pointer-events: none;
  /* Nothing until JS has a scroll position, so it fades in at rest instead of
     appearing parked at the start line. */
  opacity: 0;
  transition: opacity 420ms var(--ease-out);
}
.route[data-ready="true"] {
  opacity: 1;
}

/* The road: a dashed hairline that has to stay legible over both the white
   sections and the ink ones, so it is a mid blue-grey rather than either. */
.route-rail {
  position: absolute;
  inset: 0 auto 0 50%;
  width: 2px;
  margin-left: -1px;
  border-radius: 2px;
  background-image: linear-gradient(rgba(122, 146, 170, 0.5) 55%, transparent 55%);
  background-size: 2px 9px;
}
/* The distance already covered. */
.route-rail i {
  position: absolute;
  inset: 0;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--teal-light), var(--teal));
  transform: scaleY(var(--p, 0));
  transform-origin: top;
}

.route-start {
  position: absolute;
  top: -3px;
  left: 50%;
  width: 8px;
  height: 8px;
  margin-left: -4px;
  border-radius: 50%;
  background: var(--teal);
  box-shadow: 0 0 0 3px rgba(0, 179, 164, 0.18);
}

/* The address, sitting just past the end of the road so the rider pulls up
   at it rather than landing on top of it. Grey until the delivery arrives. */
.route-end {
  position: absolute;
  bottom: -46px;
  left: 50%;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  color: rgba(122, 146, 170, 0.85);
  transform: translateX(-50%);
  transition:
    color var(--d-panel) var(--ease-out),
    transform var(--d-panel) var(--ease-out);
}
.route-end svg {
  width: 22px;
  height: 22px;
}
.route[data-arrived="true"] .route-end {
  color: var(--teal);
  transform: translateX(-50%) scale(1.14);
}

/* The vehicle. A white chip so it reads on ink and on white without needing a
   second colour scheme, and `top` in percent so the travel is one property. */
.route-rider {
  position: absolute;
  top: calc(var(--p, 0) * 100%);
  left: 50%;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  margin: -19px 0 0 -19px;
  border-radius: 50%;
  background: var(--white);
  border: 1px solid var(--border);
  box-shadow: var(--e3);
  color: var(--teal-deep);
  /* Leans into the direction of travel. Written per frame by the scroll loop,
     so it is deliberately not transitioned — the lag is already in the JS. */
  transform: rotate(var(--lean, 0deg));
  transition:
    background-color var(--d-panel) var(--ease-out),
    border-color var(--d-panel) var(--ease-out),
    color var(--d-panel) var(--ease-out);
}
.route-veh,
.route-done {
  grid-area: 1 / 1;
  display: grid;
  place-items: center;
  transition:
    opacity var(--d-pop) var(--ease-out),
    transform var(--d-panel) var(--ease-out);
}
.route-veh svg,
.route-done svg {
  width: 19px;
  height: 19px;
}
.route-done {
  opacity: 0;
  transform: scale(0.72);
}
.route[data-arrived="true"] .route-rider {
  background: var(--teal);
  border-color: var(--teal);
  color: #04231f;
}
.route[data-arrived="true"] .route-veh {
  opacity: 0;
  transform: scale(0.72);
}
.route[data-arrived="true"] .route-done {
  opacity: 1;
  transform: none;
}

@media (max-width: 900px) {
  /* No gutter left to sit in, so it hugs the edge and gets smaller. Still
     `pointer-events: none`, so an overlap with a card corner costs nothing. */
  .route {
    top: calc(var(--nav-h) + 36px);
    bottom: 72px;
    right: 2px;
    width: 28px;
  }
  .route-rider {
    width: 28px;
    height: 28px;
    margin: -14px 0 0 -14px;
  }
  .route-veh svg,
  .route-done svg {
    width: 16px;
    height: 16px;
  }
  .route-end {
    bottom: -36px;
    width: 20px;
    height: 20px;
  }
  .route-end svg {
    width: 18px;
    height: 18px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .route {
    display: none;
  }
}
@media print {
  .route {
    display: none;
  }
}
