:root {
  /* ===== BRAND (supplied palette, do not alter these five) ===== */
  --navy-900: #001B48;   /* secondary, deepest */
  --navy-700: #02457A;   /* secondary */
  --blue-500: #018ABE;   /* PRIMARY */
  --blue-200: #97CADB;   /* primary, light */
  --blue-050: #D6E8EE;   /* primary, palest */

  /* ===== DERIVED, because five hexes cannot cover every contrast case =====
     blue-500 is 3.90:1 on white, so it can carry large display type and fills
     but not body text or a white button label. These two cover that gap. */
  --blue-ink:  #016A93;  /* small type on light: 6.03 on white, 4.77 on blue-050 */
  --blue-lift: #6FC7EA;  /* small type on dark: 8.82 on navy-900, 5.17 on navy-700 */
  --blue-cta:  #0179A6;  /* button fill that holds a white label at 4.90 */
  --navy-950:  #000E26;  /* one step under navy-900, so the hero shell reads as
                            a separate plane instead of dissolving into its own
                            frame. Ground only, never type. */

  /* ===== GROUNDS ===== */
  --bg: #F4F8FB;         /* light page ground, a tint above blue-050 */
  --bg-tint: var(--blue-050);
  --white: #ffffff;
  --dark-1: var(--navy-900);
  --dark-2: var(--navy-700);

  /* ===== TYPE COLOURS ===== */
  --ink: #10233F;
  --muted: #4C6183;      /* 5.5:1 on --bg */
  --on-dark: rgba(233, 242, 250, 0.86);
  --on-dark-mute: rgba(151, 202, 219, 0.86);

  /* ===== RULES AND TINTS ===== */
  --border: #DCE6F1;
  --rule: rgba(0, 27, 72, 0.11);
  --rule-2: rgba(0, 27, 72, 0.20);
  --rule-light: rgba(255, 255, 255, 0.13);
  --rule-light-2: rgba(255, 255, 255, 0.28);
  --tint: rgba(1, 138, 190, 0.06);

  /* ===== GLOW ===== */
  --glow-blue: rgba(1, 138, 190, 0.34);
  --glow-deep: rgba(2, 69, 122, 0.28);

  /* ===== SHAPE ===== buttons full pill, chips 10, cards 18, glass 26 */
  --r-chip: 10px;
  --r-card: 18px;
  --r-glass: 26px;
  --r-pill: 999px;
  --r-sm: var(--r-chip);
  --r-md: var(--r-card);
  --radius: var(--r-card);

  /* ===== DEPTH ===== tinted with the brand navy, never neutral black */
  --lift-1: 0 2px 8px rgba(0, 27, 72, 0.10);
  --lift-2: 0 14px 34px rgba(0, 27, 72, 0.13);
  --lift-3: 0 30px 70px rgba(0, 20, 55, 0.30);
  --sh-1: var(--lift-1);
  --sh-2: var(--lift-2);
  --sh-3: var(--lift-3);
  --shadow: var(--lift-2);

  /* ===== TYPEFACES ===== */
  --sans: "Open Sauce One", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --header-h: 74px;
  --ease: cubic-bezier(0.22, 0.7, 0.24, 1);
}

/* ===== SELF-HOSTED FACES ===== */
@font-face { font-family: "Open Sauce One"; src: url(/opensauce-400.woff2) format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Open Sauce One"; src: url(/opensauce-500.woff2) format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "Open Sauce One"; src: url(/opensauce-600.woff2) format("woff2"); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: "Open Sauce One"; src: url(/opensauce-700.woff2) format("woff2"); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: "Open Sauce One"; src: url(/opensauce-800.woff2) format("woff2"); font-weight: 800; font-style: normal; font-display: swap; }
@font-face { font-family: "JetBrains Mono"; src: url(/jetbrainsmono-400.woff2) format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "JetBrains Mono"; src: url(/jetbrainsmono-500.woff2) format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }



* { box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 14px);
  /* proximity, not mandatory: only the timeline's stations opt in as targets */
  scroll-snap-type: y proximity;
}
body {
  margin: 0;
  font-family: var(--sans);
  color: var(--ink);
  /* One flat ground. This was a linear gradient stacked on three large radial
     tints, which hazed every surface on the page and left nothing reading as
     a committed colour. */
  background: var(--bg);
  line-height: 1.6;
  overflow-x: hidden;
}
/* faint ruling across the light sections, at the same 64px pitch as the hero */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.6;
  background-image:
    linear-gradient(rgba(0, 27, 72, 0.028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 27, 72, 0.028) 1px, transparent 1px);
  background-size: 64px 64px;
}
a { text-decoration: none; color: inherit; }
img { max-width: 100%; display: block; }
/* side padding is set with padding-inline so that block-level padding on
   .nav / .hero-inner (which also carry .wrap) cannot wipe it out */
.wrap { max-width: 1180px; margin: 0 auto; padding-inline: 24px; }
.badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: rgba(1, 138, 190, 0.14);
  color: var(--blue-ink);
  font-weight: 700;
  font-size: 13px;
  padding: 7px 14px;
  border-radius: 999px;
  letter-spacing: 0.03em;
  box-shadow: inset 0 0 0 1px rgba(1, 138, 190, 0.18);
}

/* bracketed monospace section label (Forgeflow-style eyebrow) */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--blue-ink);
  margin-bottom: 16px;
}
.eyebrow::before { content: "["; opacity: 0.55; }
.eyebrow::after { content: "]"; opacity: 0.55; }
/* blue-500 is only 4.30:1 on navy-900, so small text on dark uses blue-lift */
.eyebrow-light { color: var(--blue-lift); }

/* word-by-word reveal for headlines. No blur: animating `filter` is expensive
   and any filter value keeps a stacking context alive, which stopped an
   ancestor's background-clip:text from painting the word */
html.js [data-split] .word {
  display: inline-block;
  opacity: 0;
  translate: 0 0.3em;
  transition: opacity 0.45s ease, translate 0.45s var(--ease);
  transition-delay: calc(var(--i, 0) * 30ms);
}
html.js [data-split].is-split-in .word { opacity: 1; translate: none; }

/* ============ HEADER / NAV ============
   Ref 2 puts the navigation inside the hero's glass container rather than in a
   bar of its own. `header.site` is a transparent rail; `.nav` is the visible
   surface, glass while it overlays the hero and solid once docked. */
header.site {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background: transparent;
}
.nav-wrap { padding-block: 30px; transition: padding 0.3s var(--ease); }
header.site.is-scrolled .nav-wrap { padding-block: 10px; }

.scroll-progress {
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  pointer-events: none;
}
.scroll-progress i {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--blue-500), var(--blue-lift));
}
@supports not (animation-timeline: scroll()) { .scroll-progress { display: none; } }
@supports (animation-timeline: scroll()) {
  .scroll-progress i {
    animation-name: progressGrow;
    animation-duration: auto;
    animation-timing-function: linear;
    animation-fill-mode: both;
    animation-timeline: scroll(root block);
  }
}
@keyframes progressGrow { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* Spacing here is a budget, not a taste call. The row is logo + links +
   actions, all nowrap and none of them shrinkable, inside a capsule capped at
   1180px by .wrap — so if the content is wider than the capsule the actions
   simply hang off the right and the hero shell clips them. There is no
   scrollbar and nothing reflows, so it fails silently.
   Finnish is the constraint: "Magaya-ratkaisut", "Yhteystiedot" and "Varaa
   esittely" ran the row 14px past the capsule at 1200px and 28px past at
   1181px, which cut the end off the primary CTA at every desktop width above
   the hamburger breakpoint. English had 35px of slack and looked fine.
   The gap, the left padding and the per-link padding below are all trimmed to
   buy that back with room to spare, rather than collapsing to a hamburger
   earlier and losing the single-line nav on real desktops. */
.nav {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 11px 11px 11px 18px;
  border-radius: var(--r-pill);
  transition: background 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}
/* glass while it floats over the hero photograph */
.nav {
  /* Tinted, not clear. At 14% white the painted field showed straight through
     and a bright filament read as a horizontal line ruled across the navbar.
     The navy tint keeps the glass character and stops the field punching through. */
  background:
    linear-gradient(150deg, rgba(0, 22, 58, 0.62), rgba(0, 22, 58, 0.46));
  backdrop-filter: blur(22px) saturate(140%);
  -webkit-backdrop-filter: blur(22px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, 0.20);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), var(--lift-2);
}
/* solid once docked, so it stays legible over light content below */
header.site.is-scrolled .nav {
  background: var(--white);
  border-color: var(--border);
  box-shadow: var(--lift-2);
}
@media (prefers-reduced-transparency: reduce) {
  .nav { background: rgba(0, 27, 72, 0.94); backdrop-filter: none; -webkit-backdrop-filter: none; }
}

.logo {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}

/* The supplied lockup already contains the wordmark, so the typed name and the
   old company-name tagline are gone: they duplicated it and ate the nav width
   that was forcing an early hamburger. */
.logo-lockup {
  display: block;
  height: 30px;
  width: auto;
}
/* Two real lockups rather than a filtered one: the reversed file over the hero,
   the colour file once the nav docks onto white. Declared after the base rule,
   because at equal specificity the base `display: block` wins on source order
   and both variants render at once. */
.logo-lockup--dark { display: none; }
header.site.is-scrolled .logo-lockup--light { display: none; }
header.site.is-scrolled .logo-lockup--dark { display: block; }
/* the footer is navy, so it carries the reversed lockup in place of a heading */
.foot-logo { display: block; height: 30px; width: auto; margin-bottom: 14px; }
.foot-blurb { margin: 0; max-width: 280px; color: var(--on-dark); font-size: 14px; }

