/* JDF Solutions: Steep-style editorial system. Serif headlines over a soft
   pastel aurora, tinted floating product cards, ink pill CTAs. Signifier is
   substituted by Source Serif 4, Sohne by Inter. */

:root {
  /* height of the fixed nav; heroes add it back as top padding */
  --nav-h: 76px;
  /* colors */
  --ink: #17191c;
  --paper: #ffffff;
  --mist: #f2f2f3;
  --fog: #fafafb;
  --slate: #777b86;
  --ash: #979799;
  --smoke: #a3a6af;
  --peach: #fbe1d1;
  --peach-soft: #fdeee3;
  --sienna: #5d2a1a;
  --hairline: #ececec;
  /* data-card tints (product artifacts only) */
  --tint-blue: #e7effa;
  --navy: #2c4a73;
  --bar-blue: #4477ad;
  --tint-green: #ddedd9;
  --pine: #2f5e3a;
  /* brand (logo only) */
  --jupiter-orange: #ff9000;
  /* type */
  --font-serif: "Source Serif 4", Georgia, ui-serif, serif;
  --font-sans: "Inter", -apple-system, "Segoe UI", ui-sans-serif, sans-serif;
  /* easing: the built-in keywords are too weak to read as deliberate. Entering,
     exiting and pressing all use --ease-out; the built-in ease is kept only for
     plain colour changes, where there is no movement to shape. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  /* radius */
  --r-card: 24px;
  --r-elevated: 20px;
  --r-input: 16px;
  --r-small: 16px;
  --r-img: 12px;
  --r-pill: 9999px;
  /* elevation (floating artifacts only) */
  --shadow-artifact:
    0 0 0 1px rgba(4, 23, 43, 0.05),
    0 20px 25px -5px rgba(0, 0, 0, 0.1),
    0 8px 10px -6px rgba(0, 0, 0, 0.1);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* The nav is fixed rather than sticky so the hero's aurora runs under it and
   the bar reads as genuinely transparent at the top of the page. Sticky left
   the bar in normal flow, which put a band of white body background above the
   wash. Every page opens with .hero or .page-hero, so the lost flow height is
   added back as top padding in exactly those two rules. */
html { scroll-behavior: smooth; scroll-padding-top: var(--nav-h); }

body {
  font-family: var(--font-sans);
  font-size: 17px;
  font-weight: 400;
  line-height: 1.35;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: var(--ink); }

.wrap { max-width: 1200px; margin: 0 auto; padding: 0 24px; }

/* ---------- type ---------- */
.tag {
  font-size: 14px;
  font-weight: 400;
  color: var(--ash);
  margin-bottom: 16px;
}
h1, h2, h3.display {
  font-family: var(--font-serif);
  font-weight: 400;
  line-height: 1.22;
  text-wrap: balance;
}
h1 { font-size: clamp(44px, 6.4vw, 84px); letter-spacing: -0.025em; }
h2 { font-size: clamp(34px, 4.4vw, 60px); letter-spacing: -0.015em; }
h1 em, h2 em { font-style: italic; }
.lead {
  font-size: 17px;
  color: var(--slate);
  max-width: 620px;
  line-height: 1.5;
  text-wrap: pretty;
}
.lead-lg { font-size: 20px; color: #3c3f45; }
p { text-wrap: pretty; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 22px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 400;
  text-decoration: none;
  cursor: pointer;
  transition:
    background 160ms ease,
    color 160ms ease,
    transform 160ms var(--ease-out);
}
.btn-primary { background: var(--ink); color: var(--paper); }
.btn-ghost { background: transparent; border-color: var(--ink); color: var(--ink); }
.btn .arrow { transition: transform 200ms var(--ease-out); }
/* colour on any device; movement only where there is a real pointer, so a tap
   on touch does not fire a phantom hover */
.btn-primary:hover { background: #2a2d33; }
.btn-ghost:hover { background: rgba(23, 25, 28, 0.05); }
@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover { transform: translateY(-1px); }
  .btn:hover .arrow { transform: translateX(3px); }
}
/* Press feedback: the transform transition above was declared but nothing ever
   triggered it, so a click gave no acknowledgement at all. Ungated on purpose,
   a press is real on touch too, and it sits after the hover block so a pressed
   button scales rather than keeping the hover lift. */
.btn:active { transform: scale(0.97); }

/* plain text action paired with a filled pill (Steep's "Book a demo") */
.btn-text {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 12px 10px;
  font-size: 16px;
  color: var(--ink);
  text-decoration: none;
}
.btn-text:hover { text-decoration: underline; }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 16px 0;
  font-size: 16px;
  color: var(--ink);
  text-decoration: none;
}
.link-arrow:hover { text-decoration: underline; }

/* ---------- nav ---------- */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  background: transparent;
  /* fade the frosted panel in rather than snapping it on at 8px of scroll */
  transition: background-color 220ms cubic-bezier(0.23, 1, 0.32, 1);
}
.nav.scrolled {
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 18px 24px;
  max-width: 1200px;
  margin: 0 auto;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  color: var(--ink);
}
.brand img { width: 30px; height: 30px; }
/* The company answers to both names, so the wordmark crossfades between them.
   inline-grid stacks both in a single cell sized to the wider one, so the swap
   is pure opacity and the nav never reflows. */
.brand-name {
  display: inline-grid;
  font-family: var(--font-serif);
  font-size: 19px;
  letter-spacing: 0.08em;
  white-space: nowrap;
}
.brand-name > span {
  grid-area: 1 / 1;
  animation: brand-swap-a 12s ease-in-out infinite;
}
/* the second name gets inverted keyframes rather than a delay: a delayed
   animation has no value applied during its delay, which would leave both
   wordmarks stacked at full opacity for the first cycle */
