/* MPN DigiTech — landing page redesign
   Pinned direction: melius.com structure/motion, translated to MPN tokens.
   Loads after site.css; overrides scoped to body.landing. Reference:
   .impeccable/surfaces/index-html.md "Direction contract — index.html". */

body.landing {
  background: var(--color-bg);
  background-image:
    radial-gradient(rgba(22, 34, 68, 0.38) 1.2px, transparent 1.2px),
    radial-gradient(rgba(22, 34, 68, 0.38) 1.2px, transparent 1.2px);
  background-size: 48px 48px, 48px 48px;
  background-position: 0 0, 24px 24px;
  position: relative;
}

/* Film-grain texture: fixed, full-viewport, extremely low-opacity noise
   blended over every section (light and dark). One authored device, not
   a shadow/glow substitute -- the flat, no-shadow surface rule elsewhere
   in the system is untouched by this. */
.landing::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.landing .serif {
  font-family: "Fraunces", var(--font-display), serif;
  font-weight: 500;
  letter-spacing: -0.01em;
}
.landing .serif-italic {
  font-family: "Fraunces", var(--font-display), serif;
  font-style: italic;
  font-weight: 400;
  color: var(--color-accent);
}

/* ---------- floating rounded nav ---------- */
.landing .site-header {
  background: transparent;
  backdrop-filter: none;
  border-bottom: none;
  padding-top: 14px;
}
.landing .nav-inner {
  /* Explicit, guaranteed containing block for the absolutely-positioned
     mobile .nav-links dropdown below -- without it, browsers that don't
     treat backdrop-filter as containment (Safari/iOS) position .nav-links
     against .site-header's full un-rounded width instead of this pill,
     letting its collapsed-state edges bleed past the pill's rounded
     corners on the sides Chrome never showed. */
  position: relative;
  max-width: none;
  margin-inline: 16px;
  padding-inline: var(--space-6);
  border-radius: 16px;
  background: rgba(22, 34, 68, 0.94);
  backdrop-filter: saturate(140%) blur(12px);
  -webkit-backdrop-filter: saturate(140%) blur(12px);
  box-shadow: 0 10px 30px rgba(6, 12, 28, 0.28);
  transition: background-color var(--transition-base), box-shadow var(--transition-base);
  /* iOS Safari renders backdrop-filter as an unrounded rectangle under the
     border-radius clip, so the blur pokes out past the curve as a hairline
     matching the pill's own width -- invisible in Chrome, which clips it
     correctly. overflow:hidden forces Safari to clip it too. Only while the
     mobile dropdown (a child of this same element) is closed, though --
     otherwise this would clip the open dropdown along with the bug. */
  overflow: hidden;
}
.landing .nav-inner:has(.nav-toggle:checked) {
  overflow: visible;
}
/* Adaptive nav: the floating pill flips light when it's sitting over one
   of this page's dark sections, so it never blends into the background
   behind it. Toggled by assets/landing.js reading each section's
   data-bg attribute under the pill. */
.landing .nav-inner.is-on-dark {
  background: rgba(245, 247, 250, 0.94);
  box-shadow: 0 10px 24px rgba(6, 12, 28, 0.14);
}
.landing .nav-inner.is-on-dark .nav-links a { color: var(--color-text-muted); }
.landing .nav-inner.is-on-dark .nav-links a[aria-current="page"] { color: var(--color-primary); }
.landing .nav-inner.is-on-dark .nav-toggle-label {
  border-color: var(--color-border);
  color: var(--color-primary);
} /* Same invisible-icon bug as the logo swap this pill already handles --
     .nav-toggle-label's light-on-dark color (added for the pill's default
     navy state) was never given an is-on-dark counterpart, so the
     hamburger disappeared the instant the pill flipped to its light
     background over a dark section. */