nav.links {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  /* flex children default to min-width:auto, so without this the nowrap link
     row sets a floor that pushes the actions out of the capsule instead of
     being contained by it */
  min-width: 0;
  /* zero, because min-width:0 above means any excess is taken out of the link
     row itself and centre-justification then clips BOTH ends. The 10px of
     padding on each link already separates the labels; the gap was only adding
     a floor. Restored to 2px in the mobile panel, where the row is a column. */
  gap: 0;
  font-size: 13.5px;
  font-weight: 500;
  color: #fff;
}
nav.links a {
  position: relative;
  padding: 8px 10px;
  border-radius: var(--r-pill);
  color: rgba(255, 255, 255, 0.88);
  white-space: nowrap;
  transition: color 0.2s ease, background 0.25s ease;
}
nav.links a:hover { color: #fff; background: rgba(255, 255, 255, 0.13); }
nav.links a.is-active { color: #fff; background: rgba(255, 255, 255, 0.16); }
header.site.is-scrolled nav.links a { color: var(--navy-700); }
header.site.is-scrolled nav.links a:hover,
header.site.is-scrolled nav.links a.is-active { color: var(--navy-900); background: var(--tint); }
nav.links a.cta-btn { color: #fff; }

.nav-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }

/* ---- language switcher ----
   A <details>, so it opens and is keyboard reachable with no JavaScript at all:
   the switcher is how someone reaches a language they can read, and it must not
   depend on a script. Escape-to-close and outside-click are added in app.js as
   an enhancement, because <details> does not provide either natively. */
.lang { position: relative; flex: none; }
.lang summary {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 13px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(255, 255, 255, 0.24);
  background: rgba(255, 255, 255, 0.10);
  color: #fff;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  cursor: pointer;
  list-style: none;
  transition: background 0.25s ease, border-color 0.25s ease;
}
.lang summary::-webkit-details-marker { display: none; }
.lang summary:hover { background: rgba(255, 255, 255, 0.18); }
header.site.is-scrolled .lang summary {
  border-color: var(--rule-2);
  background: none;
  color: var(--navy-900);
}
header.site.is-scrolled .lang summary:hover { background: var(--tint); }
.lang-caret {
  width: 0;
  height: 0;
  border-left: 3.5px solid transparent;
  border-right: 3.5px solid transparent;
  border-top: 4px solid currentColor;
  opacity: 0.75;
}
.lang[open] .lang-caret { transform: rotate(180deg); }
.lang-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 5;
  min-width: 168px;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--lift-3);
}
.lang-menu a {
  display: block;
  padding: 9px 12px;
  border-radius: var(--r-chip);
  font-size: 14px;
  color: var(--navy-900);
}
.lang-menu a:hover { background: var(--tint); color: var(--blue-ink); }
.lang-menu a[aria-current="true"] { background: var(--tint); font-weight: 600; }
.lang-menu em {
  font-style: normal;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
.nav-toggle {
  display: none;
  width: 42px;
  height: 42px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(255, 255, 255, 0.28);
  background: rgba(255, 255, 255, 0.10);
  cursor: pointer;
  padding: 0;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
}
header.site.is-scrolled .nav-toggle { border-color: var(--border); background: var(--white); }
.nav-toggle span { display: block; width: 18px; height: 2px; border-radius: 2px; background: #fff; transition: transform 0.3s var(--ease), opacity 0.2s ease; }
header.site.is-scrolled .nav-toggle span { background: var(--navy-900); }
header.site.nav-open .nav-toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
header.site.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
header.site.nav-open .nav-toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ---- buttons ---- */
.cta-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: var(--blue-cta);
  color: #fff;
  padding: 12px 20px;
  border-radius: var(--r-pill);
  font-weight: 600;
  font-size: 14px;
  white-space: nowrap;
  box-shadow: var(--lift-1);
  transition: transform 0.25s var(--ease), box-shadow 0.25s ease, background 0.3s ease;
}
.cta-btn:hover { transform: translateY(-2px); background: var(--blue-500); box-shadow: var(--lift-2); }
.cta-btn:active { transform: translateY(0); }
.nav-cta { flex-shrink: 0; }
.nav-panel-cta { display: none; }
.cta-arrow { display: inline-block; transition: transform 0.25s var(--ease); }
.cta-btn:hover .cta-arrow { transform: translate(2px, -2px); }
/* the brand primary cannot hold a white label at AA, so the accent variant
   uses the darkened cta blue and reserves blue-500 for the hover state */
.cta-accent { background: var(--blue-cta); }
.cta-accent:hover { background: var(--blue-500); }

.cta-outline {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid var(--rule-2);
  color: var(--navy-900);
  padding: 11px 18px;
  border-radius: var(--r-pill);
  font-weight: 600;
  font-size: 14px;
  background: none;
  transition: background 0.25s ease, transform 0.25s var(--ease), border-color 0.25s ease, color 0.25s ease;
}
.cta-outline:hover { background: var(--tint); border-color: var(--blue-500); color: var(--blue-ink); transform: translateY(-2px); }
.cta-outline-light,
.cta-ring {
  border-color: rgba(255, 255, 255, 0.34);
  color: #fff;
  background: rgba(255, 255, 255, 0.09);
}
.cta-outline-light:hover,
.cta-ring:hover { border-color: var(--blue-lift); background: rgba(255, 255, 255, 0.17); color: #fff; }

/* ============ GLASS ============
   Blur alone looks cheap. The edge highlights are what read as a real material:
   a bright top edge catching light, a weaker bottom edge, and a tinted cast
   shadow. Always over a scrim, never directly over photography. */
.glass {
  background: linear-gradient(150deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.035));
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.16);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.24),
    inset 0 -1px 0 rgba(255, 255, 255, 0.06),
    var(--lift-3);
}
@media (prefers-reduced-transparency: reduce) {
  .glass {
    background: rgba(0, 27, 72, 0.92);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* ============ HERO ============
   Ref 2 structure: a full-bleed photograph, and one glass container inset from
   every edge with the navigation living inside its top band. */
.hero-stage {
  position: relative;
  /* inset on all four sides, so the shell reads as a container floating on the
     page rather than a band welded to the section below it */
  padding: 16px;
  /* the page ground, so the shell reads as a card floating on the page. It was
     navy-950, which put a heavy near-black L around the corners. */
  background: var(--bg);
}
.hero-shell {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-glass);
  isolation: isolate;
  /* the light hairline the reference carries on its glass container, in a brand
     tint rather than plain white */
  border: 1px solid rgba(151, 202, 219, 0.22);
  box-shadow: 0 1px 0 rgba(151, 202, 219, 0.10) inset, var(--lift-3);
}
/* the painted caustic field. Sits where the photograph does, but it is drawn
   once by app.js rather than downloaded. */
.hero-ribbons {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -2;
  pointer-events: none;
}
/* The mesh sits ABOVE the scrim, below the content.
   Under the scrim it was invisible in the half of the hero that has room for
   it: this scrim runs to rgba(0,20,55,0.88) on the left, which is the point of
   it, and that buried the mesh everywhere except the right edge behind the
   cards. Above it the mesh reads properly, and the contrast it costs is paid
   for by keeping nodes off the text block and by low link alpha — measured
   across frames and pointer positions rather than assumed. */
.hero-mesh {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}
/* Dropped a layer and dimmed. Two full-strength systems in one frame read as
   busy rather than deep, so the ribbons become the soft ground the mesh is
   drawn on. This class is only applied on the hero that has a mesh, so it
   needs no :has() guard. */
.hero-ribbons--base {
  z-index: -3;
  opacity: 0.55;
}
/* the scrim. Contrast is measured against this, not against the photo, which
   is why every white element in the hero can be guaranteed rather than hoped. */
.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(100deg, rgba(0, 20, 55, 0.88) 0%, rgba(0, 20, 55, 0.62) 42%, rgba(0, 20, 55, 0.26) 76%, rgba(0, 20, 55, 0.48) 100%);
}
/* A second, steeper scrim over the text column only. The global ramp above was
   not enough where a bright filament crossed behind the headline: composited
   pixel sampling measured the caps line at 2.70:1. The right half keeps the
   ribbons at full strength. */
.hero-scrim::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Full-height column shield, deliberately not positioned. Earlier versions
     shielded the quadrant the text happened to occupy, and every layout change
     slid a caps line back onto a bright filament. Protecting the whole column
     means the guarantee survives moving things around. */
  /* Middle stops deepened. Composited-pixel sampling put white on the caps
     triad at 4.46:1 against a 4.5 floor for 13px type — the line was already
     a hair short before the port scene existed, and the scene took another
     0.07. Deepening the shield clears both. It is column-local by design, so
     the right half where the scene is meant to be seen is untouched. */
  background: linear-gradient(96deg,
    rgba(0, 17, 46, 0.95) 0%,
    rgba(0, 17, 46, 0.92) 38%,
    rgba(0, 17, 46, 0.60) 60%,
    transparent 76%);
}
/* oversized ghost wordmark, clipped by the shell so it sits in the scene */
.hero-ghost {
  position: absolute;
  bottom: -0.08em;
  right: 2vw;
  z-index: 0;
  margin: 0;
  font-size: clamp(80px, 12.5vw, 190px);
  font-weight: 800;
  letter-spacing: -0.055em;
  line-height: 0.8;
  /* Dimmed from 0.07 once the port scene moved into the same bottom band. Two
     decorative layers at equal weight read as a smudge rather than depth, and
     the scene is the one carrying meaning, so the wordmark steps back to a
     texture behind it. */
  color: rgba(255, 255, 255, 0.042);
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
}
.hero-inner { position: relative; z-index: 1; padding: 130px 0 64px; }
.hero-grid-2 {
  display: grid;
  grid-template-columns: minmax(0, 1.32fr) minmax(0, 0.52fr);
  column-gap: 52px;
  /* start, not end: bottom-aligning the short text column against the taller
     card stack pushed the headline into the lower half and left a hole up top */
  align-items: start;
}
.hero h1 {
  margin: 0 0 18px;
  font-size: clamp(38px, 4.1vw, 58px);
  line-height: 1.08;
  letter-spacing: -0.028em;
  font-weight: 600;
  color: #fff;
  max-width: 25ch;
  text-wrap: balance;
}
.hero h1 em { font-style: normal; font-weight: 600; color: var(--blue-lift); }
/* the practices as a caps triad rather than a sentence. Substantive, not an
   atmospheric strip: it names the three things RC Insight actually does. */
.hero-main { padding-top: 4px; }
.hero-triad {
  margin: 0 0 30px;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  /* blue-050 not blue-200: at 13px this line needs 4.5:1 and the lighter tint
     clears it where a filament passes behind */
  color: var(--blue-050);
}
.hero-ctas { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

/* ---- the right column: cards stacked vertically, flush to the edge ---- */
.card-stack { display: grid; gap: 12px; align-content: start; }
.hcard {
  position: relative;
  padding: 18px 58px 18px 20px;
  border-radius: var(--r-chip);
  /* tinted, not clear: a bright ribbon behind clear glass washed the labels out
     entirely. The tint guarantees legibility whatever passes underneath. */
  background:
    linear-gradient(150deg, rgba(0, 22, 58, 0.72), rgba(0, 22, 58, 0.56));
}
.hcard-glyph {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 22px;
  height: 22px;
  color: var(--blue-lift);
  opacity: 0.9;
}
.hcard-glyph svg { display: block; width: 100%; height: 100%; }
.hcard-fig {
  display: block;
  font-size: 38px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.035em;
  color: #fff;
  font-variant-numeric: tabular-nums;
}
.hcard-fig i { font-style: normal; font-size: 0.5em; font-weight: 500; margin-left: 1px; }
.hcard-label {
  display: block;
  margin-top: 8px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--blue-050);
  max-width: 24ch;
}
.hcard-route { padding-bottom: 20px; }
.hcard-label-top {
  margin: 0 0 12px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.17em;
  text-transform: uppercase;
}
.route-nodes { list-style: none; margin: 0; padding: 0 0 0 22px; position: relative; }
.route-nodes::before,
.route-nodes::after {
  content: "";
  position: absolute;
  left: 4px;
  top: 5px;
  bottom: 16px;
  width: 1px;
}
.route-nodes::before { background: rgba(255, 255, 255, 0.22); }
.route-nodes::after {
  background: linear-gradient(180deg, var(--blue-lift), var(--blue-500));
  transform: scaleY(0);
  transform-origin: 50% 0;
  animation: routeDraw 1.15s var(--ease) 0.35s forwards;
}
.route-node { position: relative; padding-bottom: 13px; }
.route-node:last-child { padding-bottom: 0; }
/* centred against the name and status pair, not pinned to the first line */
.route-node::before {
  content: "";
  position: absolute;
  top: calc((1em * 1.25 + 1em * 1.1) / 2 - 4.5px);
  left: -22px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--navy-900);
  border: 2px solid var(--blue-lift);
}
.route-name { display: block; font-size: 13px; font-weight: 600; color: #fff; }
.route-state {
  display: block;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  color: var(--blue-200);
}
@keyframes routeDraw { to { transform: scaleY(1); } }

/* ---- record strip, now a glass rail under the nav ---- */
.rec-head {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 44px;
  margin: 0 0 34px;
  padding: 14px 20px;
  border-radius: var(--r-chip);
  background: linear-gradient(150deg, rgba(0, 22, 58, 0.64), rgba(0, 22, 58, 0.48));
}
.rec-field { display: flex; flex-direction: column; gap: 4px; }
.rec-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--on-dark-mute);
}
.rec-value { font-size: 13.5px; font-weight: 600; color: #fff; }

/* ============ INTERIOR PAGE HERO ============
   Same shell as home, shorter, and single-column because these pages carry one
   message rather than a message plus a figure cluster. */
.page-hero-inner {
  position: relative;
  z-index: 1;
  padding: 158px 0 92px;
}
.page-hero h1 {
  margin: 0 0 18px;
  font-size: clamp(34px, 3.5vw, 48px);
  line-height: 1.06;
  letter-spacing: -0.032em;
  font-weight: 800;
  color: #fff;
  max-width: 24ch;
  text-wrap: balance;
}
.page-hero--article h1 { font-size: clamp(28px, 2.9vw, 38px); max-width: 32ch; letter-spacing: -0.024em; }
.page-hero h1 em { font-style: normal; font-weight: 800; color: var(--blue-lift); }
.page-hero .lead {
  margin: 0;
  font-size: 16.5px;
  line-height: 1.6;
  color: var(--on-dark);
  max-width: 52ch;
}
.page-hero .rec-head { margin-bottom: 28px; }
.crumbs {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 20px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blue-050);
}
.crumbs a { color: var(--blue-050); }
.crumbs a:hover { color: var(--blue-lift); }
/* the ghost wordmark on interior pages names the page, not the brand */
/* clear of the shell's bottom edge: a clipped wordmark reads as a bug, not a watermark */
/* The ghost wordmark names the page. Longer names still bleed past the shell,
   which is the intended device, but a straight cut mid-glyph reads as a bug, so
   it dissolves into the right edge instead. */