.brand-name > span + span { animation-name: brand-swap-b; }
@keyframes brand-swap-a {
  0%, 42% { opacity: 1; }
  50%, 92% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes brand-swap-b {
  0%, 42% { opacity: 0; }
  50%, 92% { opacity: 1; }
  100% { opacity: 0; }
}
.nav-links { display: flex; gap: 28px; align-items: center; }
.nav-links a { color: var(--ink); text-decoration: none; font-size: 16px; padding: 2px 0; }
.nav-links a:hover { text-decoration: underline; }
.nav-links a.active { text-decoration: underline; text-underline-offset: 4px; }
.nav-cta { display: flex; align-items: center; gap: 14px; }
.nav-cta .btn { padding: 9px 18px; font-size: 15px; }
.nav-toggle {
  display: none;
  background: none;
  border: 1px solid rgba(23, 25, 28, 0.2);
  border-radius: var(--r-pill);
  color: var(--ink);
  font-size: 18px;
  line-height: 1;
  padding: 8px 13px;
  cursor: pointer;
}
@media (max-width: 960px) {
  .nav-links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    background: var(--paper);
    border-bottom: 1px solid var(--hairline);
    padding: 8px 24px 16px;
  }
  .nav-links a { padding: 10px 0; width: 100%; }
  .nav-links.open { display: flex; }
  /* the bar is transparent at rest, which left the open menu looking like a
     detached white slab; give the bar the same paper while it is open */
  .nav:has(.nav-links.open) { background: var(--paper); }
  .nav-toggle { display: block; }
  .nav-cta .btn-primary { display: none; }
}