@media (min-width: 861px) {
  .landing .nav-inner { margin-inline: 24px; }
}
@media (min-width: 861px) {
  .landing .nav-links a {
    position: relative;
    color: var(--color-navy-tint);
    border-bottom-color: transparent;
  }
  .landing .nav-links a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 100%;
    bottom: -1.5px;
    height: 1.5px;
    background: var(--color-accent);
    transition: right var(--transition-base);
  }
  .landing .nav-links a:hover::after { right: 0; }
  .landing .nav-links a[aria-current="page"]::after { right: 0; }
}
.landing .nav-links a { color: var(--color-navy-tint); }
.landing .nav-links a[aria-current="page"] { color: #fff; }
.landing .nav-toggle-label {
  border-color: rgba(255, 255, 255, 0.3);
  color: var(--color-navy-tint);
} /* .nav-toggle-label has no color of its own, so its icon (stroke:
     currentColor) was inheriting the page's default dark-navy text color
     -- invisible against this header's own dark navy pill. Same fix
     already applied to .header-floating for pricing.html/about.html. */
@media (max-width: 860px) {
  .landing .nav-links { background: var(--color-surface-dark); }
  .landing .nav-links a { border-bottom-color: rgba(255,255,255,0.1); }
  /* The dropdown panel's own background never followed is-on-dark the way
     its link color already did -- scrolling to a dark section (flipping
     the pill light) then opening the mobile menu left dark link text
     (color: var(--color-text-muted)/var(--color-primary), added for a
     light panel) sitting on this still-hardcoded dark panel. Worst case,
     the current-page link and the panel background were the identical
     colour: 1:1 contrast, fully invisible. Flip the panel itself too. */
  .landing .nav-inner.is-on-dark .nav-links { background: var(--color-surface); }
  .landing .nav-inner.is-on-dark .nav-links a { border-bottom-color: var(--color-border); }
  /* At this width the pill is only inset 16px from the viewport edge, so its
     30px-blur box-shadow spreads past the rounded corners and reads as a
     stray line under the header rather than a floating shadow. Covers both
     pill states -- .is-on-dark carries its own, more specific box-shadow. */
  .landing .nav-inner,
  .landing .nav-inner.is-on-dark { box-shadow: none; }
}

/* ================= HERO ================= */
/* Fits within the first viewport (below the floating nav) on desktop, no
   vertical clipping -- only the photo fan's horizontal bleed is clipped. */
.l-hero {
  position: relative;
  min-height: calc(100svh - 78px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(6px, 0.7vw, 9px);
  padding-block: clamp(4px, 0.7vw, 8px);
  overflow-x: clip;
  overflow-y: visible;
}
.l-hero-inner {
  text-align: center;
  max-width: 900px;
  margin-inline: auto;
}
.l-hero-headline-row {
  /* Centers the headline within the band between the floating nav and the
     photo fan, rather than letting it hug the top of that gap. */
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: clamp(60px, 6.3vw, 90px);
}
.l-hero-headline {
  display: inline-block;
  max-width: min(760px, 92vw);
  margin-inline: auto;
  font-family: "Fraunces", var(--font-display), serif;
  font-weight: 500;
  font-size: clamp(1.75rem, 5.2vw, 3.75rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--color-primary);
  white-space: nowrap;
}
.l-cycle {
  display: inline-block;
  color: var(--color-accent);
  min-width: 1ch;
}
.l-hero-sub-wrap {
  display: inline-block;
  margin: 0 auto;
  padding: 10px 20px;
  background: var(--color-bg);
  border-radius: var(--radius-md);
}
.l-hero-sub {
  margin: 0 auto;
  max-width: 58ch;
  font-size: 1.0625rem;
  color: var(--color-text);
}
.l-hero-sub-second {
  margin-top: var(--space-1);
}

.l-intake {
  margin: var(--space-3) auto 0;
  max-width: 560px;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  background: var(--color-surface-dark);
  color: #fff;
  border-radius: var(--radius-lg);
  padding: 12px 12px 12px 18px;
  box-shadow: 0 20px 40px rgba(6, 12, 28, 0.18);
  text-decoration: none;
  border: 1px solid transparent;
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
  transform: translateY(12px); /* half a dot-grid space down, without
                        shifting the icon row that follows */
}
.l-intake:hover {
  border-color: var(--color-accent);
  box-shadow: 0 20px 40px rgba(6, 12, 28, 0.24);
}
.l-intake svg { flex: none; color: var(--color-navy-soft); }
.l-intake-text {
  flex: 1;
  /* Hard height (not min-height) plus min-width:0 on a nowrap flex child --
     without min-width:0, a flex item won't shrink below its own text's
     unwrapped intrinsic width, so a longer cycling prompt could still push
     .l-intake wider/taller even with overflow:hidden visually clipping it.
     Locking both dimensions here guarantees the pill never reflows the
     page as the prompts type in and out. */
  min-width: 0;
  height: 1.3em;
  text-align: left;
  font-size: 0.9375rem;
  color: var(--color-navy-tint);
  white-space: nowrap;
  overflow: hidden;
}
.l-intake-text .caret {
  display: inline-block;
  width: 1px;
  background: var(--color-accent-on-dark);
  margin-left: 1px;
  animation: l-blink 1s step-end infinite;
}
@keyframes l-blink { 50% { opacity: 0; } }
.l-intake-btn {
  flex: none;
  width: 40px; height: 40px;
  border-radius: 50%;
  border: none;
  background: var(--color-accent);
  color: #fff;
  display: grid;
  place-items: center;
  cursor: default;
}

/* fan-out placeholder deck: 10 cards, 5 each side of center, largest and
   least-overlapped near the middle, progressively smaller and more
   overlapped toward the edges -- --fi (0-9) set inline per card, every
   other value derived here from it. */
.l-fan {
  position: relative;
  width: 100%;
  height: clamp(150px, 16vw, 245px);
  margin-top: -24px; /* one dot-grid space, pulls the photos (and the
                        paragraph that follows with them) up toward the
                        headline without moving the icon row below */
  display: flex;
  align-items: center;
  justify-content: center;
}
.l-fan-card {
  /* Without this, two taps close together to zoom in then back out can
     land inside the browser's own double-tap-to-zoom timing window, which
     zooms the whole page at the same time as the tap-zoom transform below
     animates the card -- the two fights look like the card's shrink-back
     stalling partway. This tells the browser taps here are for this
     element's own UI, not a page-zoom gesture. */
  touch-action: manipulation;
  --off: calc(var(--fi) - 3);           /* -3 .. 3, signed (7 cards) */
  --ao: max(var(--off), calc(var(--off) * -1)); /* absolute value */
  --spacing: 12.5vw;    /* tight enough that neighbours overlap; edge cards
                         still bleed off the true viewport edge */
  --scale: calc(0.62 + var(--ao) * 0.135);  /* biggest at the far ends,
                         smallest at the center, smooth ramp between */
  --z: calc(5 + var(--ao));                /* biggest (edge) cards stack
                         on top of the smaller center ones */

  position: absolute;
  left: 50%;
  top: 50%;
  width: clamp(175px, 21vw, 320px);
  aspect-ratio: 900 / 491;   /* matches the shipped hero photography, not
                                the old placeholder's portrait guess */
  overflow: hidden;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  z-index: var(--z);
  /* left/top:50% + translate(-50%,-50%) centers every card (regardless of
     count) on the container's true center; the off-based translateX/Y then
     fan them out symmetrically from that shared center point. */
  transform: translate(-50%, calc(-50% + 30px)) scale(0);
  opacity: 0;
  transition: transform 700ms cubic-bezier(0.16, 1, 0.3, 1), opacity 700ms ease, box-shadow var(--transition-base);
  transition-delay: calc(var(--ao) * 60ms);
  cursor: default;
}
.l-fan-card img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
@media (max-width: 860px) {
  /* Grove's and Director Cinematographer -- dropped from the mobile fan
     only; the remaining 5 stay symmetric since off = fi - 3 already
     centers on the middle card regardless of which side cards exist. */
  .l-fan-card-desktop-only { display: none; }
}
.l-fan.is-visible .l-fan-card {
  transform:
    translate(-50%, -50%)
    translateX(calc(var(--off) * var(--spacing)))
    translateY(calc((var(--ao) - 0.5) * 9px))
    rotate(calc(var(--off) * 2deg))
    scale(var(--scale));
  opacity: 1;
}
/* (hover: hover) and (pointer: fine), not a width breakpoint -- touch
   browsers simulate :hover on tap and never clear it (there's no cursor to
   leave with), so without this scope a tap here would stick in this
   enlarged state instead of returning to the fan on the second tap, which
   is exactly what the .is-zoomed toggle below is for on touch. */
@media (hover: hover) and (pointer: fine) {
  .l-fan.is-visible .l-fan-card:hover {
    transform:
      translate(-50%, -50%)
      translateX(calc(var(--off) * var(--spacing)))
      translateY(calc((var(--ao) - 0.5) * 9px))
      rotate(0deg)
      /* Fixed absolute scale (not var(--scale) * k) so every card pops up to
         the same final rendered size on hover, regardless of its resting
         scale (center cards start smaller than edge cards) or fan position --
         every .l-fan-card shares the same underlying box width, so a fixed
         scale factor alone guarantees a matching hover size across the fan. */
      scale(1.45);
    transition-delay: 0ms;
    box-shadow: 0 20px 32px rgba(22, 34, 68, 0.18);
    z-index: 20;
  }
}
/* Touch equivalent of the hover pop-out above: mobile has no hover, so a
   tap toggles the same "look closer" moment instead -- centered rather
   than expanded in place, since the fan's rotated/offset resting position
   would otherwise push a zoomed card partway off-screen. Tapping the
   zoomed card again (or tapping elsewhere) returns it to the fan. */
@media (max-width: 860px) {
  .l-fan.is-visible .l-fan-card.is-zoomed {
    /* transform-only (no width/height) so this animates on the compositor
       instead of forcing layout on every frame; 1.9x on this breakpoint's
       clamped 175px card width lands close to the same ~330px target the
       old width-based version used. */
    transform: translate(-50%, -50%) scale(1.9);
    z-index: 30;
    box-shadow: 0 20px 32px rgba(22, 34, 68, 0.3);
    transition: transform 300ms cubic-bezier(0.16, 1, 0.3, 1), box-shadow 300ms ease;
  }
}

/* ================= INDUSTRIES (cinematic horizontal showcase) =================
   Full redesign, replacing an earlier sticky-photo + build-canvas-diagram
   pattern (melius.com-inspired) that never cleared the bar for this page's
   third-most-important section. This version: a full-bleed, scroll-snapped
   horizontal rail of large photographic industry panels, each carrying a
   settle-zoom on activation and a staggered text/tag reveal, with a
   counter + progress bar + prev/next controls tracking position. No
   scroll-jacking -- native horizontal scroll/touch/trackpad drives it;
   JS only tracks which panel is nearest-active for the UI chrome. */
.l-industries {
  margin-top: clamp(48px, 10vw, 100px);
  padding-block: clamp(20px, 3vw, 36px);
  background:
    radial-gradient(720px 480px at 12% 8%, rgba(26, 100, 70, 0.24), transparent 60%),
    radial-gradient(640px 520px at 92% 92%, rgba(140, 178, 162, 0.14), transparent 65%),
    var(--color-surface-dark);
  color: #fff;
  overflow: hidden;
}
.l-industries-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-bottom: clamp(16px, 2.5vw, 28px);
}
.l-industries-head h2 { color: var(--color-navy-tint); }
.l-industries-head .lede { color: var(--color-navy-soft); max-width: 56ch; }
.l-industries-controls {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-2);
}
.l-industries-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.18);
  background: transparent;
  color: #fff;
  cursor: pointer;
  transition: background-color var(--transition-base), border-color var(--transition-base), opacity var(--transition-base);
}
.l-industries-nav:hover:not(:disabled) { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.32); }
.l-industries-nav:disabled { opacity: 0.3; cursor: default; }
/* Segmented stepper, not a single filling bar: with the numeric "01/05"
   counter gone, the segments themselves have to carry position at a
   glance -- count how many are lit, see which one is raised. The active
   segment lifts and glows on change (feedback for a state change, per
   the animate playbook); reduced motion keeps the colour change but
   drops the scale/glow. */