.page-hero .hero-ghost {
  font-size: clamp(46px, 6.2vw, 92px);
  /* line-height 1, not the base 0.8: at 0.8 the box is shorter than the glyphs
     and descenders in names like "Magaya Solutions" fell outside it, so the
     shell's overflow cut the g and y in half */
  line-height: 1;
  bottom: 0.04em;
  right: 1.5vw;
  mask-image: linear-gradient(90deg, #000 62%, transparent 98%);
  -webkit-mask-image: linear-gradient(90deg, #000 62%, transparent 98%);
}

/* Interior heroes are shorter, so the same painted field lands denser in them.
   Their text column gets a heavier shield than the home hero needs. */
.page-hero .hero-scrim::after {
  background: linear-gradient(96deg,
    rgba(0, 15, 42, 0.95) 0%,
    rgba(0, 15, 42, 0.92) 38%,
    rgba(0, 15, 42, 0.56) 62%,
    transparent 76%);
}

/* ============ DARK BAND CONTEXT ============
   One context class flips the whole ruled component set onto a dark ground by
   redefining the tokens those components already reference, rather than writing
   a dark variant of each. Assign a band per section to get a deliberate
   light/dark rhythm instead of one flat page. */
.band-dark,
.band-dark-2 {
  position: relative;
  color: #fff;
  --rule: var(--rule-light);
  --rule-2: var(--rule-light-2);
  --tint: rgba(255, 255, 255, 0.055);
  --ink: #ffffff;
  --navy-900: #ffffff;      /* headings and figures invert */
  --navy-700: var(--blue-200);
  --muted: var(--on-dark-mute);
  --blue-ink: var(--blue-lift);
  --border: var(--rule-light);
}
.band-dark {
  background:
    radial-gradient(75% 90% at 12% 0%, var(--glow-blue), transparent 62%),
    #001B48;
}
.band-dark-2 {
  background:
    radial-gradient(70% 85% at 88% 4%, var(--glow-deep), transparent 60%),
    #02457A;
}
.band-dark .wrap,
.band-dark-2 .wrap { position: relative; z-index: 1; }
/* the outline button reads correctly from the inverted tokens already, but the
   filled one must not pick up the inverted navy as its label colour */
.band-dark .cta-btn,
.band-dark-2 .cta-btn { color: #fff; }

/* ============ CREDENTIAL STRIP ============
   Two labelled groups divided by a rule. It used to be a scrolling marquee of
   five text wordmarks under one "authorized partner and reseller for" label,
   which implied RC Insight resold its own products. Five items also could not
   loop without the duplicate landing in the same viewport. */
.credit-strip {
  background: var(--white);
  border-bottom: 1px solid var(--rule);
  padding: 22px 0;
}
.credit-grid {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 44px;
  align-items: center;
}
/* grid and flex children default to min-width:auto, so a max-content marquee
   track pushes the column wider than the viewport instead of being clipped */
.credit-cell { min-width: 0; }
.credit-cell + .credit-cell { border-left: 1px solid var(--rule); padding-left: 44px; }
.credit-label {
  display: block;
  margin-bottom: 12px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--muted);
}
.credit-logo { display: inline-flex; }
.credit-logo img { height: 26px; width: auto; }
.credit-logos { display: flex; align-items: center; flex-wrap: nowrap; gap: 12px 58px; }

/* Portfolio logos scroll. The track is tripled and travels exactly one third,
   so the loop point never lands mid-gap. With four marks a wide viewport will
   show a repeat: that is inherent to the item count, not a seam. */
.credit-marquee {
  min-width: 0;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 15%, #000 86%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 15%, #000 86%, transparent);
}
.credit-track {
  display: flex;
  align-items: center;
  width: max-content;
  gap: 0 58px;
  animation: creditRoll 34s linear infinite;
}
.credit-marquee:hover .credit-track,
.credit-marquee:focus-within .credit-track { animation-play-state: paused; }
@keyframes creditRoll {
  from { transform: translateX(0); }
  to   { transform: translateX(-33.3333%); }
}
/* the one real third-party bitmap in the set sits at the same optical weight */
.credit-logos .lg-img { height: 21px; width: auto; }
/* mark plus name, for the products with no public logo */
/* the logo itself is the link where the product has a public site */
.lg-link {
  display: inline-flex;
  align-items: center;
  border-radius: var(--r-sm);
  transition: opacity 0.2s ease, transform 0.2s var(--ease);
}
.lg-link:hover { opacity: 0.72; transform: translateY(-1px); }
.lg-lockup {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--navy-900);
}
.lg-mark { display: block; width: 19px; height: 19px; color: var(--blue-ink); }
/* a real mark file rather than a drawn monogram; kept at the same optical size */
.lg-mark-img { display: block; width: 20px; height: 20px; object-fit: contain; flex: none; }
.lg-mark svg { display: block; width: 100%; height: 100%; }

/* ============ STATS BAND (odometer counters) ============ */
.stats-band { padding: 40px 0 44px; }
/* closed with a rule so the figures read as a band, not four floating numbers */
.stats-band .stats-row { padding-bottom: 34px; border-bottom: 1px solid var(--rule); }
.stats-row { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0; max-width: 720px; }
.stat { padding: 6px 26px; border-left: 1px solid var(--rule); }
.stat:first-child { border-left: none; padding-left: 0; }
/* plain numbers. The rolling odometer that used to build a ten-cell column per
   digit was a lot of machinery to land on values under 13. */
.stat-num {
  font-size: clamp(38px, 4.4vw, 58px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(140deg, var(--navy-900) 10%, var(--blue-ink) 90%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.stat-label { margin-top: 12px; font-size: 13.5px; color: var(--muted); max-width: 190px; }

/* ============ SECTIONS ============ */
section { padding: 72px 0; position: relative; }
.section-head { max-width: 700px; margin: 0 auto 44px; text-align: center; }
.section-head .badge { margin-bottom: 14px; }
.section-head h2 { font-size: 30px; margin: 0 0 12px; color: var(--navy-900); font-weight: 800; line-height: 1.2; }
/* the same accent .statement and the hero headlines carry. Without it an <em>
   in a section heading fell through to the browser default italic, which is
   the one type treatment this design does not use anywhere. */
.section-head h2 em { font-style: normal; font-weight: 800; color: var(--blue-ink); }
.section-head p { color: var(--muted); font-size: 15.5px; }
.alt { background: rgba(255, 255, 255, 0.72); }

/* ============ REVEAL ENGINE ============ */
/* uses translate/scale (not transform) so hover transforms stay composable */
html.js [data-reveal] {
  opacity: 0;
  translate: 0 12px;
  transition: opacity 0.45s var(--ease), translate 0.45s var(--ease), scale 0.45s var(--ease);
  transition-delay: var(--d, 0ms);
  will-change: opacity, translate;
}
html.js [data-reveal="zoom"] { translate: 0 8px; scale: 0.98; }
html.js [data-reveal="left"] { translate: -18px 0; }
html.js [data-reveal="right"] { translate: 18px 0; }
html.js [data-reveal].is-visible { opacity: 1; translate: none; scale: none; }

/* ============ MANIFEST (replaces the card grid) ============
   Solutions read as a module manifest: a mono record code in the gutter, the
   module name, then what it does. No fill, no shadow, no lift. Hover tints the
   row and runs an accent up its leading edge. */
.manifest { border-top: 1px solid var(--rule-2); }
.mf-row {
  position: relative;
  display: grid;
  grid-template-columns: 62px minmax(0, 0.9fr) minmax(0, 1.3fr);
  gap: 6px 30px;
  align-items: start;
  padding: 24px 20px 24px 18px;
  border-bottom: 1px solid var(--rule);
  color: inherit;
  transition: background 0.3s ease;
}
.mf-row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--blue-500);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.35s var(--ease);
}
.mf-row:hover { background: var(--tint); }
.mf-row:hover::before { transform: scaleY(1); }
.mf-rec {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.07em;
  color: var(--muted);
  padding-top: 3px;
  transition: color 0.25s ease;
}
.mf-row:hover .mf-rec { color: var(--blue-ink); }
.mf-row h3 { margin: 0; font-size: 17.5px; line-height: 1.3; font-weight: 700; color: var(--navy-900); }
.mf-row p { margin: 0; font-size: 14.5px; color: var(--muted); }

/* the closing action row: same grid, heavier closing rule, arrow on the right */
.mf-row--action { padding-right: 54px; border-bottom: 1px solid var(--rule-2); }
.mf-row--action h3 { color: var(--blue-ink); }
.mf-row--action::after {
  content: "\2197";
  position: absolute;
  right: 20px;
  top: 24px;
  font-size: 15px;
  color: var(--blue-ink);
  transition: transform 0.25s var(--ease);
}
.mf-row--action:hover::after { transform: translate(3px, -3px); }

/* platform add-ons: a mono index, not a row of pills */
.tag-row { margin-top: 30px; display: flex; flex-wrap: wrap; gap: 8px; }
.tag {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.03em;
  background: none;
  color: var(--muted);
  padding: 6px 10px;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  transition: border-color 0.25s ease, color 0.25s ease, background 0.25s ease;
}
.tag:hover { border-color: rgba(1, 138, 190, 0.5); color: var(--blue-ink); background: var(--tint); }

/* ============ SERVICES (scroll-driven process timeline) ============ */
.timeline { position: relative; padding-top: 46px; }
.timeline .rail {
  position: absolute;
  top: 6px;
  left: 4%;
  right: 4%;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, rgba(1, 138, 190, 0.16), rgba(1, 138, 190, 0.16));
  overflow: hidden;
}
/* full by default; the desktop scroll timeline below scales it back and fills
   it as the sticky stage is scrolled through */
.timeline .rail i {
  display: block;
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, var(--blue-500), var(--blue-200));
  box-shadow: 0 0 14px rgba(1, 138, 190, 0.8);
}
.svc .node {
  position: absolute;
  top: -34px;
  left: 50%;
  width: 12px;
  height: 12px;
  margin-left: -6px;
  border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--rule-2);
  transition: border-color 0.3s ease, background 0.3s ease, box-shadow 0.3s ease, transform 0.3s var(--ease);
}
/* pending is hollow and faint; arrived fills with that step's own ink */
.svc.is-visible .node { border-color: var(--step-ink); background: var(--step-ink); }
.svc:hover .node { transform: scale(1.3); }
/* ---- PROCESS STEPS: columns, not cards. No border, no shadow, no box.
   A hairline separator and a giant ghost numeral carry the structure. ---- */
.services-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 0; }
.svc {
  position: relative;
  padding: 34px 26px 30px;
  background: none;
  border: 0;
  border-left: 1px solid var(--rule);
  box-shadow: none;
  transition: background 0.4s ease;
}
.svc:first-child { border-left: 0; }
/* a single display numeral carries the step marker (no duplicate label) */
.svc .num {
  display: block;
  font-size: 56px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  margin-bottom: 16px;
  background: none;
  color: var(--step-ink, var(--navy-900));
  opacity: 0.28;
  transition: opacity 0.45s ease, transform 0.45s var(--ease);
}
/* The ramp is the lifecycle: earliest step deepest, last step brightest. The
   colour carries the order rather than decorating five identical columns. */