/* ---------- aurora backdrop ---------- */
.aurora {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
.aurora::before {
  content: "";
  position: absolute;
  inset: -25%;
  background:
    radial-gradient(38% 42% at 16% 24%, rgba(213, 226, 247, 0.95), transparent 70%),
    radial-gradient(40% 46% at 84% 22%, rgba(251, 225, 209, 0.95), transparent 70%),
    radial-gradient(38% 44% at 72% 82%, rgba(248, 206, 194, 0.85), transparent 72%),
    radial-gradient(42% 46% at 26% 84%, rgba(232, 220, 244, 0.8), transparent 70%),
    radial-gradient(30% 34% at 50% 50%, rgba(252, 240, 230, 0.7), transparent 75%),
    #ffffff;
  filter: blur(48px);
}
.aurora::after {
  /* fade the wash into the white canvas below */
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 160px;
  background: linear-gradient(180deg, transparent, #ffffff);
}
.aurora.soft::before { opacity: 0.55; }

/* ---------- hero ---------- */
.hero {
  position: relative;
  padding: calc(100px + var(--nav-h)) 0 190px;
  text-align: center;
}
.hero-inner { position: relative; z-index: 2; max-width: 820px; margin: 0 auto; }
.hero h1 { margin-bottom: 24px; }
.hero .lead { margin: 0 auto 34px; }
.hero-cta { display: flex; gap: 10px; justify-content: center; align-items: center; flex-wrap: wrap; }
.hero-note {
  margin-top: 34px;
  font-size: 15px;
  color: var(--slate);
  display: inline-flex;
  gap: 18px;
  flex-wrap: wrap;
  justify-content: center;
}

/* ---------- floating product artifacts ---------- */
.artifact {
  position: absolute;
  border-radius: var(--r-elevated);
  box-shadow: var(--shadow-artifact);
  padding: 18px 20px;
  text-align: left;
  font-size: 14px;
  z-index: 1;
  background: var(--paper);
}
.artifact .a-label { font-size: 14px; font-weight: 500; margin-bottom: 12px; }
.artifact .a-metric { font-size: 26px; font-weight: 500; letter-spacing: -0.01em; }
.artifact .a-delta { font-size: 13px; margin-top: 2px; }

/* blue data card */
.artifact-blue { background: var(--tint-blue); color: var(--navy); }
.artifact-blue .a-label { color: var(--navy); }
.artifact-blue .a-delta { color: rgba(44, 74, 115, 0.7); }
.artifact-blue table { border-collapse: collapse; width: 100%; }
.artifact-blue td {
  padding: 7px 0;
  font-size: 13.5px;
  border-top: 1px solid rgba(44, 74, 115, 0.12);
  white-space: nowrap;
}
.artifact-blue td:last-child { text-align: right; padding-left: 28px; font-weight: 500; }
.artifact-blue tr:first-child td { border-top: 0; }

/* bar chart (pure CSS) */
.bars { display: flex; gap: 6px; align-items: flex-end; height: 62px; margin-top: 14px; }
.bars i { width: 9px; border-radius: 4px; background: var(--bar-blue); display: block; }
.bar-days { display: flex; gap: 6px; margin-top: 6px; }
.bar-days span {
  width: 9px;
  font-size: 9px;
  color: rgba(44, 74, 115, 0.6);
  text-align: center;
}

/* peach gauge card */
.artifact-peach { background: var(--peach-soft); color: var(--sienna); }
.artifact-peach .a-label { color: var(--sienna); }
.artifact-peach .a-delta { color: rgba(93, 42, 26, 0.7); }
.gauge-row { display: flex; align-items: center; gap: 20px; }
.gauge { position: relative; width: 108px; height: 108px; }
.gauge svg { transform: rotate(-90deg); }
.gauge circle { fill: none; stroke-width: 6; stroke-linecap: round; }
.gauge .track { stroke: rgba(93, 42, 26, 0.15); }
.gauge .fill { stroke: var(--sienna); }
.gauge-center {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  text-align: center;
}
.gauge-center strong { font-size: 22px; font-weight: 500; }
.gauge-center span { font-size: 10px; color: rgba(93, 42, 26, 0.7); }

/* line chart card */
.artifact-line { background: var(--paper); color: var(--ink); }
.artifact-line .a-label { color: var(--ink); }
.artifact-line .a-delta { color: var(--slate); }
.artifact-line svg .line { stroke: #3c3f45; fill: none; stroke-width: 1.6; }
.artifact-line svg .dash { stroke: rgba(23, 25, 28, 0.25); stroke-dasharray: 4 4; stroke-width: 1; }
.artifact-line svg .dot { fill: #3c3f45; }

/* composer ("ask anything") card */
.composer {
  position: absolute;
  z-index: 2;
  background: var(--paper);
  border-radius: var(--r-input);
  box-shadow: var(--shadow-artifact);
  padding: 16px 16px 12px;
  width: 330px;
  text-align: left;
}
/* The three composer panels (idle, form, sent) swap by toggling [hidden], so
   each one used to teleport in. display:none cannot be transitioned, so the
   panel that is currently shown carries a short entrance instead. Scale starts
   at 0.97, never 0: the panel grows out of the card rather than out of nothing. */
.composer > :not([hidden]) { animation: composer-in 200ms var(--ease-out) both; }
@keyframes composer-in {
  from { opacity: 0; transform: scale(0.97); }
}
.composer .c-placeholder { font-size: 15px; color: var(--smoke); }
.composer .c-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 18px;
}
.composer .c-icons { display: flex; gap: 10px; color: var(--slate); }
.composer .c-icons svg { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 1.5; }
.composer .c-send {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--ink);
  display: grid;
  place-items: center;
}
.composer .c-send svg { width: 15px; height: 15px; stroke: #fff; fill: none; stroke-width: 2; }

/* avatar bubble with cursor (collaboration motif) */
.av-bubble {
  position: absolute;
  z-index: 3;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 14px;
  font-weight: 500;
  box-shadow: 0 0 0 2px #ffffff;
}
.av-bubble svg {
  position: absolute;
  top: -9px;
  left: -8px;
  width: 15px;
  height: 15px;
  fill: var(--ink);
  stroke: #fff;
  stroke-width: 1;
}
.av-green { background: var(--tint-green); color: var(--pine); }
.av-blue { background: var(--tint-blue); color: var(--navy); }

/* artifact placement on the hero */
.artifact-tl { top: 10px; left: -16px; }
.artifact-tr { top: 96px; right: -16px; }
.artifact-bl { bottom: 4px; left: -16px; }
.composer-hero { bottom: 10px; right: -10px; }
.av-hero { bottom: 118px; right: 330px; }
@media (max-width: 1200px) {
  .artifact, .composer, .av-bubble { display: none; }
  .hero { padding: calc(76px + var(--nav-h)) 0 76px; }
}

/* static (in-flow) artifact for splits */
.artifact-static {
  border-radius: var(--r-elevated);
  box-shadow: var(--shadow-artifact);
  padding: 20px 24px;
  font-size: 14px;
  width: min(100%, 420px);
  background: var(--tint-blue);
  color: var(--navy);
}
.artifact-static .a-label { font-size: 14px; font-weight: 500; margin-bottom: 10px; }
.artifact-static table { border-collapse: collapse; width: 100%; }
.artifact-static td {
  padding: 9px 0;
  font-size: 14px;
  border-top: 1px solid rgba(44, 74, 115, 0.12);
}
.artifact-static tr:first-child td { border-top: 0; }
.artifact-static td:last-child { text-align: right; font-weight: 500; padding-left: 24px; }

/* page hero (inner pages) */
.page-hero { position: relative; padding: calc(84px + var(--nav-h)) 0 48px; text-align: center; }
.page-hero .lead { margin: 20px auto 0; }

/* ---------- sections ---------- */
.section { padding: 100px 0; }
.section.tight { padding: 64px 0; }
.vspace { margin-top: 72px; }
.section.fog { background: var(--fog); }
.section-head { max-width: 760px; margin-bottom: 52px; }
.section-head.center { margin-left: auto; margin-right: auto; text-align: center; }
.section-head p { margin-top: 18px; color: var(--slate); line-height: 1.5; }

/* ---------- cards ---------- */
.card { background: var(--mist); border-radius: var(--r-card); padding: 32px 28px; }
.card .tag { margin-bottom: 10px; }
.card h3 { font-size: 20px; font-weight: 500; letter-spacing: -0.01em; margin-bottom: 12px; }
.card p { color: #3c3f45; font-size: 16px; line-height: 1.5; }
.card p + p { margin-top: 10px; }
.card .muted { color: var(--slate); }

/* tinted feature cards (Steep's colored panels) */
.card-tint-peach { background: var(--peach); }
.card-tint-peach h3, .card-tint-peach .tag { color: var(--sienna); }
.card-tint-peach p { color: rgba(93, 42, 26, 0.85); }
.card-tint-blue { background: #dce8f8; }
.card-tint-blue h3, .card-tint-blue .tag { color: var(--navy); }
.card-tint-blue p { color: rgba(44, 74, 115, 0.85); }

/* Honeypot. Moved off-screen rather than display:none or visibility:hidden,
   which the better form-filling bots already skip. Nothing here is reachable by
   pointer, keyboard or screen reader: the wrapper carries aria-hidden and the
   input tabindex="-1". */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* line-art illustration inside feature cards */
.illus { margin: 30px auto 26px; display: flex; justify-content: center; }
.illus.illus-sm { margin: 24px auto 20px; }
.illus svg { stroke: currentColor; fill: none; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.card .illus { color: #3c3f45; }
.card-tint-peach .illus { color: var(--sienna); }
.card-tint-blue .illus { color: var(--navy); }

/* intro row of a large service card: text beside a photo */
.service-lead {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 40px;
  align-items: center;
}
.service-lead img {
  border-radius: var(--r-small);
  width: 100%;
  height: 260px;
  object-fit: cover;
}
@media (max-width: 900px) { .service-lead { grid-template-columns: 1fr; gap: 24px; } }

/* ---------- device mockups (original, drawn in CSS) ---------- */
/* phone running a remote-control app */
.phone-mock {
  width: 250px;
  background: var(--ink);
  border-radius: 36px;
  padding: 12px;
  box-shadow: var(--shadow-artifact);
  margin: 0 auto;
}
.pm-screen {
  background: var(--paper);
  border-radius: 26px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.pm-appbar {
  background: var(--bar-blue);
  color: #fff;
  font-size: 12.5px;
  font-weight: 500;
  padding: 12px 16px 10px;
  display: flex;
  align-items: center;
  gap: 7px;
}
.pm-appbar::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #8fe3a4;
}
.pm-body { padding: 26px 18px 18px; display: grid; gap: 11px; }
.pm-title {
  font-size: 15px;
  font-weight: 500;
  text-align: center;
  margin-bottom: 6px;
  color: var(--ink);
}
.pm-field {
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 12.5px;
  color: var(--smoke);
}
.pm-btn {
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 12.5px;
  font-weight: 500;
  text-align: center;
}
.pm-btn-fill { background: var(--bar-blue); color: #fff; }
.pm-btn-line { border: 1px solid var(--bar-blue); color: var(--bar-blue); }
.pm-foot {
  border-top: 1px solid var(--hairline);
  padding: 10px 16px 14px;
  font-size: 11px;
  color: var(--slate);
  text-align: center;
}

/* desktop monitor mirroring a phone, small handset in front */
.mirror-mock { position: relative; width: min(100%, 430px); margin: 0 auto; padding-bottom: 34px; }
.mm-monitor {
  background: var(--ink);
  border-radius: 16px;
  padding: 12px;
  box-shadow: var(--shadow-artifact);
}
.mm-screen {
  background: linear-gradient(160deg, #dfe9f8, #f6e7dc);
  border-radius: 8px;
  height: 230px;
  display: grid;
  place-items: center;
}
.mm-cast {
  width: 108px;
  background: #ffffff;
  border-radius: 10px;
  box-shadow: 0 8px 20px rgba(4, 23, 43, 0.15);
  padding: 10px 10px 12px;
}
.mm-stand {
  width: 90px;
  height: 12px;
  background: var(--ink);
  border-radius: 0 0 8px 8px;
  margin: 0 auto;
}
.mm-base { width: 150px; height: 7px; background: var(--ink); border-radius: 999px; margin: 4px auto 0; }
.mm-phone {
  position: absolute;
  right: 8px;
  bottom: 0;
  width: 96px;
  background: var(--ink);
  border-radius: 18px;
  padding: 6px;
  box-shadow: var(--shadow-artifact);
}
.mm-phone .mm-cast { width: 100%; box-shadow: none; border-radius: 13px; }
.app-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; margin-top: 8px; }
.app-grid i { aspect-ratio: 1; border-radius: 6px; display: block; }
.mm-statusrow { height: 8px; border-radius: 4px; background: var(--mist); }
.app-c1 { background: #a8c4e8; } .app-c2 { background: #f3c9ad; }
.app-c3 { background: #bfe0c4; } .app-c4 { background: #e4d3f0; }
.app-c5 { background: #f0dfa8; } .app-c6 { background: #d4dbe6; }
.app-c7 { background: #e8b8b0; } .app-c8 { background: #c4dced; }

/* photo with a floating artifact card overlapping its corner */
.stack { position: relative; width: min(100%, 460px); }
.stack > img {
  border-radius: var(--r-card);
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}
.stack .artifact-static {
  position: absolute;
  left: -28px;
  bottom: -28px;
  width: min(80%, 330px);
  padding: 16px 20px;
}
@media (max-width: 900px) {
  .stack .artifact-static { position: static; width: 100%; margin-top: 16px; }
}

.grid { display: grid; gap: 24px; }
.grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) {
  .grid.cols-3, .grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .grid.cols-2, .grid.cols-3, .grid.cols-4 { grid-template-columns: 1fr; }
}

/* peach accent card: at most one per page */
.card-accent {
  background: var(--peach);
  color: var(--sienna);
  border-radius: var(--r-card);
  padding: 40px;
}
.card-accent h2, .card-accent h3, .card-accent p, .card-accent cite { color: var(--sienna); }
.card-accent h3 { font-size: 26px; font-weight: 450; letter-spacing: -0.23px; margin-bottom: 12px; }
.card-accent p { font-size: 18px; line-height: 1.5; }
.card-accent blockquote {
  font-family: var(--font-serif);
  font-size: clamp(20px, 2.4vw, 26px);
  line-height: 1.45;
}
.card-accent cite {
  display: block;
  margin-top: 14px;
  font-family: var(--font-sans);
  font-style: normal;
  font-size: 14px;
}
.card-accent .btn-sienna { background: var(--sienna); color: var(--peach); margin-top: 22px; }

/* numbered step rows */
.steps { display: grid; gap: 12px; margin-top: 20px; }
.step {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  background: var(--paper);
  border-radius: var(--r-small);
  padding: 16px 18px;
}
.step-num {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: var(--r-pill);
  display: grid;
  place-items: center;
  font-size: 13px;
  font-weight: 500;
  color: var(--sienna);
  background: var(--peach);
}
.step h4 { font-size: 15px; font-weight: 500; margin-bottom: 3px; }
.step p { font-size: 14.5px; color: var(--slate); line-height: 1.45; }

/* split section */
.split {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: 64px;
  align-items: center;
}
.split.flip { grid-template-columns: 0.95fr 1.05fr; }
.split-visual { display: flex; justify-content: center; }
@media (max-width: 900px) {
  .split, .split.flip { grid-template-columns: 1fr; gap: 36px; }
}

/* ---------- team ---------- */
.team-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
@media (max-width: 1000px) { .team-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 760px) { .team-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .team-grid { grid-template-columns: 1fr; } }
.member { background: var(--mist); border-radius: var(--r-card); overflow: hidden; }
.member img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: var(--r-img); }
.member-body { padding: 18px 20px 20px; }
.member-role { font-size: 14px; color: var(--ash); margin-bottom: 4px; }
.member-name { font-family: var(--font-serif); font-size: 22px; font-weight: 400; letter-spacing: -0.01em; }
.member-bio { margin-top: 8px; font-size: 14.5px; color: var(--slate); line-height: 1.5; }
.member-links { margin-top: 10px; }
.member-links a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  color: var(--ink);
  text-decoration: none;
}
.member-links a:hover { text-decoration: underline; }

/* ---------- country list ---------- */
.continents { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
@media (max-width: 900px) { .continents { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .continents { grid-template-columns: 1fr; } }
.continent { background: var(--mist); border-radius: var(--r-card); padding: 28px 24px; }
.continent h3 {
  font-family: var(--font-serif);
  font-size: 24px;
  font-weight: 400;
  padding-bottom: 14px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--hairline);
}
.continent ul { list-style: none; display: grid; gap: 8px; }
.continent li { font-size: 15px; color: var(--ink); }

/* ---------- forms ---------- */
.form-panel {
  max-width: 560px;
  margin: 0 auto;
  background: var(--paper);
  border-radius: var(--r-card);
  padding: 36px 32px;
  box-shadow: var(--shadow-artifact);
}
.form-grid { display: grid; gap: 16px; }
.form-grid .row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 520px) { .form-grid .row2 { grid-template-columns: 1fr; } }
label { font-size: 14px; color: var(--slate); display: block; margin-bottom: 6px; }
input, select, textarea {
  width: 100%;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-input);
  padding: 14px 16px;
  font-family: var(--font-sans);
  font-size: 16px;
  color: var(--ink);
}
input::placeholder, textarea::placeholder { color: var(--smoke); }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--ink); }
select { appearance: none; }
.form-note { font-size: 15px; color: var(--slate); text-align: center; margin-top: 14px; }

/* ---------- CTA banner ---------- */
.cta-banner {
  position: relative;
  overflow: hidden;
  text-align: center;
  border-radius: var(--r-card);
  padding: 72px 32px;
  background: var(--mist);
}
.cta-banner h2 { margin-bottom: 14px; }
.cta-banner p { color: var(--slate); max-width: 560px; margin: 0 auto 30px; line-height: 1.5; }
.cta-banner .hero-cta { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* ---------- footer ---------- */
footer { background: var(--fog); padding: 64px 0 40px; margin-top: 80px; }
.foot-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 40px;
  margin-bottom: 48px;
}
@media (max-width: 760px) { .foot-grid { grid-template-columns: 1fr; gap: 32px; } }
.foot-brand p { margin-top: 16px; font-size: 15px; color: var(--slate); max-width: 340px; line-height: 1.5; }
.foot-col h4 { font-size: 14px; font-weight: 400; color: var(--ash); margin-bottom: 14px; }
.foot-col a { display: block; color: var(--ink); text-decoration: none; font-size: 15px; padding: 5px 0; }
.foot-col a:hover { text-decoration: underline; }
.foot-base {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  border-top: 1px solid var(--hairline);
  padding-top: 26px;
  font-size: 14px;
  color: var(--slate);
}
.socials { display: flex; gap: 10px; }
.socials a {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid var(--hairline);
  border-radius: var(--r-pill);
  color: var(--slate);
  transition: color 150ms, border-color 150ms;
}
.socials a:hover { color: var(--ink); border-color: var(--ink); }
.socials svg { width: 15px; height: 15px; fill: currentColor; }

/* ---------- reveal on scroll (staggered) ---------- */
.reveal {
  opacity: 0;
  transform: translateY(22px);
  /* 420ms, not 650: with a 60ms stagger the sixth sibling in a row already
     lands 300ms after the first, and 650 left the row still settling most of a
     second after it came into view. */
  transition:
    opacity 420ms var(--ease-out),
    transform 420ms var(--ease-out);
  transition-delay: var(--rd, 0ms);
}
.reveal.in { opacity: 1; transform: none; }

/* ---------- hero motion ---------- */
@keyframes jdf-drift { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
.hero .artifact, .hero .composer, .hero .av-bubble { animation: jdf-drift 7s ease-in-out infinite; }
.hero .artifact-tr { animation-delay: 1.4s; }
.hero .artifact-bl { animation-delay: 2.6s; }
.hero .composer { animation-delay: 0.8s; }
.hero .av-bubble { animation-delay: 2s; }
/* room for the artifacts to dock into a row beneath the hero copy */
@media (min-width: 1201px) { .hero { padding-bottom: 380px; } }

.hero-grain { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; }

/* scroll cue */
.scroll-cue {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin-top: 48px;
  color: var(--slate);
  font-size: 12.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  transition: opacity 400ms ease, transform 400ms ease;
}
.scroll-cue-track {
  display: block;
  width: 22px;
  height: 34px;
  border: 1.5px solid rgba(44, 74, 115, 0.35);
  border-radius: 12px;
  position: relative;
}
.scroll-cue-dot {
  position: absolute;
  left: 50%;
  top: 6px;
  width: 4px;
  height: 7px;
  margin-left: -2px;
  border-radius: 3px;
  background: var(--bar-blue);
  animation: jdf-cue 2s ease-in-out infinite;
}
@keyframes jdf-cue {
  0%, 20% { transform: translateY(0); opacity: 1; }
  60% { transform: translateY(12px); opacity: 0; }
  61% { transform: translateY(-4px); opacity: 0; }
  80%, 100% { transform: translateY(0); opacity: 1; }
}
.scroll-cue.gone { opacity: 0; transform: translateY(8px); pointer-events: none; }

/* ---------- animated line-art illustrations ---------- */
@keyframes il-buzz {
  0%, 74%, 100% { transform: translateX(0); }
  76% { transform: translateX(-1.4px); } 78% { transform: translateX(1.4px); }
  80% { transform: translateX(-1.2px); } 82% { transform: translateX(1.2px); }
  84% { transform: translateX(-0.7px); } 86% { transform: translateX(0.7px); }
  88% { transform: translateX(0); }
}
@keyframes il-wave {
  0%, 68% { opacity: 0.25; transform: scale(0.96); }
  78%, 88% { opacity: 1; transform: scale(1.05); }
  100% { opacity: 0.25; transform: scale(0.96); }
}
.il-phone { animation: il-buzz 4.5s ease-in-out infinite; }
.il-wave { transform-origin: 145px 46px; animation: il-wave 4.5s ease-in-out infinite; }
.il-wave-r { animation-delay: 0.12s; }

/* remote session: a packet runs console-ward to device, then the pointer it is
   carrying moves on the handset. The two are one 4.5s story sharing the phone's
   buzz cycle, so the device reacts to the link rather than idling beside it. */
@keyframes il-packet {
  0%, 4% { transform: translateX(0); opacity: 0; }
  8% { opacity: 1; }
  30% { transform: translateX(34px); opacity: 1; }
  36%, 100% { transform: translateX(34px); opacity: 0; }
}
.il-packet { animation: il-packet 4.5s ease-in-out infinite; }
@keyframes il-cursor {
  0%, 34% { transform: translate(140px, 58px); }
  52%, 62% { transform: translate(133px, 34px); }
  80%, 100% { transform: translate(146px, 46px); }
}
/* the declared transform is the resting pose, so killing the animation under
   reduced motion leaves the pointer on the handset instead of at the SVG origin */
.il-cursor {
  transform: translate(146px, 46px);
  animation: il-cursor 4.5s ease-in-out infinite;
}
@keyframes il-con-line {
  0%, 40% { opacity: 0.45; }
  60%, 100% { opacity: 0.18; }
}
.il-con-line { animation: il-con-line 4.5s ease-in-out infinite; }

/* the team collage: 18 silhouettes on offsets spread across one long cycle, so
   different faces come forward and the group reads as populated rather than as
   a fixed grid of six. Opacity only, and the offsets are wide (not a 30-80ms
   entrance stagger) because this is ambient, not an entrance. */
@keyframes il-face-breathe {
  0%, 100% { opacity: 0.42; }
  50% { opacity: 1; }
}
.il-faces use { animation: il-face-breathe 6s ease-in-out infinite; }
.il-faces use:nth-child(3n + 2) { animation-delay: 0.9s; }
.il-faces use:nth-child(3n + 3) { animation-delay: 1.8s; }
.il-faces use:nth-child(6n + 4) { animation-delay: 2.7s; }
.il-faces use:nth-child(6n + 5) { animation-delay: 3.6s; }
.il-faces use:nth-child(7n + 6) { animation-delay: 4.5s; }

/* operator wall: wordmarks, not logo artwork. Chips are sized so an official
   SVG can replace the text later without the grid reflowing. */
.illus-operators { width: 100%; }
.mno-wall {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}
.mno {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding: 0 12px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--mno, var(--ink));
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: -0.005em;
  white-space: nowrap;
}
.mno-more { color: var(--slate); font-weight: 400; background: transparent; }

/* ---------- console mockup (fleet window) ---------- */
.console {
  position: relative;
  width: min(760px, 100%);
  background: var(--paper);
  border-radius: 16px;
  box-shadow: var(--shadow-artifact);
}
.console-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--hairline);
}
.console-bar i { width: 11px; height: 11px; border-radius: 50%; display: inline-block; }
.console-bar .c-red { background: #f6605c; }
.console-bar .c-amber { background: #fbbc3e; }
.console-bar .c-green { background: #3ec24e; }
.console-bar span { margin-left: 10px; font-size: 13px; color: var(--slate); }
.console-body { display: grid; grid-template-columns: 1fr 230px; min-height: 340px; }
.console-list { padding: 18px 20px; }
.console-list .c-label { font-size: 13px; color: var(--ash); margin-bottom: 10px; }
.console-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 12px;
  border-radius: 10px;
  font-size: 14.5px;
}
.console-row .dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; background: #8fe3a4; }
.console-row .dot.off { background: #d4dbe6; }
.console-row .name { flex: 1; }
.console-row .op { color: var(--ash); font-size: 13px; }
@keyframes jdf-cur {
  0%, 6% { transform: translate(0px, 44px); }
  14% { transform: translate(437px, -49px); }
  16.5% { transform: translate(437px, -49px) scale(0.8); }
  19%, 46% { transform: translate(437px, -49px); }
  54% { transform: translate(0px, 0px); }
  56.5% { transform: translate(0px, 0px) scale(0.8); }
  59%, 62% { transform: translate(0px, 0px); }
  70% { transform: translate(437px, -49px); }
  72.5% { transform: translate(437px, -49px) scale(0.8); }
  75%, 92% { transform: translate(437px, -49px); }
  98% { transform: translate(0px, 44px); }
  99% { transform: translate(0px, 44px) scale(0.8); }
  100% { transform: translate(0px, 44px); }
}
@keyframes jdf-row-sn { 0%, 54% { background: transparent; } 57%, 96% { background: var(--tint-blue); } 100% { background: transparent; } }
@keyframes jdf-row-br { 0%, 52% { background: var(--tint-blue); } 56%, 98% { background: transparent; } 100% { background: var(--tint-blue); } }
@keyframes jdf-ico {
  0%, 15% { transform: scale(1); box-shadow: none; }
  16.5% { transform: scale(0.82); box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.55); }
  19%, 71% { transform: scale(1); box-shadow: none; }
  72.5% { transform: scale(0.82); box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.55); }
  75%, 100% { transform: scale(1); box-shadow: none; }
}
@keyframes jdf-app {
  0%, 17% { opacity: 0; transform: scale(0.4); }
  21%, 50% { opacity: 1; transform: scale(1); }
  54%, 73% { opacity: 0; transform: scale(0.4); }
  77%, 96% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(0.4); }
}
@keyframes jdf-loc-sn { 0%, 56% { opacity: 0; } 58%, 98.5% { opacity: 1; } 100% { opacity: 0; } }
@keyframes jdf-loc-br { 0%, 56% { opacity: 1; } 58%, 98.5% { opacity: 0; } 100% { opacity: 1; } }
.jdf-cur {
  position: absolute;
  left: 210px;
  top: 143px;
  width: 20px;
  height: 20px;
  z-index: 3;
  fill: var(--ink);
  stroke: #fff;
  stroke-width: 1;
  transform-origin: 2px 2px;
  animation: jdf-cur 16s cubic-bezier(0.45, 0, 0.25, 1) infinite;
}
.jdf-row-sn { animation: jdf-row-sn 16s infinite; }
.jdf-row-br { animation: jdf-row-br 16s infinite; }
.jdf-ico { animation: jdf-ico 16s infinite; }
.jdf-app { animation: jdf-app 16s cubic-bezier(0.3, 1.2, 0.4, 1) infinite; transform-origin: 50% 30%; }
.jdf-loc-sn { animation: jdf-loc-sn 16s infinite; }
.jdf-loc-br { animation: jdf-loc-br 16s infinite; }
/* the phone that pops out of the console */
.console-phone {
  position: absolute;
  right: 32px;
  top: 16px;
  width: 158px;
  background: var(--ink);
  border-radius: 28px;
  padding: 7px;
  box-shadow: 0 0 0 1px rgba(4, 23, 43, 0.05), 0 20px 25px -5px rgba(0, 0, 0, 0.18), 0 8px 10px -6px rgba(0, 0, 0, 0.12);
  z-index: 2;
}
.cp-screen {
  position: relative;
  background: linear-gradient(160deg, #dce9f7, #f3e7dc);
  border-radius: 22px;
  overflow: hidden;
  height: 318px;
}
.cp-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 7px 12px 0;
  font-size: 9px;
  color: #3a4356;
}
.cp-loc { position: relative; height: 13px; margin-top: 8px; }
.cp-loc > div { position: absolute; inset: 0; text-align: center; font-size: 9.5px; color: #3a4356; }
.cp-apps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px 6px;
  padding: 18px 14px 0;
  justify-items: center;
}
.cp-app { display: grid; justify-items: center; gap: 3px; }
.cp-app i { width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center; }
.cp-app i svg { width: 14px; height: 14px; fill: none; stroke: #fff; stroke-width: 2; }
.cp-app span { font-size: 7.5px; color: #3a4356; }
.cp-home {
  position: absolute;
  left: 50%;
  bottom: 6px;
  transform: translateX(-50%);
  width: 52px;
  height: 4px;
  border-radius: 2px;
  background: rgba(58, 67, 86, 0.35);
}
.cp-msg { position: absolute; inset: 0; background: var(--paper); border-radius: 19px; overflow: hidden; }
.cp-msg-bar {
  background: var(--bar-blue);
  color: #fff;
  font-size: 10px;
  font-weight: 500;
  padding: 9px 11px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.cp-msg-list { padding: 10px 9px; display: grid; gap: 7px; }
.cp-msg-list .in {
  justify-self: start;
  max-width: 78%;
  background: #eef1f5;
  border-radius: 10px 10px 10px 3px;
  padding: 6px 8px;
  font-size: 8.5px;
  color: #3a4356;
}
.cp-msg-list .out {
  justify-self: end;
  max-width: 78%;
  background: var(--bar-blue);
  border-radius: 10px 10px 3px 10px;
  padding: 6px 8px;
  font-size: 8.5px;
  color: #fff;
}
@media (max-width: 760px) {
  .console-body { grid-template-columns: 1fr; min-height: 0; }
  .console-phone { display: none; }
  .jdf-cur { display: none; }
}

/* ---------- phone mock: typing + connection ---------- */
.phone-mock { animation: jdf-drift 8s ease-in-out infinite; }
.pm-screen { position: relative; }
/* typewriter without animating layout: the text is a fixed-width box revealed
   with clip-path, and the caret rides along on a transform */
@keyframes jdf-type {
  0%, 10% { clip-path: inset(0 100% 0 0); }
  30%, 88% { clip-path: inset(0 0 0 0); }
  92%, 100% { clip-path: inset(0 100% 0 0); }
}
@keyframes jdf-caret-move {
  0%, 10% { transform: translateX(-64px); }
  30%, 88% { transform: translateX(0); }
  92%, 100% { transform: translateX(-64px); }
}
@keyframes jdf-caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes jdf-press {
  0%, 31% { transform: scale(1); }
  33% { transform: scale(0.95); filter: brightness(0.88); }
  35%, 100% { transform: scale(1); }
}
@keyframes jdf-conn {
  0%, 35% { opacity: 0; transform: translateY(14px); }
  40%, 84% { opacity: 1; transform: none; }
  90%, 100% { opacity: 0; transform: translateY(14px); }
}
@keyframes jdf-bar { 0%, 100% { transform: scaleY(0.35); } 50% { transform: scaleY(1); } }
@keyframes jdf-ph { 0%, 10% { opacity: 1; } 13%, 88% { opacity: 0; } 92%, 100% { opacity: 1; } }
.pm-type {
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  vertical-align: bottom;
  width: 64px;
  clip-path: inset(0 100% 0 0);
  animation: jdf-type 10s steps(8, end) infinite;
  color: var(--ink);
}
.pm-caret {
  display: inline-block;
  width: 1px;
  height: 12px;
  background: var(--ink);
  vertical-align: -1px;
  animation: jdf-caret 1s infinite, jdf-caret-move 10s steps(8, end) infinite;
}
.pm-press { animation: jdf-press 10s infinite; }
.pm-ph { color: var(--smoke); animation: jdf-ph 10s infinite; }
.pm-conn {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 34px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 11px 12px;
  box-shadow: 0 8px 18px -8px rgba(4, 23, 43, 0.25);
  animation: jdf-conn 10s infinite;
}
.pm-conn .conn-head {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 500;
  color: var(--ink);
}
.pm-conn .conn-head .dot { width: 7px; height: 7px; border-radius: 50%; background: #3ec24e; display: inline-block; }
.pm-conn .conn-head .ms { margin-left: auto; font-weight: 400; color: var(--slate); font-size: 11px; }
.pm-conn .bars { display: flex; gap: 3px; align-items: flex-end; height: 18px; margin-top: 8px; }
.pm-conn .bars span {
  width: 6px;
  border-radius: 2px;
  background: var(--bar-blue);
  height: 100%;
  transform-origin: bottom;
  animation: jdf-bar 1.1s ease-in-out infinite;
}
.pm-conn .bars span:nth-child(2) { animation-delay: 0.15s; }
.pm-conn .bars span:nth-child(3) { animation-delay: 0.3s; }
.pm-conn .bars span:nth-child(4) { animation-delay: 0.45s; }
.pm-conn .bars span:nth-child(5) { animation-delay: 0.6s; }
.pm-conn .bars span:nth-child(6) { animation-delay: 0.75s; }
.pm-conn .bars span:nth-child(7) { animation-delay: 0.9s; }
.pm-conn .conn-note { font-size: 10.5px; color: var(--slate); margin-top: 7px; }

/* step numbers pulse in sequence */
.step .step-num { --step-bg: var(--peach); animation: jdf-stepglow 9.6s infinite; }
@keyframes jdf-stepglow {
  0%, 14%, 100% { transform: none; background: var(--step-bg); color: var(--sienna); }
  5% { transform: scale(1.18); background: var(--bar-blue); color: #ffffff; }
}
.steps-row .step:nth-child(2) .step-num { animation-delay: 1.6s; }
.steps-row .step:nth-child(3) .step-num { animation-delay: 3.2s; }
.steps-row .step:nth-child(4) .step-num { animation-delay: 4.8s; }
.steps-row .step:nth-child(5) .step-num { animation-delay: 6.4s; }
.steps-row .step:nth-child(6) .step-num { animation-delay: 8s; }

/* ---------- service card visualisations ---------- */
/* travel is expressed as a transform (GPU) rather than animating `left`.
   The bar is 14% of the track and crosses 122% of it, hence 122/14 = 871%. */
@keyframes jdf-scan { 0% { transform: translateX(0); } 100% { transform: translateX(871%); } }
.svc-viz {
  position: relative;
  height: 56px;
  border-radius: 10px;
  background: rgba(68, 119, 173, 0.06);
  margin-bottom: 16px;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  gap: 4px;
  padding: 10px 12px;
}
.svc-viz .b { flex: 1; border-radius: 2px 2px 0 0; background: #c8d8ea; }
.svc-viz .scanline {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 14%;
  left: -18%;
  background: linear-gradient(90deg, transparent, rgba(68, 119, 173, 0.28), transparent);
  animation: jdf-scan 3.4s linear infinite;
}
/* the packet rides an offset-path (composited) instead of animating `left`.
   The track is a zero-height inset rect, so 0%->50% runs left to right and
   50%->100% returns, giving the out-and-back hop. */
@keyframes jdf-hop {
  0%, 4% { offset-distance: 0%; opacity: 0; }
  8% { opacity: 1; }
  44%, 56% { offset-distance: 50%; }
  92% { opacity: 1; }
  96%, 100% { offset-distance: 100%; opacity: 0; }
}
.svc-route {
  position: relative;
  height: 56px;
  border-radius: 10px;
  background: rgba(68, 119, 173, 0.06);
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 18px;
  font-size: 10.5px;
  color: var(--slate);
}
.svc-route .node { display: grid; justify-items: center; gap: 4px; }
.svc-route .node i { width: 9px; height: 9px; border-radius: 50%; background: #c8d8ea; font-style: normal; }
.svc-route .node:nth-child(2) i { background: var(--bar-blue); }
.svc-route .pkt { position: absolute; left: 24px; right: 24px; top: 19px; height: 0; }
.svc-route .pkt s {
  position: absolute;
  width: 7px;
  height: 7px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--bar-blue);
  text-decoration: none;
  offset-path: inset(0 0 0 0);
  offset-rotate: 0deg;
  animation: jdf-hop 4s ease-in-out infinite;
}
/* The dot pulse used to expand a box-shadow ring, which repaints on every frame
   of an infinite loop. The ring is now a pseudo-element that scales and fades,
   so both halves of the pulse are transform + opacity and stay off the paint
   path. Same look, no per-frame paint. */
@keyframes jdf-ping {
  0%, 70%, 100% { transform: scale(1); }
  8% { transform: scale(1.5); }
}
@keyframes jdf-ping-ring {
  0% { transform: scale(1); opacity: 1; }
  30%, 100% { transform: scale(3.5); opacity: 0; }
}
.svc-map {
  position: relative;
  height: 56px;
  border-radius: 10px;
  background: rgba(68, 119, 173, 0.06);
  margin-bottom: 16px;
  overflow: hidden;
}
.svc-map i {
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--bar-blue);
  animation: jdf-ping 5.6s infinite;
}
.svc-map i::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: rgba(68, 119, 173, 0.4);
  animation: jdf-ping-ring 5.6s infinite;
}

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
  .hero .artifact, .hero .composer, .hero .av-bubble,
  .scroll-cue-dot, .il-phone, .il-wave,
  .il-packet, .il-cursor, .il-con-line, .il-faces use,
  .phone-mock, .pm-type, .pm-caret, .pm-press, .pm-conn, .pm-conn .bars span,
  .step .step-num, .pm-ph, .svc-viz .scanline, .svc-route .pkt s,
  .svc-map i, .svc-map i::after { animation: none; }
  .svc-map i::after { opacity: 0; }
  /* the packet only means anything while it travels; at rest it is a stray dot */
  .il-packet { opacity: 0; }
  .scroll-cue { transition: opacity 400ms ease; }
  /* keep the fade, drop the movement */
  .composer > :not([hidden]) { animation: composer-fade-in 200ms ease both; }
  @keyframes composer-fade-in { from { opacity: 0; } }
  .jdf-cur { display: none; }
  .jdf-row-sn { background: var(--tint-blue); animation: none; }
  .jdf-row-br, .jdf-ico { animation: none; }
  .jdf-app { animation: none; opacity: 0; }
  .jdf-loc-sn { animation: none; opacity: 1; }
  .jdf-loc-br { animation: none; opacity: 0; }
  .pm-conn { opacity: 1; transform: none; }
  .pm-type { clip-path: inset(0 0 0 0); }
  .pm-caret { transform: none; }
  .pm-ph { opacity: 0; }
  /* hold a single wordmark rather than cycling it */
  .brand-name > span { animation: none; }
  .brand-name > span + span { opacity: 0; }
  .svc-route .pkt s { offset-distance: 50%; opacity: 1; }
}