.l-industries-progress {
  flex: 1;
  max-width: 260px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.l-progress-seg {
  flex: 1;
  height: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  transform: scaleY(1);
  transition: background-color 350ms cubic-bezier(0.16, 1, 0.3, 1), transform 350ms cubic-bezier(0.16, 1, 0.3, 1);
}
.l-progress-seg.is-done { background: rgba(140, 178, 162, 0.5); }
.l-progress-seg.is-active {
  background: var(--color-accent);
  transform: scaleY(1.6);
}
@media (prefers-reduced-motion: reduce) {
  .l-progress-seg { transition: background-color 150ms ease; transform: none !important; }
}

.l-industries-rail {
  display: flex;
  gap: 28px;
  overflow-x: auto;
  overflow-y: hidden; /* explicit: this is a horizontal-only scroller */
  /* Tells the browser this element only claims horizontal pan gestures,
     so a vertical scroll/swipe starting over it hands off to the page
     instead of the rail trying to consume it. The standard fix for a
     horizontal-scroll-snap carousel intercepting page scroll. */
  touch-action: pan-x;
  /* proximity, not mandatory -- mandatory snap can win gesture arbitration
     on a swipe that's only mostly-vertical (not perfectly so), trapping it
     into a horizontal snap instead of handing off to the page scroll the
     touch-action above is supposed to allow. Proximity still snaps at
     rest, just without forcing every ambiguous touch into this rail. */
  scroll-snap-type: x proximity;
  scroll-padding-left: max(24px, calc((100vw - 1180px) / 2 + 24px));
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 4px;
  padding-left: max(24px, calc((100vw - 1180px) / 2 + 24px));
  padding-right: max(24px, calc((100vw - 1180px) / 2 + 24px));
}
.l-industries-rail::-webkit-scrollbar { display: none; }
.l-industries-rail:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 4px; }