/* Two ramps, not one. The numeral is 56px so it only needs 3:1 and can run to
   the brightest brand blue; the 18px title needs 4.5:1, and blue-500 is 3.66:1
   on this ground, so the title ramp stops short of it. */
.svc[data-step="0"] { --step-ink: #001B48; --step-title: #001B48; --step-tint: rgba(0, 27, 72, 0.055); }
.svc[data-step="1"] { --step-ink: #02457A; --step-title: #02457A; --step-tint: rgba(2, 69, 122, 0.06); }
.svc[data-step="2"] { --step-ink: #016A93; --step-title: #024E77; --step-tint: rgba(1, 106, 147, 0.07); }
.svc[data-step="3"] { --step-ink: #0179A6; --step-title: #015C80; --step-tint: rgba(1, 121, 166, 0.075); }
.svc[data-step="4"] { --step-ink: #018ABE; --step-title: #016A93; --step-tint: rgba(1, 138, 190, 0.085); }
.svc:hover .num,
.svc.is-visible .num { opacity: 1; }
.svc:hover .num { transform: translateY(-2px); }
/* the accent that climbs the divider on hover */
.svc::after {
  content: "";
  position: absolute;
  left: -1px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: linear-gradient(180deg, var(--blue-500), var(--blue-200));
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.45s var(--ease);
}
.svc:first-child::after { left: 0; }
.svc:hover { background: linear-gradient(180deg, rgba(1, 138, 190, 0.06), transparent 70%); }
.svc:hover::before { opacity: 0.11; transform: translateY(-3px); }
.svc:hover::after { transform: scaleY(1); }
.svc h4 { margin: 0 0 11px; font-size: 18px; line-height: 1.25; letter-spacing: -0.015em; color: var(--step-title, var(--navy-900)); }
.svc p { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--muted); }

/*
 * Scrollytelling stage. The runway is tall; the inner block is sticky.
 *
 * The sticky block is a full viewport tall and centres its content, rather than
 * being a short block pinned near the top. Pinned near the top it left half a
 * screen of empty section under the steps for the whole time it was parked.
 *
 * Steps advance in discrete stops. Each step has a short ramp followed by a
 * long hold, and the runway carries snap stations at the same offsets, so a
 * scroll settles on a step rather than between two.
 */
.timeline-stage { position: relative; }

/* Snap stations. Only these carry scroll-snap-align, so nothing else on any
   page becomes a snap target; `proximity` also leaves ordinary scrolling alone
   until the reader is already close to a stop. */
.snap-stations { display: none; }

@media (min-width: 960px) {
  @supports (animation-timeline: view()) {
    html.js .timeline-stage {
      min-height: 190vh;
      view-timeline-name: --stage;
      view-timeline-axis: block;
    }
    html.js .timeline-sticky {
      position: sticky;
      top: calc(var(--header-h) + 8px);
      /* sized to hug its content rather than the whole viewport: a full-height
         frame around a 535px block is what produced the empty band */
      min-height: 66svh;
      display: grid;
      align-content: center;
    }

    html.js .snap-stations {
      display: block;
      position: absolute;
      inset: 0;
      pointer-events: none;
    }
    html.js .snap-stations i {
      display: block;
      height: 20%;
      scroll-snap-align: start;
    }

    html.js .svc[data-step] {
      animation-name: stepIn;
      animation-duration: auto;
      animation-fill-mode: both;
      animation-timing-function: var(--ease);
      animation-timeline: --stage;
    }
    /* Short ramp, long hold, aligned to the station spacing above. Step 1 sits
       on `entry` so it has arrived before the block parks; putting it at
       contain 0% left the whole row blank for a full viewport of scrolling. */
    /* The active pass. Each step's panel tints as it arrives and releases once
       the next arrives, so there is always exactly one current column instead of
       five identical arrived ones. Ranges overlap the following step's ramp. */
    html.js .svc[data-step] {
      animation-name: stepIn, stepActive;
      animation-timeline: --stage, --stage;
    }
    html.js .svc[data-step="0"] { animation-range: entry 62% entry 100%, entry 62% contain 21%; }
    html.js .svc[data-step="1"] { animation-range: contain 15% contain 21%, contain 15% contain 39%; }
    html.js .svc[data-step="2"] { animation-range: contain 33% contain 39%, contain 33% contain 57%; }
    html.js .svc[data-step="3"] { animation-range: contain 51% contain 57%, contain 51% contain 75%; }
    /* the last one keeps its tint: there is no next step to hand off to */
    html.js .svc[data-step="4"] { animation-range: contain 69% contain 75%, contain 69% contain 82%; }
    html.js .svc[data-step="4"] { animation-name: stepIn, stepHold; }

    /* the node pops as its step arrives, so each stop reads as a station */
    html.js .svc[data-step] .node {
      animation-name: nodeArrive;
      animation-duration: auto;
      animation-fill-mode: both;
      animation-timing-function: var(--ease);
      animation-timeline: --stage;
    }
    html.js .svc[data-step="0"] .node { animation-range: entry 62% entry 100%; }
    html.js .svc[data-step="1"] .node { animation-range: contain 15% contain 23%; }
    html.js .svc[data-step="2"] .node { animation-range: contain 33% contain 41%; }
    html.js .svc[data-step="3"] .node { animation-range: contain 51% contain 59%; }
    html.js .svc[data-step="4"] .node { animation-range: contain 69% contain 77%; }

    html.js .timeline .rail i {
      transform-origin: 0 50%;
      animation-name: railFill;
      animation-duration: auto;
      animation-fill-mode: both;
      animation-timing-function: linear;
      animation-timeline: --stage;
      animation-range: contain 0% contain 75%;
    }
  }
}

@keyframes nodeArrive {
  0%   { transform: scale(0.5); border-color: var(--rule-2); box-shadow: 0 0 0 0 rgba(1, 138, 190, 0); }
  62%  { transform: scale(1.5); border-color: var(--blue-500); box-shadow: 0 0 0 7px rgba(1, 138, 190, 0.18); }
  100% { transform: scale(1);   border-color: var(--blue-500); box-shadow: 0 0 0 5px rgba(1, 138, 190, 0.14); }
}
@keyframes stepActive {
  0%   { background-color: transparent; }
  26%  { background-color: var(--step-tint); }
  68%  { background-color: var(--step-tint); }
  100% { background-color: transparent; }
}
@keyframes stepHold {
  0%   { background-color: transparent; }
  40%  { background-color: var(--step-tint); }
  100% { background-color: var(--step-tint); }
}
@keyframes stepIn {
  from { opacity: 0; translate: 0 26px; scale: 0.97; }
  to   { opacity: 1; translate: 0 0;    scale: 1; }
}
@keyframes railFill {
  /* Stepped, not linear. The rail holds while a step is held and only advances
     across that step's ramp, so it never runs ahead of the step count. The
     percentages are the step ramps expressed as fractions of contain 0-75%. */
  0%,  20% { transform: scaleX(0.2); }
  28%, 44% { transform: scaleX(0.4); }
  52%, 68% { transform: scaleX(0.6); }
  76%, 92% { transform: scaleX(0.8); }
  100%     { transform: scaleX(1); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-snap-type: none; }
  html.js .timeline-stage { min-height: 0; view-timeline-name: none; }
  html.js .timeline-sticky { position: static; min-height: 0; display: block; }
  html.js .snap-stations { display: none; }
  html.js .svc[data-step] .node { animation: none; }
  html.js .svc[data-step] {
    animation-timeline: none;
    animation-name: none;
    background-color: transparent;
    opacity: 1;
    translate: 0 0;
    scale: 1;
  }
  html.js .timeline .rail i { animation-timeline: none; animation-name: none; transform: none; }
}

/* ============ PORTFOLIO ============ */
.portfolio-band {
  background: linear-gradient(135deg, #02457A 0%, #001B48 100%);
  color: #fff;
  overflow: hidden;
}
.portfolio-band::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.55;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(circle at 30% 20%, #000, transparent 70%);
  -webkit-mask-image: radial-gradient(circle at 30% 20%, #000, transparent 70%);
}
.portfolio-band .wrap { position: relative; z-index: 1; }
.portfolio-band .section-head h2 { color: #fff; }
.portfolio-band .section-head p { color: #97CADB; }
/* Portfolio is the same ruled language on dark ground, cut differently: two
   columns, the product name block left and the prose right, so it does not read
   as the light manifest inverted. The conic hover ring and the 3-equal-column
   grid it sat in are both gone. */
.pf-manifest { border-top: 1px solid var(--rule-light-2); }
.pf-row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.5fr);
  gap: 10px 44px;
  align-items: start;
  padding: 30px 18px;
  border-bottom: 1px solid var(--rule-light);
  transition: background 0.3s ease;
}
.pf-row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--blue-500);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.35s var(--ease);
}
.pf-row:hover { background: rgba(255, 255, 255, 0.045); }
.pf-row:hover::before { transform: scaleY(1); }
.pf-badge {
  display: block;
  margin-bottom: 8px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blue-lift);
}
.pf-row h3 { margin: 0; font-size: 20px; line-height: 1.25; color: #fff; }
.pf-row p { margin: 0 0 14px; font-size: 14.5px; color: #B9CFE4; }
.pf-link {
  display: inline-block;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--blue-lift);
  border-bottom: 1px solid rgba(111, 199, 234, 0.45);
  padding-bottom: 2px;
  transition: border-color 0.25s ease, color 0.25s ease;
}
.pf-link::after { content: " \2197"; }
/* the product's own site, alongside the enquiry link rather than replacing it */
.pf-actions { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.pf-site {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--blue-200);
  border-bottom: 1px solid rgba(151, 202, 219, 0.35);
  padding-bottom: 2px;
  transition: color 0.25s ease, border-color 0.25s ease;
}
.pf-site::after { content: " \2197"; }
.pf-site:hover { color: #fff; border-color: #fff; }
.pf-link:hover { color: #97CADB; border-color: #97CADB; }
.note { font-size: 12px; color: #8FA8C4; margin-top: 34px; text-align: center; position: relative; z-index: 1; }

/* ============ INDUSTRIES ============
   A ruled index in three columns. No numbering: these are a set, not a
   sequence, so a counter would encode nothing. */
.industry-index {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--rule-2);
}
.industry-index li {
  position: relative;
  padding: 18px 16px 18px 20px;
  font-size: 15px;
  font-weight: 600;
  color: var(--navy-900);
  border-bottom: 1px solid var(--rule);
  transition: background 0.3s ease, color 0.25s ease;
}
.industry-index li + li { border-left: 1px solid var(--rule); }
.industry-index li:nth-child(3n + 1) { border-left: 0; }
.industry-index li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--blue-500);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.35s var(--ease);
}
.industry-index li:hover { background: var(--tint); color: var(--blue-ink); }
.industry-index li:hover::before { transform: scaleY(1); }

/* ============ ABOUT ============ */
.about-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: center; }
.about-grid h2 { font-size: 30px; color: var(--navy-900); font-weight: 800; margin-top: 0; }
/* editorial statement heading with a serif-italic accent (Avelety) */
.statement { font-size: clamp(28px, 3vw, 40px); line-height: 1.14; letter-spacing: -0.03em; }
.statement em {
  font-style: normal;
  font-weight: 800;
  color: var(--blue-ink);
}
.about-grid p { color: var(--muted); font-size: 15.5px; }
.checklist { list-style: none; padding: 0; margin: 22px 0 0; }
.checklist li {
  padding: 11px 0 11px 30px;
  position: relative;
  font-size: 14.5px;
  color: var(--ink);
  border-top: 1px solid var(--rule);
  transition: transform 0.25s var(--ease), color 0.25s ease;
}
.checklist li:first-child { border-top: none; }
.checklist li:hover { transform: translateX(5px); color: var(--navy-900); }
.checklist li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 9px;
  color: var(--blue-ink);
  font-weight: 900;
  transition: transform 0.25s var(--ease);
}
.checklist li:hover::before { transform: scale(1.25); }
/* the dark panel primitive: coverage, post CTA and the contact accent all use
   this one surface instead of three near-identical gradients */
.map-card {
  position: relative;
  background: linear-gradient(160deg, var(--navy-900), #001B48);
  color: #fff;
  border: 1px solid rgba(1, 138, 190, 0.22);
  border-radius: var(--r-md);
  padding: 30px 28px;
  overflow: hidden;
}
.map-card > * { position: relative; z-index: 1; }
.map-card h4 { margin: 0 0 10px; color: var(--blue-500); font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase; }
.map-card .region { display: flex; justify-content: space-between; gap: 14px; padding: 11px 0; border-bottom: 1px solid var(--rule-light); font-size: 14.5px; }
.map-card .region:last-child { border-bottom: none; }

/* ============ CTA BAND + FOOTER ============ */
.cta-band {
  position: relative;
  background:
    radial-gradient(80% 120% at 50% 0%, var(--glow-deep), transparent 62%),
    #02457A;
  color: #fff;
  text-align: center;
  padding: 72px 0;
  overflow: hidden;
}
.cta-band .wrap { position: relative; z-index: 1; }
.cta-band .eyebrow { color: #D6E8EE; }
.cta-band h2 { font-size: 28px; margin: 0 0 10px; }
.cta-band p { color: #D6E8EE; margin: 0 0 26px; }
.cta-band .cta-btn { background: #fff; color: var(--blue-ink); box-shadow: none; }
.cta-band .cta-btn:hover { background: var(--navy-900); color: #fff; }
footer.site { background: var(--navy-900); color: #B9CFE4; padding: 54px 0 28px; font-size: 14px; position: relative; overflow: hidden; }
footer.site::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--blue-500), transparent);
}
.foot-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 32px; padding-bottom: 30px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); }
.foot-grid h5 { color: #fff; font-size: 14px; margin: 0 0 14px; }
.foot-grid ul { list-style: none; padding: 0; margin: 0; }
.foot-grid li { margin-bottom: 9px; opacity: 0.85; transition: opacity 0.2s ease, transform 0.2s var(--ease), color 0.2s ease; }
.foot-grid li:hover { opacity: 1; transform: translateX(4px); color: var(--blue-500); }
.foot-bottom { padding-top: 22px; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px; font-size: 12.5px; opacity: 0.7; }

/* back-to-top */
.to-top {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 90;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(1, 138, 190, 0.4);
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
  color: var(--navy-900);
  font-size: 17px;
  cursor: pointer;
  display: grid;
  place-items: center;
  opacity: 0;
  transform: translateY(14px) scale(0.9);
  pointer-events: none;
  box-shadow: var(--sh-2);
  transition: opacity 0.3s ease, transform 0.3s var(--ease), background 0.25s ease;
}
.to-top.is-visible { opacity: 1; transform: none; pointer-events: auto; }
.to-top:hover { background: var(--blue-500); color: #fff; }

/* ============ KEYFRAMES ============
   Zero perpetual animations remain. What is left runs once (the corridor draw,
   the reveal transitions) or is driven by scroll position (progressGrow,
   stepIn, railFill), so nothing loops in the background.

   Cut across the motion and card passes: fadeUp, float, aurora, sweep,
   scanline, sheen, gridDrift, beam, ping, radar, twinkle, wheel,
   gradientShift, spinBorder, spin, bloom, marquee, ringSpin. */
@keyframes bloom {
  0% { transform: translate3d(0, 0, 0) scale(1); opacity: 0.85; }
  100% { transform: translate3d(4%, -3%, 0) scale(1.12); opacity: 1; }
}

/* ============ RESPONSIVE ============ */
/* the step columns are separated by a left hairline, so whichever item
   starts a row must drop its divider at every breakpoint */
@media (max-width: 1100px) {
  .services-grid { grid-template-columns: repeat(3, 1fr); row-gap: 8px; }
  .svc:nth-child(3n + 1) { border-left: 0; }
  .svc:nth-child(3n + 1)::after { left: 0; }
}
@media (max-width: 820px) {
  .incl-grid { grid-template-columns: 1fr; gap: 0; }
  /* the ledger's two columns stack, so the dividing rule becomes a top rule */
  .ledger-pair { grid-template-columns: 1fr; gap: 16px; }
  .ledger-pair > div + div { border-left: 0; padding-left: 0; border-top: 1px solid var(--rule); padding-top: 16px; }
  .spec-grid { grid-template-columns: 1fr; }
  .spec:nth-child(odd) { padding-right: 0; }
  .spec:nth-child(even) { padding-left: 0; border-left: 0; }
}

/* collapse the capsule into a toggle panel before links crowd the brand */
@media (max-width: 1180px) {
  .nav-toggle { display: flex; }
  nav.links {
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 2px;
    padding: 12px;
    border-radius: var(--r-md);
    background: #F4F8FB;
    border: 1px solid var(--border);
    box-shadow: var(--sh-3);
    clip-path: inset(0 0 100% 0 round var(--r-md));
    opacity: 0;
    pointer-events: none;
    transition: clip-path 0.4s var(--ease), opacity 0.25s ease;
  }
  header.site.nav-open nav.links { clip-path: inset(0 round var(--r-md)); opacity: 1; pointer-events: auto; }
  nav.links a { padding: 12px 14px; border-radius: var(--r-sm); font-size: 15px; }
  nav.links a::after { left: 14px; right: auto; width: 22px; bottom: 6px; }
}

@media (max-width: 1000px) {
  .stats-row { grid-template-columns: repeat(2, 1fr); gap: 26px 0; }
  .stat:nth-child(3) { border-left: none; padding-left: 0; }
}

@media (max-width: 1000px) {
  .hero-inner { grid-template-columns: 1fr; row-gap: 40px; }
  .route { padding-left: 26px; }
  .credit-grid { grid-template-columns: 1fr; gap: 22px; }
  .credit-cell + .credit-cell { border-left: 0; padding-left: 0; border-top: 1px solid var(--rule); padding-top: 20px; }
}

@media (max-width: 960px) {
  /* manifest rows lose the prose column: description drops under the title */
  .mf-row { grid-template-columns: 62px minmax(0, 1fr); }
  .mf-row p { grid-column: 2; }
  .pf-row { grid-template-columns: 1fr; gap: 12px; }
  .blog-row { grid-template-columns: 104px minmax(0, 1fr); }
  .blog-row p { grid-column: 2; }
  .practice { grid-template-columns: 1fr; gap: 18px; }
  .industry-index { grid-template-columns: repeat(2, 1fr); }
  .industry-index li:nth-child(3n + 1) { border-left: 1px solid var(--rule); }
  .industry-index li:nth-child(2n + 1) { border-left: 0; }
  /* the rail only reads as a timeline on one row — stack it vertically */
  .timeline { padding-top: 0; padding-left: 26px; }
  .timeline .rail { top: 0; bottom: 0; left: 5px; right: auto; width: 2px; height: auto; }
  /* stacked rail is a static connector: the fill animation is desktop-only */
  .timeline .rail i { width: 100%; height: 100%; }
  .svc .node { top: 26px; left: -26px; margin-left: 0; }
  .services-grid { grid-template-columns: repeat(2, 1fr); }
  .svc:nth-child(3n + 1) { border-left: 1px solid var(--border); }
  .svc:nth-child(2n + 1) { border-left: 0; }
  .svc:nth-child(2n + 1)::after { left: 0; }
  .about-grid { grid-template-columns: 1fr; }
  .foot-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 640px) {
  /* vertical-only reveal offsets: a horizontal pre-reveal translate on an
     element at the right edge briefly widens the document and flashes a
     horizontal scrollbar before the animation settles */
  html.js [data-reveal="left"],
  html.js [data-reveal="right"] { translate: 0 12px; }
  .wrap { padding-inline: 18px; }
  .hero { padding-top: 84px; }
  .hero h1 { font-size: 32px; }
  .services-grid, .foot-grid { grid-template-columns: 1fr; }
  /* single column: the record code sits above the title rather than beside it */
  .mf-row, .blog-row, .value-row, .roster-row { grid-template-columns: 1fr; gap: 8px; padding-left: 14px; }
  .mf-row p, .blog-row p { grid-column: 1; }
  .mf-row--action { padding-right: 40px; }
  .value-key, .blog-when { padding-top: 0; }
  .industry-index { grid-template-columns: 1fr; }
  .industry-index li:nth-child(n) { border-left: 0; }
  /* single column: separate the steps with a top rule instead of a side one.
     `:nth-child(n)` matches everything and only exists to match the specificity
     of the nth-child rules in the wider breakpoints, so source order decides */
  .svc:nth-child(n) { border-left: 0; border-top: 1px solid var(--border); padding-left: 26px; }
  .svc:first-child { border-top: 0; }
  .svc:nth-child(n)::after { left: 0; }
  .stats-row { grid-template-columns: 1fr 1fr; }
  .stat { padding-inline: 14px; }
  .stat-label { font-size: 12.5px; }
  .nav { padding: 8px 8px 8px 16px; gap: 12px; }
  .logo { font-size: 17px; }
  .logo small { font-size: 9.5px; }
  .nav-cta { display: none; }
  .nav-panel-cta { display: inline-flex; margin-top: 8px; }
  /* Both actions move into the panel together. The panel ground is light, so
     the reversed outline is overridden back to the dark-on-light variant. */
  .nav-contact { display: none; }
  nav.links a.nav-panel-contact {
    display: inline-flex;
    margin-top: 12px;
    border-color: var(--rule-2);
    background: none;
    color: var(--navy-900);
  }
  nav.links a.nav-panel-contact:hover { border-color: var(--blue-500); background: var(--tint); color: var(--blue-ink); }
  .hero-ctas { flex-direction: column; align-items: stretch; }
  .hero-ctas .cta-btn, .hero-ctas .cta-outline { width: 100%; }
  section { padding: 56px 0; }
  .to-top { right: 14px; bottom: 14px; }
}

@media (max-width: 380px) {
  .logo small { display: none; }
}

/* ============ SECTION "SEE ALL" LINKS ============ */
.section-more { display: flex; justify-content: center; margin-top: 34px; }
.section-more-left { justify-content: flex-start; margin-top: 24px; }
/* .cta-outline-light is declared with the button family above */

/* ============ BLOG ============ */
.blog-index { padding: 76px 0; }
/* the one feature surface on the index: it carries real art, so elevation here
   states hierarchy rather than decorating a row */
.blog-lead {
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 0;
  margin-bottom: 40px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: var(--sh-2);
  transition: box-shadow 0.3s ease, border-color 0.3s ease;
}
.blog-lead:hover { border-color: rgba(1, 138, 190, 0.4); box-shadow: var(--sh-3); }
.blog-lead-body { padding: 34px 34px 30px; }
.blog-lead-body h2 { margin: 14px 0 12px; font-size: 26px; line-height: 1.22; color: var(--navy-900); }
.blog-lead-body p { margin: 0 0 16px; color: var(--muted); font-size: 14.5px; }
.blog-lead-art {
  position: relative;
  display: grid;
  place-items: center;
  background: linear-gradient(140deg, #02457A 0%, #02457A 100%);
  overflow: hidden;
}
.blog-lead-art::after {
  content: "";
  position: absolute;
  inset: -30%;
  background: radial-gradient(closest-side, rgba(1, 138, 190, 0.42), transparent 70%);
}
.blog-lead-art span {
  position: relative;
  z-index: 1;
  font-size: 54px;
  font-weight: 800;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.9);
}
/* ---- BLOG INDEX: dated entries on rules, with the date in a mono gutter.
   The lead post above keeps its art panel and stays the one feature. ---- */
.blog-list { border-top: 1px solid var(--rule-2); }
.blog-row {
  position: relative;
  display: grid;
  grid-template-columns: 104px minmax(0, 0.95fr) minmax(0, 1.25fr);
  gap: 6px 28px;
  align-items: start;
  padding: 24px 20px 24px 18px;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  color: inherit;
  transition: background 0.3s ease;
}
.blog-row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--blue-500);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.35s var(--ease);
}
.blog-row:hover { background: var(--tint); }
.blog-row:hover::before { transform: scaleY(1); }
.blog-when {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--muted);
  padding-top: 4px;
  font-variant-numeric: tabular-nums;
}
.blog-row h3 { margin: 0 0 6px; font-size: 17.5px; line-height: 1.3; color: var(--navy-900); }
.blog-row:hover h3 { color: var(--blue-ink); }
.blog-row p { margin: 0; font-size: 14px; color: var(--muted); }
.blog-meta { display: block; margin-top: 6px; font-family: var(--mono); font-size: 11px; color: var(--muted); }
.blog-lead .pf-badge { color: var(--blue-ink); }
.blog-lead .pf-link { color: var(--blue-ink); border-color: rgba(1, 106, 147, 0.4); }
.blog-lead .pf-link:hover { color: var(--navy-900); border-color: var(--navy-900); }

/* ============ BLOG POST ============ */
.post { padding: 70px 0 20px; }
.post-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 48px; align-items: start; }
.post-body { max-width: 720px; font-size: 16px; line-height: 1.78; color: #2B3D5C; }
.post-body .post-lead { font-size: 18.5px; line-height: 1.62; color: var(--navy-900); font-weight: 500; }
.post-body h3 { margin: 34px 0 12px; font-size: 20px; color: var(--navy-900); letter-spacing: -0.01em; }
.post-body p { margin: 0 0 18px; }
.post-body img { max-width: 100%; height: auto; border-radius: 8px; }
.post-body figure.article-photo { margin: 28px 0; text-align: center; }
.post-body figure.article-photo img { width: 100%; border-radius: 8px; border: 1px solid var(--border); box-shadow: 0 4px 14px rgba(0,0,0,0.06); }
.post-body figure.article-photo figcaption { margin-top: 8px; font-size: 13px; color: var(--muted); font-style: italic; }
.post-aside { position: sticky; top: calc(var(--header-h) + 30px); }
.post-cta {
  padding: 30px 28px;
  border: 1px solid rgba(1, 138, 190, 0.22);
  border-radius: var(--r-md);
  background: linear-gradient(160deg, var(--navy-900), #001B48);
  color: #fff;
}
.post-cta h4 { margin: 0 0 10px; font-size: 17px; }
.post-cta p { margin: 0 0 18px; font-size: 13.5px; color: rgba(226, 238, 253, 0.78); }
.post-next { padding: 46px 0 76px; border-top: 1px solid var(--border); margin-top: 40px; }
.post-next h4 { margin: 0 0 20px; font-size: 14px; text-transform: uppercase; letter-spacing: 0.14em; color: var(--muted); }

/* ============ FORMS / CONTACT ============ */
.form-section { padding: 70px 0 86px; }
.form-grid { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: 34px; align-items: start; }
/* forms are the one place a raised surface earns itself: it marks the area you
   type into as distinct from the page around it */
.form-card {
  padding: 32px 30px;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: var(--sh-2);
}
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.field { display: block; margin-bottom: 18px; }
.field > span { display: block; margin-bottom: 7px; font-size: 13px; font-weight: 600; color: var(--navy-900); }
.field > span i { color: var(--blue-200); font-style: normal; }
.field input, .field select, .field textarea {
  width: 100%;
  padding: 12px 14px;
  font: inherit;
  font-size: 14.5px;
  color: var(--ink);
  background: #FAFCFE;
  border: 1px solid var(--rule-2);
  border-radius: var(--r-sm);
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}
.field textarea { resize: vertical; min-height: 110px; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  background: #fff;
  border-color: var(--blue-500);
  box-shadow: 0 0 0 4px rgba(1, 138, 190, 0.14);
}
.field.has-error input { border-color: #d9534f; background: #fff8f8; }
.field-error { display: block; margin-top: 6px; font-size: 12px; font-style: normal; color: #c0392b; }
.form-alert {
  margin-bottom: 22px;
  padding: 12px 16px;
  font-size: 13.5px;
  color: #a03027;
  background: #fdeeec;
  border: 1px solid #f6cfca;
  border-radius: var(--r-sm);
}
.form-note { margin: 14px 0 0; font-size: 12.5px; color: var(--muted); }
.form-aside { padding: 4px 0 0; }
.form-aside h4 { margin: 0 0 16px; font-size: 17px; color: var(--navy-900); }
.steps-list { margin: 0 0 28px; padding-left: 20px; }
.steps-list li { margin-bottom: 13px; font-size: 14px; color: var(--muted); line-height: 1.6; }
.steps-list strong { color: var(--navy-900); }
.aside-contact { padding: 20px 0 0; border-top: 1px solid var(--rule-2); }
.aside-contact h5 { margin: 0 0 10px; font-size: 13px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted); }
.aside-contact p { margin: 0 0 8px; font-size: 15px; font-weight: 600; color: var(--navy-900); }
.aside-contact .muted { font-size: 13px; font-weight: 400; color: var(--muted); }

.contact-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; }
/* contact details are a list of facts, so they are set as a ledger rather than
   boxed. Only the accent variant becomes a surface. */
.contact-card { padding: 24px 0 0; border-top: 1px solid var(--rule-2); }
.contact-card h3 { margin: 12px 0 18px; font-size: 22px; color: var(--navy-900); }
.contact-list { list-style: none; margin: 0; padding: 0; }
.contact-list li {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 13px 0;
  border-bottom: 1px solid var(--rule);
  font-size: 14.5px;
}
.contact-list li:last-child { border-bottom: 0; }
.contact-list span { color: var(--muted); }
.contact-list strong { color: var(--navy-900); text-align: right; }
.contact-card-accent {
  padding: 30px 28px;
  background: linear-gradient(160deg, var(--navy-900), #001B48);
  border: 1px solid rgba(1, 138, 190, 0.22);
  border-radius: var(--r-md);
  color: #fff;
}
.contact-card-accent h3 { color: #fff; }
.contact-card-accent p { color: rgba(226, 238, 253, 0.8); font-size: 14.5px; margin: 0 0 20px; }

/* ============ THANKS / 404 ============ */
/* no box: rules above and below do the framing */
.thanks-card {
  max-width: 620px;
  margin: 0 auto;
  padding: 46px 0;
  text-align: center;
  border-top: 1px solid var(--rule-2);
  border-bottom: 1px solid var(--rule-2);
}
.thanks-mark {
  width: 52px;
  height: 52px;
  margin: 0 auto 22px;
  display: grid;
  place-items: center;
  font-size: 22px;
  font-weight: 600;
  color: var(--blue-ink);
  border: 1px solid var(--rule-2);
  border-radius: var(--r-sm);
  background: var(--tint);
}
.thanks-mark-muted { color: var(--muted); background: rgba(0, 27, 72, 0.04); }
.thanks-card h2 { margin: 0 0 14px; font-size: 26px; color: var(--navy-900); }
.thanks-card p { margin: 0 0 26px; color: var(--muted); }
.thanks-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* ---- mail handoff ----
   The thanks card centres its text, so the copied message has to opt back
   out: a mail body reads as a block of labelled lines, not as poetry.
   .thanks-card p already sets a margin, so the meta line is qualified by
   the card to outrank it rather than reaching for !important. */
.mail-handoff { margin: 0 0 24px; }
.mail-copy { max-width: 520px; margin: 18px auto 0; text-align: left; }
.mail-copy > summary {
  cursor: pointer;
  list-style: none;
  text-align: center;
  padding: 6px 0;
  font-size: 12.5px;
  color: var(--blue-ink);
}
.mail-copy > summary::-webkit-details-marker { display: none; }
.mail-copy > summary::after { content: ' ↓'; }
.mail-copy[open] > summary::after { content: ' ↑'; }
.mail-copy > summary:hover { text-decoration: underline; }
.thanks-card .mail-meta {
  margin: 14px 0 10px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--muted);
}
.mail-meta strong { color: var(--navy-900); font-weight: 600; }
.mail-body {
  /* No max-height: this is the message the reader is about to send, so
     clipping it behind a nested scrollbar hid the closing line and read as
     truncation. The 900-char server-side cap in buildMail bounds the height
     instead. */
  margin: 0 0 14px;
  padding: 14px 16px;
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.65;
  color: var(--navy-900);
  background: var(--tint);
  border: 1px solid var(--rule-2);
  border-radius: var(--r-chip);
  white-space: pre-wrap;
  word-break: break-word;
}

@media (max-width: 900px) {
  .post-wrap { grid-template-columns: 1fr; gap: 32px; }
  .post-aside { position: static; }
  .form-grid { grid-template-columns: 1fr; }
  .blog-lead { grid-template-columns: 1fr; }
  .blog-lead-art { min-height: 150px; order: -1; }
}

@media (max-width: 620px) {
  .page-hero { padding: calc(var(--header-h) + 66px) 0 54px; }
  .field-row { grid-template-columns: 1fr; gap: 0; }
  .form-card, .contact-card, .thanks-card { padding: 26px 20px; }
  .blog-lead-body { padding: 26px 22px; }
}

/* ============ VALUES (mission / vision / values) ============ */
.values-band { padding: 76px 0 10px; }
/* Same ruled language as the manifest, cut wider: a broad label gutter with the
   claim and its body stacked in the main column. Three entries, so rows read
   better than columns. */
.values-list { border-top: 1px solid var(--rule-2); }
.value-row {
  position: relative;
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  gap: 4px 30px;
  padding: 26px 20px 26px 18px;
  border-bottom: 1px solid var(--rule);
  transition: background 0.3s ease;
}
.value-row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--blue-500);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.35s var(--ease);
}
.value-row:hover { background: var(--tint); }
.value-row:hover::before { transform: scaleY(1); }
.value-key {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blue-ink);
  padding-top: 6px;
}
.value-row h3 { margin: 0 0 8px; font-size: 19px; line-height: 1.3; color: var(--navy-900); }
.value-row p { margin: 0; font-size: 14.5px; color: var(--muted); max-width: 68ch; }

/* ============ APPROACH ============ */
.approach { padding: 72px 0; }
.approach-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 46px; align-items: start; }
.approach-grid p { color: var(--muted); font-size: 15.5px; }
.approach-list { list-style: none; margin: 0; padding: 0; }
.approach-list li {
  position: relative;
  padding: 18px 0 18px 34px;
  border-bottom: 1px solid var(--rule);
}
.approach-list li:last-child { border-bottom: 0; }
.approach-list li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 25px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--blue-500);
  box-shadow: 0 0 0 4px rgba(1, 138, 190, 0.16);
}
.approach-list strong { display: block; margin-bottom: 4px; font-size: 15px; color: var(--navy-900); }
.approach-list span { font-size: 14px; color: var(--muted); }