.l-industry-panel {
  position: relative;
  flex: none;
  height: min(58vh, 580px);
  width: auto;
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-lg);
  overflow: hidden;
  scroll-snap-align: start;
  background: var(--color-surface-dark-2);
  box-shadow: 0 32px 64px -24px rgba(6, 12, 28, 0.55);
}
.l-industry-panel img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Long-press on an <img> can start a native drag/save-image gesture on
     mobile, which competes with a vertical swipe for the same touch --
     another source of the rail swallowing a scroll that should have
     passed through to the page. */
  -webkit-user-drag: none;
  user-select: none;
  transform: scale(1.045);
  filter: saturate(0.9) brightness(0.9);
  transition: transform 700ms cubic-bezier(0.16, 1, 0.3, 1), filter 700ms cubic-bezier(0.16, 1, 0.3, 1);
}
.l-industry-panel.is-active img { transform: scale(1); filter: saturate(1) brightness(1); }
.l-industry-scrim {
  position: absolute;
  inset: 0;
  /* The dark zone is concentrated in the bottom third where the caption
     actually sits -- verified to keep the mono eyebrow and muted lede
     (both under the 18px/700 large-text threshold, so both need the
     full 4.5:1) above WCAG AA even over the brightest photos (retail,
     services have near-white walls filling most of the frame) -- and
     fades out well before the photo's midpoint so most of each picture
     reads at full brightness instead of being shaded top to bottom. A
     text-shadow on those two elements below is the
     second line of defence for any high-frequency detail the gradient
     alone doesn't fully tame. */
  background: linear-gradient(to top, rgba(8, 12, 24, 0.94) 0%, rgba(8, 12, 24, 0.85) 38%, rgba(8, 12, 24, 0.16) 55%, rgba(8, 12, 24, 0) 66%);
}
.l-industry-copy {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  /* var(--space-5) doesn't exist in the token scale -- that made this
     whole shorthand invalid, so the block had no padding at all beyond
     each child's own margin, leaving "Go live" sitting almost flush
     against the bottom edge. Fixed with real tokens, bottom generous
     enough to lift the tags row clear of the edge. */
  padding: var(--space-8) var(--space-6) var(--space-8);
  text-align: center;
}
.l-industry-eyebrow {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--color-accent-on-dark);
  margin-bottom: var(--space-2);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}