/* ============ TEAM ============ */
.team-section { padding: 76px 0; }
/* A roster, read across: monogram, then who they are, then what they do. The
   monogram is a squared plate rather than an avatar circle, which keeps it in
   the same geometry as the rules around it. */
.roster { border-top: 1px solid var(--rule-2); }
.roster-row {
  position: relative;
  display: grid;
  grid-template-columns: 54px minmax(0, 250px) minmax(0, 1fr);
  gap: 4px 26px;
  align-items: start;
  padding: 24px 20px 24px 18px;
  border-bottom: 1px solid var(--rule);
  transition: background 0.3s ease;
}
.roster-row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--blue-500);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.35s var(--ease);
}
.roster-row:hover { background: var(--tint); }
.roster-row:hover::before { transform: scaleY(1); }
.team-avatar {
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--blue-ink);
  border: 1px solid var(--rule-2);
  border-radius: var(--r-sm);
  background: var(--tint);
}
.roster-row h3 { margin: 0 0 4px; font-size: 17px; color: var(--navy-900); }
.team-role { display: block; font-size: 12.5px; font-weight: 500; color: var(--muted); }
.team-link {
  display: inline-block;
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--blue-ink);
  border-bottom: 1px solid rgba(1, 106, 147, 0.4);
  padding-bottom: 1px;
}
.team-link::after { content: " \2197"; }
.team-link:hover { color: var(--navy-900); border-color: var(--navy-900); }
.roster-row p { margin: 0; font-size: 14.5px; color: var(--muted); padding-top: 2px; }