.l-industry-copy h3 {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1.8vw, 1.5rem);
  font-weight: 500;
  color: #fff;
  margin: 0 0 var(--space-2);
}
.l-industry-copy p {
  font-size: 0.875rem;
  color: var(--color-navy-soft);
  max-width: 30ch;
  margin: 0 auto var(--space-4);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}
.l-industry-tags {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.l-industry-tags li {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  border-radius: 999px;
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.16);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-size: 0.6875rem;
  font-weight: 500;
  color: #fff;
  white-space: nowrap;
}
.l-industry-tags li svg { flex: none; color: var(--color-accent-on-dark); }
.l-industry-tags li.is-live { background: rgba(26,100,70,0.35); border-color: var(--color-accent-on-dark); }
.l-industry-tags li.is-live svg { color: #fff; }
/* Forces the wrap after the 3rd tag regardless of text length or panel
   width, so "Go live" always lands alone on its own row instead of
   wrapping unpredictably (2+2, 3+1, etc.) as tag-label lengths vary. */
.l-industry-tags li.l-tag-break {
  flex-basis: 100%;
  width: 0;
  height: 0;
  padding: 0;
  margin: 0;
  border: none;
  background: none;
}

@media (prefers-reduced-motion: reduce) {
  .l-industry-panel img { transition: none !important; transform: scale(1) !important; filter: none !important; }
}

@media (max-width: 720px) {
  .l-industries-rail { gap: 16px; padding-left: 16px; padding-right: 16px; }
  .l-industry-panel { width: 84vw; height: auto; aspect-ratio: 3 / 4; }
  .l-industry-copy { padding: var(--space-6) var(--space-4) var(--space-6); }
}

/* ================= DELIVERABLES SCATTER ================= */
.l-scatter-section { padding-block: clamp(16px, 2vw, 28px); }
.l-scatter {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-8);
  max-width: 900px;
  margin-inline: auto;
}
@media (max-width: 760px) { .l-scatter { grid-template-columns: 1fr; max-width: 420px; } }
.l-scatter-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 12px 28px rgba(22,34,68,0.08);
  padding: var(--space-4);
  transform: rotate(var(--rot, 0deg)) translateY(24px);
  opacity: 0;
  transition: transform 600ms cubic-bezier(0.16,1,0.3,1), opacity 600ms ease;
  transition-delay: calc(var(--si, 0) * 90ms);
}
.l-scatter.is-visible .l-scatter-card { transform: rotate(var(--rot, 0deg)) translateY(0); opacity: 1; }
.l-scatter-card:nth-child(1) { --rot: -4deg; }
.l-scatter-card:nth-child(2) { --rot: 2deg; margin-top: 12px; }
.l-scatter-card:nth-child(3) { --rot: -2deg; }
.l-scatter-thumb {
  aspect-ratio: 3/2;
  background: var(--color-surface-alt);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: var(--space-3);
}
.l-scatter-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.l-scatter-tag {
  display: inline-block;
  background: var(--color-success-bg);
  color: var(--color-success);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 999px;
}

/* ================= INTEGRATIONS CAROUSEL ================= */
.l-carousel-section {
  background: var(--color-surface-dark);
  color: #fff;
  padding-block: clamp(24px, 3vw, 40px);
  text-align: center;
  overflow: hidden;
}
.l-carousel-title {
  font-family: "Fraunces", var(--font-display), serif;
  font-weight: 500;
  font-size: clamp(1.5rem, 4vw, 2.25rem);
  line-height: 1.25;
  color: #fff;
}
/* Scroll-snap rail, same touch/scroll behaviour as .l-industries-rail
   (side-scroll drag/swipe, vertical swipes hand off to the page) --
   replaces the old button+transform coverflow, which had no touch
   scrolling at all. */
.l-car-rail {
  /* No justify-content:center -- on an overflowing flex container that
     shifts the initial scroll position to start mid-content instead of
     at the first card. The padding below gives the same centered-look
     inset on wide viewports without touching where scroll starts. */
  margin-top: clamp(16px, 3vw, 28px);
  display: flex;
  gap: var(--space-4);
  overflow-x: auto;
  overflow-y: hidden;
  touch-action: pan-x;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 4px max(24px, calc((100vw - 680px) / 2)) 8px;
}
.l-car-rail::-webkit-scrollbar { display: none; }
.l-car-rail:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 4px; }
.l-car-card {
  flex: none;
  scroll-snap-align: center;
  width: 220px;
  height: 92px;
  border-radius: var(--radius-lg);
  background: var(--color-surface-dark-2);
  border: 1px solid rgba(255,255,255,0.14);
  display: grid;
  place-items: center;
  padding: 8px 16px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.9375rem;
  /* see .l-showcase-photo: --color-navy-soft fails AA on surface-dark-2 */
  color: var(--color-navy-soft-on-dark2);
  transition: color 400ms ease, border-color 400ms ease;
}
.l-car-card.is-active { color: #fff; border-color: var(--color-accent); }

.l-car-progress {
  margin: var(--space-4) auto 0;
  width: 160px;
  height: 2px;
  background: rgba(255,255,255,0.16);
  border-radius: 2px;
  overflow: hidden;
}
.l-car-progress span {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--color-accent);
  transform-origin: left;
  transition: transform 400ms ease;
}

/* ================= PRICING (embedded, 4-card grid, one price shown per toggle) ================= */
.l-pricing-section { padding-block: clamp(32px, 4vw, 56px); }
.l-pricing-head { text-align: center; max-width: 640px; margin-inline: auto; }
.l-pricing-head h2 {
  font-family: "Fraunces", var(--font-display), serif;
  font-weight: 500;
  font-size: clamp(1.75rem, 4.5vw, 2.5rem);
}

/* -- Monthly / Once-off focus toggle (pill style, matches pricing.html's route-toggle) -- */
.l-route-toggle-row { display: flex; justify-content: center; margin-top: var(--space-6); }
/* site.css's active-state selector assumes .route-toggle is a direct sibling
   of the radio inputs (true on pricing.html); this page wraps it in
   .l-route-toggle-row to center it, which breaks that ~ sibling match --
   restated here reaching through the wrapper so the active pill actually
   highlights. */
#route-partnership:checked ~ .l-route-toggle-row .route-toggle label[for="route-partnership"],
#route-loneWolf:checked ~ .l-route-toggle-row .route-toggle label[for="route-loneWolf"] {
  background: var(--color-primary);
  color: #fff;
}

/* -- Package grid: all four tiers always visible -- */
.l-pricing-grid {
  margin-top: var(--space-8);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
  align-items: stretch;
}
@media (max-width: 1000px) { .l-pricing-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .l-pricing-grid { grid-template-columns: 1fr; } }

.l-price-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
}
.l-pricing-panel-head { display: flex; align-items: center; gap: var(--space-2); }
.l-pricing-panel-head svg { flex: none; color: var(--color-accent); }
.l-pricing-panel-head h3 { font-family: var(--font-display); font-weight: 700; font-size: 1.125rem; }