/* ============ SERVICE DETAIL ============ */
/* ---- practices: ruled bands, name and summary left, capabilities right.
   The 01-04 numerals are gone: four practices are a set, not a sequence, so
   numbering them was decoration rather than information. ---- */
.svc-detail { padding: 76px 0; }
.practice-list { border-top: 1px solid var(--rule-2); }
.practice {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: 20px 44px;
  padding: 32px 20px 32px 18px;
  border-bottom: 1px solid var(--rule);
  transition: background 0.3s ease;
}
.practice::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--blue-500);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.35s var(--ease);
}
.practice:hover { background: var(--tint); }
.practice:hover::before { transform: scaleY(1); }
.practice h3 { margin: 0 0 10px; font-size: 21px; line-height: 1.25; color: var(--navy-900); }
.practice > div > p { margin: 0; font-size: 14.5px; color: var(--muted); max-width: 46ch; }
.practice-points { list-style: none; margin: 0; padding: 0; align-self: start; }
.practice-points li {
  padding: 10px 0;
  font-size: 14px;
  color: var(--muted);
  border-bottom: 1px solid var(--rule);
}
.practice-points li:last-child { border-bottom: 0; }
.practice-points strong { display: block; color: var(--navy-900); font-weight: 600; font-size: 14px; }

/* ============ INDUSTRY DETAIL ============ */
/* ---- LEDGER: the constraint and what we run against it, set as two columns
   divided by a vertical rule. The pairing is the content, so the layout states
   it directly instead of stacking two labelled blocks inside a card. ---- */