.l-price-block {
  margin-top: var(--space-4);
  padding: 10px var(--space-3); border-radius: var(--radius-md);
  border: 1px solid var(--color-accent); box-shadow: 0 0 0 1px var(--color-accent);
  background: var(--color-surface);
  display: none;
}
.l-price-block-label { display: block; font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--color-text-muted); }
.l-price-block .amount {
  display: block; margin-top: 4px; font-family: var(--font-mono); font-weight: 500;
  color: var(--color-primary); font-size: 1.375rem;
}
.l-price-block .amount .period { font-size: 0.75rem; font-weight: 400; color: var(--color-text-muted); }
.l-price-block .setup { display: block; margin-top: 2px; font-family: var(--font-mono); font-size: 0.6875rem; color: var(--color-text-muted); }

/* Only the selected route's price shows -- the other is fully hidden, not just de-emphasized */
#route-partnership:checked ~ .l-pricing-grid .block-monthly,
#route-loneWolf:checked ~ .l-pricing-grid .block-onceoff {
  display: block;
}

.l-price-card .desc { color: var(--color-text-muted); font-size: 0.8125rem; margin-top: var(--space-3); }

.l-price-features {
  list-style: none; margin: var(--space-4) 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 8px;
  flex: 1;
}
.l-price-features li { display: none; gap: 8px; font-size: 0.8125rem; color: var(--color-text); }
.l-price-features svg { flex: none; color: var(--color-accent); margin-top: 2px; }

/* Only the selected route's feature line shows, matching the price block above it */
#route-partnership:checked ~ .l-pricing-grid .feat-monthly,
#route-loneWolf:checked ~ .l-pricing-grid .feat-onceoff {
  display: flex;
}
.l-price-card .btn { margin-top: var(--space-4); justify-content: center; }

/* Custom Digital Platform's CTA breaks from the One Green Rule on request --
   the base system's full-strength crimson (--color-highlight, #9a2035),
   otherwise reserved elsewhere for naming Actuarial Expertise specifically. */
.l-price-card.is-custom .btn-primary { background: var(--color-highlight); }
.l-price-card.is-custom .btn-primary:hover { background: #7c1a2b; }

/* ================= FAQ ================= */

/* ================= CONTACT ================= */
.l-contact-section {
  padding-block: clamp(56px, 10vw, 120px);
  background: var(--color-surface);
}
.l-contact-section h2 { margin-bottom: 0; }
.l-stats {
  margin-top: var(--space-12);
  display: flex;
  gap: var(--space-8);
  flex-wrap: wrap;
}
.l-stat { max-width: 160px; }
.l-stat-num {
  display: block;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 2rem;
  color: var(--color-accent);
  line-height: 1;
}
.l-stat-label {
  display: block;
  margin-top: 6px;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  line-height: 1.4;
}

.l-contact-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
}
.l-field { display: flex; flex-direction: column; gap: 4px; }
.l-field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
}
@media (max-width: 480px) {
  .l-field-row { grid-template-columns: 1fr; }
}
.l-field label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-primary);
}
.l-field-required {
  color: var(--color-accent);
  font-weight: 700;
}
.l-field input,
.l-field select,
.l-field textarea {
  font-family: var(--font-body);
  font-size: 1rem; /* 16px minimum -- below this, iOS Safari auto-zooms the
    whole page on focus. This rule is shared by every contact form on the
    site (index/pricing/about), so this is the site's single highest-reach
    mobile fix. */
  color: var(--color-primary);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  transition: border-color var(--transition-base);
}
.l-field input:focus-visible,
.l-field select:focus-visible,
.l-field textarea:focus-visible {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(26, 100, 70, 0.25);
}
.l-field textarea { resize: vertical; min-height: 96px; }
.l-field-honeypot {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}
.l-contact-form .btn {
  align-self: flex-start;
  margin-top: var(--space-1);
  border: none;
  cursor: pointer;
}
.l-contact-form .btn:disabled { opacity: 0.6; cursor: default; }
.l-form-success[hidden] { display: none; }
.l-form-success {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--color-accent);
  font-size: 0.9375rem;
  font-weight: 600;
}
.l-form-success svg { flex: none; }
.l-contact-company { margin-top: calc(var(--space-3) + 32px); }

/* ================= INCLUDED-IN-EVERY-BUILD (hero strip) =================
   Fourteen authored line icons (24x24 viewBox, 1.5 uniform stroke, round
   caps/joins, single currentColor) for the fourteen real inclusions listed
   in PRODUCT.md, spread edge-to-edge across the hero on the paper ground
   below the intake box -- the same full-width distribution language as
   .l-fan, each icon paired with its name set in the page's body face.

   Motion thesis -- "assembling the system": these 12 marks are the discrete
   parts of one engineered build, so they don't just fade in, they arrive
   like components clicking into place -- each one spins in from a twisted,
   undersized state to true scale and 0deg as its stroke self-draws
   (pathLength="1" on every shape) in the accent green, settling to ink the
   instant it's fully drawn. Staggered left-to-right so the row visibly
   assembles once, left to right. Transition-driven off the shared
   .is-visible class (same IntersectionObserver reveal as .l-fan/.l-scatter),
   never animation-with-fill-forwards, so the hover state can still win. */
.l-included-mini {
  list-style: none;
  margin: calc(var(--space-3) + 24px) auto 0; /* offsets .l-fan's negative
                        margin-top so the icon row stays put */
  padding: 10px 24px;
  width: min(96vw, 1360px);
  background: var(--color-bg);
  border-radius: var(--radius-md);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  row-gap: var(--space-5);
  column-gap: var(--space-2);
}
/* The four differentiators (WhatsApp, dashboards, analytics, POPIA) read as
   a curated highlight, not a spec dump -- grouped and centered rather than
   spread edge-to-edge like the full 12-item list used to be. The other 8
   inclusions are still real and still one click away, just not competing
   for attention up front. */
.l-included-mini--headline {
  width: auto;
  max-width: 640px;
  justify-content: center;
  gap: var(--space-8);
}
.l-included-more {
  width: min(96vw, 1360px);
  margin: 0 auto;
}
.l-included-more summary {
  display: flex;
  align-items: center;
  gap: 6px;
  width: fit-content;
  margin-inline: auto;
  padding: 2px 4px;
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text-muted);
  cursor: pointer;
  list-style: none;
}
.l-included-more summary::-webkit-details-marker { display: none; }
.l-included-more summary:hover { color: var(--color-primary); }
.l-included-more summary .icon {
  width: 14px; height: 14px;
  position: relative;
}
.l-included-more summary .icon::before,
.l-included-more summary .icon::after {
  content: "";
  position: absolute;
  background: currentColor;
  transition: transform var(--transition-base);
}
.l-included-more summary .icon::before { top: 6px; left: 1px; width: 12px; height: 1.5px; }
.l-included-more summary .icon::after { top: 1px; left: 6px; width: 1.5px; height: 12px; }
.l-included-more[open] summary .icon::after { transform: scaleY(0); }
.l-included-more .l-included-mini-extra {
  margin: var(--space-4) auto 0;
}
.l-included-mini-item {
  --d: calc(var(--ii, 0) * 55ms);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 92px;
  text-align: center;
  color: var(--color-accent);
  opacity: 0;
  transform: scale(0.4) rotate(-14deg);
  transition:
    color 460ms ease calc(var(--d) + 340ms),
    opacity 260ms ease var(--d),
    transform 520ms cubic-bezier(0.16, 1, 0.3, 1) var(--d);
}
.l-included-mini-item svg { display: block; }
.l-included-mini-item :is(path, circle, rect) {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 700ms cubic-bezier(0.22, 1, 0.36, 1) var(--d);
}
.l-included-mini.is-visible .l-included-mini-item {
  opacity: 1;
  transform: scale(1) rotate(0deg);
  color: var(--color-text);
}
.l-included-mini.is-visible .l-included-mini-item :is(path, circle, rect) { stroke-dashoffset: 0; }

.l-included-mini-label {
  font-family: var(--font-body);
  font-size: 0.75rem;
  line-height: 1.3;
  color: var(--color-text);
  transition: color var(--transition-base);
}

@media (hover: hover) {
  .l-included-mini.is-visible .l-included-mini-item:hover {
    color: var(--color-accent);
    transform: translateY(-3px) scale(1.08);
    transition: color 160ms ease, transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .l-included-mini.is-visible .l-included-mini-item:hover .l-included-mini-label {
    color: var(--color-primary);
  }
}

@media (prefers-reduced-motion: reduce) {
  .l-included-mini-item {
    opacity: 1;
    transform: none;
    transition: none;
    color: var(--color-text);
  }
  .l-included-mini-item :is(path, circle, rect) {
    stroke-dashoffset: 0;
    transition: none;
  }
  .l-included-mini.is-visible .l-included-mini-item:hover {
    transform: none;
    transition: color 160ms ease;
  }
}

/* ================= FOOTER — giant wordmark ================= */
.landing .site-footer { position: relative; overflow: hidden; }
.l-footer-mark {
  position: absolute;
  left: 50%;
  bottom: -10%;
  transform: translateX(-50%);
  width: min(1400px, 130vw);
  opacity: 0.08;
  filter: brightness(0) invert(1);
  pointer-events: none;
  user-select: none;
}
.landing .footer-grid, .landing .footer-bottom { position: relative; z-index: 1; }