.ind-detail { padding: 76px 0 30px; }
.ind-group + .ind-group { margin-top: 0; }
/* the two groups alternate ground, so a long page of ledgers has a rhythm */
.ind-group { padding: 56px 0; }
.ind-group--dark {
  color: #fff;
  --rule: var(--rule-light);
  --rule-2: var(--rule-light-2);
  --tint: rgba(255, 255, 255, 0.055);
  --navy-900: #ffffff;
  --muted: var(--on-dark-mute);
  --blue-ink: var(--blue-lift);
  background:
    radial-gradient(70% 90% at 88% 0%, var(--glow-deep), transparent 60%),
    #02457A;
  /* the ledger runs edge to edge on its own ground */
  margin-inline: calc(50% - 50vw);
  padding-inline: calc(50vw - 50%);
}
.ledger { border-top: 1px solid var(--rule-2); }
.ledger-row {
  position: relative;
  padding: 26px 20px 26px 18px;
  border-bottom: 1px solid var(--rule);
  transition: background 0.3s ease;
}
.ledger-row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--blue-500);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.35s var(--ease);
}
.ledger-row:hover { background: var(--tint); }
.ledger-row:hover::before { transform: scaleY(1); }
.ledger-row h3 {
  margin: 0 0 16px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--navy-900);
}
.ledger-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 0 36px; }
.ledger-pair > div + div { border-left: 1px solid var(--rule); padding-left: 36px; }
.ledger-lab {
  display: block;
  margin-bottom: 6px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blue-ink);
}
.ledger-pair p { margin: 0; font-size: 14.5px; color: var(--muted); }

/* ============ PRODUCT SPOTLIGHT (RC-Vision) ============ */
.spotlight { padding: 76px 0; }
.spotlight-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: 46px; align-items: center; }
.spotlight-lead { font-size: 17px; color: var(--navy-900); font-weight: 500; }
.spotlight-grid p { color: var(--muted); font-size: 15.5px; }
.spotlight-ctas { margin-top: 26px; }
/* ---- RC-Vision capabilities: a two-column spec grid on rules. Denser than the
   manifest rows, because these are short entries read as a block. ---- */
.spec-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  border-top: 1px solid var(--rule-2);
}
.spec {
  padding: 16px 0;
  border-bottom: 1px solid var(--rule);
  transition: background 0.25s ease;
}
.spec:nth-child(odd) { padding-right: 24px; }
.spec:nth-child(even) { padding-left: 24px; border-left: 1px solid var(--rule); }
.spec strong { display: block; margin-bottom: 5px; font-size: 14.5px; color: var(--navy-900); }
.spec span { font-size: 13.5px; color: var(--muted); line-height: 1.55; }

/* ============ INCLUSIONS ============ */
/* ---- INCLUSIONS: a checklist, not eight more boxes. Rows on a hairline
   grid; the tick fills in and the row slides on hover. ---- */
.inclusions { padding: 76px 0; }
.incl-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0 44px;
  border-top: 1px solid var(--rule-2);
}
.incl-card {
  display: flex;
  gap: 14px;
  padding: 20px 8px 20px 4px;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--rule);
  border-radius: 0;
  transition: transform 0.35s var(--ease);
}
.incl-card:hover { transform: translateX(6px); }
.incl-check {
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 1px;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--blue-ink);
  border-radius: 50%;
  border: 1.5px solid rgba(1, 138, 190, 0.45);
  background: transparent;
  transition: background 0.35s ease, color 0.35s ease, border-color 0.35s ease, transform 0.35s var(--ease);
}
.incl-card:hover .incl-check {
  color: #fff;
  border-color: transparent;
  background: linear-gradient(140deg, var(--blue-500), var(--blue-ink));
  transform: scale(1.12) rotate(-8deg);
}
.incl-card h4 { margin: 0 0 6px; font-size: 15px; color: var(--navy-900); }
.incl-card p { margin: 0; font-size: 13.5px; color: var(--muted); }

/* ============ FAQ ============ */
.faq-section { padding: 60px 0 80px; }
.faq-wrap { max-width: 880px; }
/* de-boxed: rules only, and the open row carries the tint the manifest uses */
.faq-list { border-top: 1px solid var(--rule-2); }
.faq-item {
  background: none;
  border: 0;
  border-bottom: 1px solid var(--rule);
  border-radius: 0;
  transition: background 0.3s ease;
}
.faq-item[open] { background: var(--tint); }
.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 19px 20px 19px 18px;
  cursor: pointer;
  font-size: 15.5px;
  font-weight: 600;
  color: var(--navy-900);
  list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--blue-ink); }
.faq-mark {
  position: relative;
  flex: none;
  width: 15px;
  height: 15px;
}
.faq-mark::before, .faq-mark::after {
  content: "";
  position: absolute;
  background: var(--blue-500);
  border-radius: 2px;
  transition: transform 0.3s var(--ease), opacity 0.3s ease;
}
.faq-mark::before { top: 6.5px; left: 0; width: 15px; height: 2px; }
.faq-mark::after { left: 6.5px; top: 0; width: 2px; height: 15px; }
.faq-item[open] .faq-mark::after { transform: scaleY(0); opacity: 0; }
.faq-answer { padding: 0 22px 20px; }
.faq-answer p { margin: 0; font-size: 14.5px; color: var(--muted); }

/* ============ FORM EXTRAS ============ */
.form-title { margin: 0 0 20px; font-size: 20px; color: var(--navy-900); }
.form-aside .aside-contact + .aside-contact { margin-top: 16px; }
.aside-contact a { color: var(--navy-900); text-decoration: none; border-bottom: 1px solid rgba(1, 138, 190, 0.45); }
.aside-contact a:hover { color: var(--blue-ink); }
.aside-contact .social-icons { margin-top: 14px; }
.social-list,
.social-icons { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.social-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: #fff;
  color: var(--navy-900);
  text-decoration: none;
  box-shadow: var(--lift-1);
  transition: border-color 0.25s ease, color 0.25s ease, background 0.25s ease, transform 0.25s var(--ease), box-shadow 0.25s ease;
}
.social-icon-btn svg {
  width: 18px;
  height: 18px;
  display: block;
}
.social-icon-btn:hover {
  border-color: var(--blue-500);
  color: var(--blue-ink);
  background: var(--tint);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(1, 138, 190, 0.16);
}
.social-list a:not(.social-icon-btn) {
  display: inline-block;
  padding: 7px 12px;
  font-size: 13px;
  font-weight: 600;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  color: var(--navy-900);
  text-decoration: none;
  transition: border-color 0.25s ease, color 0.25s ease, transform 0.25s var(--ease);
}
.social-list a:not(.social-icon-btn):hover { border-color: var(--blue-500); color: var(--blue-ink); transform: translateY(-2px); }
.form-note a { color: var(--blue-ink); }

@media (max-width: 980px) {
  .approach-grid, .spotlight-grid { grid-template-columns: 1fr; gap: 30px; }
  .practice { grid-template-columns: 1fr; gap: 18px; }
}

/* ============ PORT SCENE ============
   Freight imagery for the heroes, drawn rather than photographed (server.js
   composes it). Three depth layers, each a flat fill: the illusion of distance
   is opacity and scale, not detail, which is why it stays clean when a 1600px
   field is painted into a 380px hero.

   It sits ABOVE the scrim, at the same layer as the node mesh. Under the scrim
   the near layer measured as a grey smear. The contrast that costs is paid for
   by the horizontal mask in the SVG, which holds the scene near-transparent
   across the headline column and only brings it up under the empty right. */
.hero-scene {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 0;
  width: 100%;
  height: clamp(190px, 30vw, 336px);
  pointer-events: none;
}
.hero-scene--compact { height: clamp(120px, 18vw, 200px); }
/* Raised across the board. At the previous values the scene was technically
   present and practically invisible — it read as a smudge on the gradient
   rather than as a port. The two masks in the SVG are what buy the headroom:
   they hold it back over the copy, so the fills can be strong where there is
   nothing to protect. */
.ps-far  { fill: rgba(151, 202, 219, 0.26); }
.ps-mid  { fill: rgba(126, 205, 236, 0.40); }
.ps-near { fill: rgba(219, 236, 243, 0.55); }
.ps-water rect:first-child { fill: rgba(1, 138, 190, 0.30); }
.ps-water rect + rect { fill: rgba(226, 240, 246, 0.38); }

/* ============ NAV CONTACT ============
   An outline button rather than an eighth text link. The row already
   hamburgers at 1180px and another link would push that further into the
   desktop band; as a button it also reads as an action, which is what it is. */
.nav-contact { flex-shrink: 0; padding: 9px 14px; font-size: 13.5px; white-space: nowrap; }
.nav-contact.is-active { border-color: rgba(255, 255, 255, 0.72); background: rgba(255, 255, 255, 0.20); }
/* Docked, the capsule turns white, so the reversed outline would vanish into
   it — the same swap the language switcher and the toggle already make. */
header.site.is-scrolled .nav-contact {
  border-color: var(--rule-2);
  background: none;
  color: var(--navy-900);
}
header.site.is-scrolled .nav-contact:hover,
header.site.is-scrolled .nav-contact.is-active {
  border-color: var(--blue-500);
  background: var(--tint);
  color: var(--blue-ink);
}
.nav-panel-contact { display: none; }

/* ============ CUSTOMER BAND ============
   Kept apart from the credential strip above it. That strip says who
   authorizes us and what we build; this says who we run in production for,
   and folding the two together blurs a claim that has to stay precise. */
.customer-band {
  padding: 26px 0;
  background: var(--white);
  border-bottom: 1px solid var(--rule);
}
.customer-grid { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 44px; }
.customer-band .credit-label { margin-bottom: 0; flex: none; }
.customer-logos { display: flex; align-items: center; flex-wrap: wrap; gap: 14px 46px; }
.cust { display: flex; align-items: center; }
.cust-img { height: 30px; width: auto; object-fit: contain; }
/* No logo file supplied, so a typographic lockup rather than an invented mark.
   Sized to sit at the same optical weight a real logo would. */
.cust-lockup { display: flex; flex-direction: column; gap: 2px; }
.cust-name {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1;
  color: var(--navy-900);
}
.cust-sub {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blue-ink);
}

/* ============ POSITIONING BAND ============ */
.pos-band { padding: 76px 0 72px; }
.pos-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
  gap: 50px;
  align-items: start;
}
.pos-lead {
  margin: 0 0 16px;
  font-size: 17.5px;
  line-height: 1.5;
  font-weight: 500;
  color: var(--navy-700);
  max-width: 40ch;
}
.pos-grid > div > p:last-child { color: var(--muted); font-size: 15.5px; margin: 0; }
.pos-pillars { border-top: 1px solid var(--rule-2); }
.pos-pillar {
  position: relative;
  padding: 22px 20px 22px 18px;
  border-bottom: 1px solid var(--rule);
  transition: background 0.3s ease;
}
.pos-pillar::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--blue-500);
  transform: scaleY(0);
  transform-origin: 50% 0;
  transition: transform 0.35s var(--ease);
}
.pos-pillar:hover { background: var(--tint); }
.pos-pillar:hover::before { transform: scaleY(1); }
.pos-key {
  display: block;
  margin-bottom: 8px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--blue-ink);
}
.pos-pillar h3 { margin: 0 0 6px; font-size: 17px; color: var(--navy-900); }
.pos-pillar p { margin: 0; font-size: 14.5px; color: var(--muted); }

/* ============ CAPABILITY GRID ============
   Seven cards, and seven is an awkward number in any even grid. The Magaya
   card spans two so the count resolves to eight cells at every breakpoint —
   which also puts the platform card at the weight it should carry. */
.cap-section { padding: 76px 0; }
.cap-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }
.cap-card {
  position: relative;
  padding: 24px 22px 22px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  transition: transform 0.3s var(--ease), box-shadow 0.3s ease, border-color 0.3s ease;
}
.cap-card:hover {
  transform: translateY(-3px);
  border-color: rgba(1, 138, 190, 0.42);
  box-shadow: var(--lift-2);
}
.cap-card--core {
  background: linear-gradient(146deg, var(--navy-900), var(--navy-700));
  border-color: transparent;
}
.cap-rec {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  color: var(--muted);
}
.cap-card--core .cap-rec { color: var(--blue-200); }
.cap-glyph {
  position: absolute;
  top: 21px;
  right: 20px;
  width: 21px;
  height: 21px;
  color: var(--blue-500);
}
.cap-card--core .cap-glyph { color: var(--blue-lift); }
.cap-glyph svg { display: block; width: 100%; height: 100%; }
.cap-card h3 {
  margin: 10px 0 8px;
  font-size: 18px;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--navy-900);
}
.cap-card p { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--muted); }
.cap-card--core h3 { color: #fff; font-size: 21px; }
.cap-card--core p { color: var(--on-dark); }
.cap-points {
  list-style: none;
  margin: 16px 0 0;
  padding: 14px 0 0;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}
.cap-card--core .cap-points { border-top-color: var(--rule-light); }
.cap-points li {
  padding: 5px 10px;
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.3;
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  color: var(--navy-700);
}
.cap-card--core .cap-points li { border-color: var(--rule-light-2); color: var(--blue-050); }

/* ============ STRENGTHS AND BENEFITS ============
   One section, two lanes: what we bring, and what it changes. Split across two
   stacked bands they read as two lists; side by side they read as a claim and
   its consequence, which is the argument being made. */
.value-prop { padding: 76px 0; }
.vp-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 46px; }
.vp-lane--out { border-left: 1px solid var(--rule); padding-left: 46px; }
.vp-lane-head {
  margin: 0 0 6px;
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--blue-ink);
}
.vp-list { list-style: none; margin: 0; padding: 0; }
.vp-list li {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  gap: 14px;
  align-items: start;
  padding: 18px 0;
  border-bottom: 1px solid var(--rule);
}
.vp-list li:last-child { border-bottom: 0; }
.vp-mark {
  width: 20px;
  height: 20px;
  margin-top: 2px;
  color: var(--blue-500);
}
.vp-lane--out .vp-mark { color: var(--navy-700); }
.vp-mark svg { display: block; width: 100%; height: 100%; }
.vp-list strong { display: block; margin-bottom: 4px; font-size: 15.5px; font-weight: 600; color: var(--navy-900); }
.vp-list span { display: block; font-size: 14.5px; line-height: 1.55; color: var(--muted); }

/* ============ OFFICE MAP ============ */
.map-section { padding: 72px 0; }
.map-head {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 26px;
  margin-bottom: 26px;
}
.map-head p { margin: 12px 0 0; font-size: 15px; color: var(--muted); max-width: 54ch; }
.map-head .cta-outline { flex: none; }
.map-embed {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--lift-1);
  /* a fixed ratio rather than a fixed height, so the frame never letterboxes
     the tiles on a phone or leave a strip of grey on a wide desktop */
  aspect-ratio: 16 / 7;
  background: var(--blue-050);
}
/* The tile grid is absolutely positioned and offset by the server so the pin
   lands dead centre whatever width the frame resolves to. Wider viewports
   simply reveal more map, which is the correct behaviour for a location. */
.map-plane { position: absolute; inset: 0; display: block; overflow: hidden; }
.map-tiles { position: absolute; left: 50%; top: 50%; display: block; }
.map-tiles img { position: absolute; display: block; }
/* a drawn pin, so the marker needs no image request of its own */
.map-pin {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 22px;
  height: 22px;
  margin: -11px 0 0 -11px;
  border-radius: 50%;
  background: var(--blue-cta);
  border: 3px solid #fff;
  box-shadow: 0 2px 10px rgba(0, 27, 72, 0.45), 0 0 0 8px rgba(1, 138, 190, 0.22);
}
.map-plane:hover .map-pin { box-shadow: 0 2px 10px rgba(0, 27, 72, 0.45), 0 0 0 13px rgba(1, 138, 190, 0.26); }
.map-pin, .map-plane:hover .map-pin { transition: box-shadow 0.3s var(--ease); }
.map-credit {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  margin: 12px 0 0;
  font-size: 12.5px;
  color: var(--muted);
}
.map-credit a { color: var(--blue-ink); border-bottom: 1px solid rgba(1, 138, 190, 0.4); }
.map-credit a:hover { color: var(--navy-900); }

@media (min-width: 700px) {
  .cap-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cap-card--core { grid-column: 1 / -1; }
}
@media (min-width: 1080px) {
  .cap-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .cap-card--core { grid-column: span 2; }
}
@media (max-width: 980px) {
  .pos-grid { grid-template-columns: 1fr; gap: 30px; }
}
@media (max-width: 900px) {
  .vp-grid { grid-template-columns: 1fr; gap: 34px; }
  .vp-lane--out { border-left: 0; padding-left: 0; border-top: 1px solid var(--rule); padding-top: 30px; }
}
@media (max-width: 760px) {
  .map-head { flex-direction: column; align-items: start; }
  .map-embed { aspect-ratio: 4 / 3; }
  .customer-grid { gap: 14px; }
}

/* ============ MOTION SAFETY ============ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  html.js [data-reveal] { opacity: 1 !important; translate: none !important; scale: none !important; }
  html.js [data-split] .word { opacity: 1 !important; translate: none !important; }
  /* the corridor is shown drawn rather than animating. scaleY, not scaleX: the
     rail runs vertically now, and scaleX(1) left it collapsed and invisible. */
  .route-nodes::after { animation: none; transform: scaleY(1); }
  .credit-track { animation: none; }
  .value-card:hover { transform: none; }
  /* the progress bar reads as motion the user did not ask for */
  .scroll-progress { display: none; }
}

/* ============ RESPONSIVE, LATE ============
   These row components are declared after the main responsive block, so their
   base rules were winning on source order and the mobile collapse never
   applied. Declaring the collapse last fixes it without specificity hacks. */
@media (max-width: 1000px) {
  .roster-row { grid-template-columns: 46px minmax(0, 1fr); }
  .roster-row p { grid-column: 2; }
}
@media (max-width: 640px) {
  .mf-row,
  .blog-row,
  .value-row,
  .roster-row { grid-template-columns: 1fr; gap: 8px; padding-left: 14px; }
  .mf-row p,
  .blog-row p,
  .roster-row p { grid-column: 1; }
  .mf-row--action { padding-right: 40px; }
  .value-key,
  .blog-when { padding-top: 0; }
  .ledger-pair { grid-template-columns: 1fr; gap: 16px; }
  .ledger-pair > div + div { border-left: 0; padding-left: 0; border-top: 1px solid var(--rule); padding-top: 16px; }
  .spec-grid { grid-template-columns: 1fr; }
  .spec:nth-child(odd) { padding-right: 0; }
  .spec:nth-child(even) { padding-left: 0; border-left: 0; }
  .page-hero-inner { padding: 124px 0 62px; }
  .hero-inner { padding: 118px 0 34px; }
}

/* The home hero's two columns never collapsed.
   .hero-grid-2 is minmax(0, 1.32fr) / minmax(0, 0.52fr) with no override at
   any width, so at 390px the card column resolved to 86px while its content
   needed 192px: the three cards were squeezed and clipped. Nothing scrolled
   sideways, so it failed silently. Declared here, last, for the same
   source-order reason as the rows above. */
@media (max-width: 1000px) {
  .hero-grid-2 {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 30px;
  }
  /* Two across while there is width for it. The coverage card carries three
     rows of labelled text and reads badly in a narrow column, so it spans. */
  .card-stack {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
  }
  .card-stack > .hcard-route { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .card-stack { grid-template-columns: minmax(0, 1fr); }
}

/* Both hero scrims are angled for a wide hero: they shield the left column and
   let the right stay bright for the card rail. Once the hero collapses to one
   column that assumption breaks — the headline spans the full width, so the
   angled falloff left "Europe" on the third line sitting over a bright wash at
   1.43:1 against a 3.0 floor. Pre-existing, and invisible to the pixel suite
   because it only sampled 1440px. Shield the whole width instead; the node
   mesh sits above the scrim, so darkening this does not flatten the hero. */
@media (max-width: 1000px) {
  .hero-scrim {
    background: linear-gradient(178deg,
      rgba(0, 20, 55, 0.90) 0%,
      rgba(0, 20, 55, 0.80) 50%,
      rgba(0, 20, 55, 0.90) 100%);
  }
  .hero-scrim::after {
    background: linear-gradient(178deg,
      rgba(0, 17, 46, 0.62) 0%,
      rgba(0, 17, 46, 0.50) 55%,
      rgba(0, 17, 46, 0.62) 100%);
  }
}

/* Narrow widths collapse the hero to one column, so the headline now runs
   across the full width — including the right side the scene mask keeps at
   full strength. The mask is horizontal and cannot know that, so the whole
   scene steps back instead. Declared last for the same source-order reason as
   the hero-grid collapse above. */
@media (max-width: 1000px) {
  .hero-scene { opacity: 0.84; height: clamp(148px, 26vw, 220px); }
  .hero-scene--compact { opacity: 0.7; height: clamp(96px, 17vw, 150px); }
}
@media (max-width: 640px) {
  .hero-scene { opacity: 0.66; }
  .cap-card { padding: 20px 18px 18px; }
  .cap-card--core h3 { font-size: 19px; }
  .vp-list li { grid-template-columns: 22px minmax(0, 1fr); gap: 11px; }
}
