/* ===========================================================================
   Vāruni Systems — design system
   ---------------------------------------------------------------------------
   Light-first. The page is paper; red is the only accent, used sparingly enough
   that it still means something when it appears. A handful of bands invert to
   near-black (.invert) to break the rhythm, and the closing call to action is
   the brand's red slide.

   The layout is a nautical chart: sheet labels, sounding rules, coordinate
   readouts. The palette is the brand manual's — red, black, grey, white — with
   the secondary tan standing in for the brass an admiralty chart would use.

   Contrast (WCAG 2.1 AA):
     ink   #0B0B0D on paper #F8F8F8   18.9:1   headings and body
     muted #5A5A5A on paper           6.5:1    secondary copy
     tan-d #7A5B3E on paper           5.8:1    instrument annotations
     red   #ED1C24 on paper           4.1:1    LARGE TEXT ONLY (>=24px, or
                                               >=18.66px bold) — never body copy
     white #FFFFFF on red             4.4:1    large text only; buttons are 19px
                                               semibold, which qualifies
   The red CTA band therefore sets its body copy in near-black (5.8:1 on red),
   not white. The brand manual also forbids the logo on a red ground, so no
   band carrying the mark is ever red.
   ========================================================================= */

/* ------------------------------------------------------------------ fonts */
/* Self-hosted: a defence contractor selling "no data leaves your perimeter"
   should not phone Google for a font on every page load. */

@font-face {
  font-family: 'Antonio';
  src: url('/fonts/antonio-var.woff2') format('woff2-variations');
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Open Sauce One';
  src: url('/fonts/OpenSauceOne-Regular.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Open Sauce One';
  src: url('/fonts/OpenSauceOne-Medium.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Open Sauce One';
  src: url('/fonts/OpenSauceOne-SemiBold.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Open Sauce One';
  src: url('/fonts/OpenSauceOne-Bold.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}

/* ----------------------------------------------------------------- tokens */

:root {
  /* brand — primary */
  --red:        #ED1C24;
  --red-deep:   #C4141B;
  --black:      #000000;
  --grey:       #7A7A7A;
  --white:      #FFFFFF;

  /* brand — secondary */
  --grey-light: #E0E0E0;
  --charcoal:   #403B35;
  --maroon:     #6D0013;
  --beige:      #DCD7D0;
  --navy:       #030153;
  --tan:        #AC896B;

  /* roles — light ground (the default) */
  --bg:         #F8F8F8;  /* page: brand white */
  --bg-2:       #FFFFFF;  /* cards, elevated surfaces */
  --bg-3:       #EFEFEF;  /* alternating band */
  --ink:        #0B0B0D;  /* text: brand black, lifted off pure #000 */
  --ink-soft:   #2A2A2E;
  --muted:      #5A5A5A;  /* secondary copy — 6.5:1 on --bg */
  --instrument: #7A5B3E;  /* chart annotations — 5.8:1 on --bg */
  --hair:       rgba(11, 11, 13, 0.14);
  --rule:       rgba(11, 11, 13, 0.10);

  --font-display: 'Antonio', 'Arial Narrow', sans-serif;
  --font-body:    'Open Sauce One', system-ui, -apple-system, sans-serif;
  /* The brand has no monospace. A system stack keeps the instrument voice
     without a fourth font download. */
  --font-mono: ui-monospace, 'Cascadia Mono', 'SF Mono', Menlo, Consolas, monospace;

  --wrap: 1180px;
}

/* Inverted bands. Everything downstream reads the same variable names, so a
   component does not need to know which ground it is sitting on. */
.invert {
  /* Varuni grey, not black. On this lighter ground the mid-grey --muted would
     be unreadable, so the text tokens are lifted: white body (6.7:1), a light
     cite (4.8:1), and the emphasis switches from red — which is only 1.5:1 on
     grey — to a warm off-white that still stands apart. */
  --bg:         #5A5A5C;
  --bg-2:       #6A6A6D;
  --bg-3:       #6A6A6D;
  --ink:        #F8F8F8;
  --ink-soft:   #ECECEC;
  --muted:      #D8D8D8;
  --instrument: #E7D3B4;
  --hair:       rgba(248, 248, 248, 0.20);
  --rule:       rgba(248, 248, 248, 0.14);
  background: var(--bg);
  color: var(--ink);
}
/* On the grey band the brand red loses contrast, so the founder's emphasised
   clause uses the light tan instead — still a lift, still on-palette. */
.invert .quote blockquote em { color: var(--instrument); }

/* ------------------------------------------------------------------ reset */

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

body {
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--ink);
  line-height: 1.6;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
img, svg { max-width: 100%; display: block; }

:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 3px;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--red); color: #fff; padding: 12px 20px;
  font-family: var(--font-display); text-transform: uppercase; letter-spacing: .08em;
}
.skip:focus { left: 0; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 24px; }
.mono { font-family: var(--font-mono); }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* -------------------------------------------------- chart-sheet signature */

/* The annotation label above every section, with a rule trailing off to the
   right like a callout on a survey sheet.
   Grid, not flex: as a flex container the bare text node becomes an anonymous
   item that shrinks and wraps, orphaning the rule onto a second line. An `auto`
   grid column sizes to the text and lets the rule take the remainder. */
.sheet {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .22em;
  color: var(--instrument);
  text-transform: uppercase;
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 14px;
}
.sheet::after { content: ""; height: 1px; background: var(--hair); }

/* A depth-sounding rule: ticks along a baseline. */
.sounding {
  height: 14px;
  background:
    repeating-linear-gradient(90deg, var(--hair) 0 1px, transparent 1px 48px) bottom / 100% 7px no-repeat,
    linear-gradient(var(--hair), var(--hair)) bottom / 100% 1px no-repeat;
}

/* -------------------------------------------------------------------- nav */

.nav {
  position: sticky; top: 0; z-index: 50;
  background: rgba(248, 248, 248, .9);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--hair);
}
.nav-in { display: flex; align-items: center; justify-content: space-between; height: 68px; gap: 24px; }

/* The primary, full-colour mark: grey wordmark, red swoosh. The brand manual
   reserves this for light grounds — which is now every ground carrying it. */
.brand { display: flex; align-items: center; flex: none; }
.brand img { height: 40px; width: auto; }

.nav-links { display: flex; align-items: center; gap: 30px; font-size: 14px; font-weight: 500; list-style: none; }
.nav-links a { color: var(--muted); transition: color .2s; }
.nav-links a:hover { color: var(--ink); }

/* The current page is marked in brand red, with a rule under it so the state
   does not rest on colour alone — a red-green colourblind reader still sees it. */
.nav-links a[aria-current="page"] {
  color: var(--red);
  font-weight: 600;
  border-bottom: 2px solid var(--red);
  padding-bottom: 3px;
}

/* --- grouped dropdown menus --- */
.has-menu { position: relative; }
.menu-btn {
  display: inline-flex; align-items: center; gap: 7px;
  background: none; border: 0; cursor: pointer; padding: 0;
  font: inherit; font-weight: 500; color: var(--muted); transition: color .2s;
}
.menu-btn:hover, .has-menu:hover .menu-btn, .menu-btn[aria-expanded="true"] { color: var(--ink); }
.caret { width: 6px; height: 6px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg) translateY(-1px); transition: transform .2s; }
.menu-btn[aria-expanded="true"] .caret, .has-menu:hover .caret { transform: rotate(225deg) translateY(-2px); }

.submenu {
  list-style: none; position: absolute; top: calc(100% + 14px); left: -18px;
  min-width: 210px; background: var(--bg-2); border: 1px solid var(--hair);
  box-shadow: 0 12px 32px rgba(11, 11, 13, .10);
  padding: 8px 0; opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .16s, transform .16s, visibility .16s;
  z-index: 60;
}
/* A hover bridge so the pointer can cross the gap to the submenu. */
.has-menu::after { content: ""; position: absolute; top: 100%; left: 0; right: 0; height: 16px; }
.has-menu:hover .submenu, .has-menu:focus-within .submenu, .submenu.open {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.submenu a { display: block; padding: 10px 20px; color: var(--muted); white-space: nowrap; }
.submenu a:hover { color: var(--ink); background: var(--bg-3); }
.submenu a[aria-current="page"] { color: var(--red); border: 0; padding-bottom: 10px; }

.nav-cta {
  font-family: var(--font-mono);
  font-size: 12px; letter-spacing: .1em;
  border: 1px solid var(--red); color: var(--red);
  padding: 9px 18px; flex: none;
  transition: background .2s, color .2s;
}
.nav-cta:hover { background: var(--red); color: #fff; }

.nav-toggle {
  display: none; background: none; border: 1px solid var(--hair); color: var(--ink);
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .1em;
  padding: 8px 14px; cursor: pointer; text-transform: uppercase;
}

@media (max-width: 900px) {
  .nav-toggle { display: block; }
  .nav-cta { display: none; }
  .nav-links {
    display: none; position: absolute; top: 68px; left: 0; right: 0;
    flex-direction: column; gap: 0; background: var(--bg-2);
    border-bottom: 1px solid var(--hair); padding: 8px 0;
  }
  .nav-links.open { display: flex; }
  .nav-links a { display: block; padding: 14px 24px; }

  /* On mobile the dropdowns don't hover — flatten each group into a labelled
     section with its items listed beneath. No JS toggle needed. */
  .has-menu { position: static; }
  .has-menu::after { display: none; }
  .menu-btn {
    display: block; width: 100%; padding: 16px 24px 6px;
    font-family: var(--font-mono); font-size: 11px; letter-spacing: .16em;
    text-transform: uppercase; color: var(--instrument); cursor: default; pointer-events: none;
  }
  .caret { display: none; }
  .submenu {
    position: static; opacity: 1; visibility: visible; transform: none;
    min-width: 0; border: 0; box-shadow: none; background: none; padding: 0;
  }
  .submenu a { padding: 12px 36px; }
}

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

.hero-wrap { position: relative; overflow: hidden; border-bottom: 1px solid var(--hair); }

/* ---- hero map layers ---------------------------------------------------- */
/*
   Three map images stacked in the same box, cross-fading on the same 9s
   timeline as the headline word: sea → air → land. The order of the elements
   matches the order of the words, not the source order of the files.

   Legibility comes from a mask rather than a dark scrim: the images fade in
   from the left, so the headline and the buttons sit on clean paper while the
   map fills the empty right-hand side. On narrow screens the copy would sit on
   top of the map, so the layers are hidden entirely below 900px.
*/
.hero-maps { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.hero-map {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center right;
  opacity: 0;
  /* Two masks: fade in from the left, and soften the bottom into the trust bar.
     The left ramp is what keeps the headline readable, so it starts before the
     copy ends rather than at the edge of the viewport. */
  -webkit-mask-image: linear-gradient(90deg, transparent 36%, #000 68%),
                      linear-gradient(180deg, #000 76%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 36%, #000 68%),
                      linear-gradient(180deg, #000 76%, transparent 100%);
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
  animation: rotate-map 9s infinite;
}
.hero-map-sea  { animation-delay: 0s; }
.hero-map-air  { animation-delay: 3s; }
.hero-map-land { animation-delay: 6s; }

/* A longer plateau and softer edges than the word: a map that snaps is jarring,
   a word that lingers is dull. Full opacity — the saturation and the fade-in
   are baked into the asset and the mask, so nothing needs to be held back here. */
@keyframes rotate-map {
  0%      { opacity: 0; }
  4%, 30% { opacity: 1; }
  35%     { opacity: 0; }
  100%    { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-map { animation: none; opacity: 0; }
  .hero-map-sea { opacity: 1; }   /* the static state matches the static word */
}

@media (max-width: 900px) {
  .hero-maps { display: none; }
}
.hero { position: relative; padding: 108px 0 88px; }
.hero .sheet { margin-bottom: 34px; }

h1 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(48px, 7.6vw, 92px);
  line-height: .98;
  letter-spacing: .005em;
  text-transform: uppercase;
  max-width: 900px;
  color: var(--ink);
}
h1 em { font-style: normal; color: var(--red); }

/* ---- rotating domain word: sea → air → land ----------------------------- */
/*
   Only "sea." exists as DOM text; "air." and "land." are pseudo-element
   content, which keeps the heading's text content and accessible name to a
   single clean sentence.

   The pseudos are absolutely positioned, so they contribute no width and the
   element stays the size of "sea." — the longer words simply paint further
   right into the empty end of the line. Nothing reflows on each tick, which is
   what keeps this from being a layout-thrash animation.

   One cycle is 9s: three 3s slots, each word fading up and out at its edges.
   The global prefers-reduced-motion rule kills the animations entirely, and the
   static state it falls back to is exactly the DOM text — "sea." visible at
   full opacity, both pseudos transparent.
*/
.rotator {
  position: relative;
  display: inline-block;
  white-space: nowrap;
  font-style: normal;
  color: var(--red);
}
.rotator > span { display: inline-block; }
.rotator::before,
.rotator::after {
  position: absolute;
  left: 0;
  top: 0;
  opacity: 0;
  pointer-events: none;
}
.rotator::before { content: "air."; }
.rotator::after  { content: "land."; }

.rotator > span,
.rotator::before,
.rotator::after {
  animation: rotate-word 9s infinite;
}
.rotator > span   { animation-delay: 0s; }
.rotator::before  { animation-delay: 3s; }
.rotator::after   { animation-delay: 6s; }

@keyframes rotate-word {
  0%              { opacity: 0; transform: translateY(0.16em); }
  2%, 30%         { opacity: 1; transform: translateY(0); }
  33%             { opacity: 0; transform: translateY(-0.16em); }
  100%            { opacity: 0; transform: translateY(-0.16em); }
}

@media (prefers-reduced-motion: reduce) {
  .rotator > span  { opacity: 1; transform: none; }
  .rotator::before,
  .rotator::after  { opacity: 0; }
}

/* Exclude .sheet: a bare `.hero p` out-specifies `.sheet` (0,1,1 beats 0,1,0)
   and would impose its max-width and font-size on the chart label, wrapping
   the text and orphaning the trailing rule. Same reason for the :not() on
   .page-body, .final and .centred below. */
.hero p:not(.sheet) { max-width: 600px; margin: 28px 0 40px; font-size: 18px; color: var(--muted); }
.hero p:not(.sheet) strong { color: var(--ink); font-weight: 600; }

.cta-row { display: flex; gap: 16px; flex-wrap: wrap; }

.btn {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 19px;            /* >=18.66px bold => AA-large, so white on red passes */
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 14px 30px;
  display: inline-block;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform .15s, background .2s, color .2s, border-color .2s;
}
.btn-red   { background: var(--red); color: #fff; }
.btn-red:hover { background: var(--red-deep); transform: translateY(-1px); }
.btn-ghost { border-color: var(--hair); color: var(--ink); }
.btn-ghost:hover { border-color: var(--red); color: var(--red); }
.btn-ink   { background: var(--ink); color: #F8F8F8; }
.btn-ink:hover { background: #24242a; transform: translateY(-1px); }
.invert .btn-ink { background: #F8F8F8; color: #0B0B0D; }

.coords {
  margin-top: 64px; display: flex; gap: 40px; flex-wrap: wrap;
  font-family: var(--font-mono); font-size: 12px; color: var(--muted); letter-spacing: .08em;
}
.coords b { color: var(--instrument); font-weight: 600; display: block; margin-bottom: 2px; }

/* ------------------------------------------------------------------ trust */

.trust { border-bottom: 1px solid var(--hair); background: var(--bg-3); padding: 26px 0 30px; }
.mono, .trust .k { font-family: var(--font-mono); }

.trust-head {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
}
.trust-head .k { color: var(--red); font-weight: 500; }
.trust .bni { height: 46px; width: auto; flex: none; }

/* --- logo marquee --- */
/* The slider masks its edges so logos fade in and out rather than clip. The
   track holds two copies of the logo list and slides left by exactly half its
   width, so the loop is seamless. */
.logo-slider {
  margin: 22px 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.logo-track {
  display: flex; align-items: center; gap: 24px; width: max-content;
  animation: logo-scroll 42s linear infinite;
}
.logo-slider:hover .logo-track { animation-play-state: paused; }
/* Uniform white chips. The logos come from many brands with mixed
   backgrounds — some transparent, some already on white, some faint line art —
   so a chip normalises them: every mark reads clearly on the same ground,
   whatever it shipped with. */
.client-logo {
  height: 44px; width: auto; flex: none;
  box-sizing: content-box;
  background: #fff;
  padding: 14px 24px;
  border: 1px solid var(--hair);
  border-radius: 6px;
  transition: box-shadow .2s;
}
.client-logo:hover { box-shadow: 0 2px 14px rgba(11, 11, 13, .08); }

@keyframes logo-scroll {
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  /* No scroll: show the logos as a static, wrapping row. */
  .logo-slider { -webkit-mask-image: none; mask-image: none; }
  .logo-track { animation: none; flex-wrap: wrap; width: auto; gap: 40px 48px; justify-content: center; }
  /* The duplicate copy is aria-hidden; hide it so it doesn't double the row. */
  .logo-track .client-logo[aria-hidden="true"] { display: none; }
}

.trust-creds {
  display: flex; align-items: center; gap: 12px 32px; flex-wrap: wrap;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted);
}
.trust-creds .k { color: var(--red); font-weight: 500; }

/* --------------------------------------------------------------- sections */

section { padding: 96px 0; }
.alt { background: var(--bg-3); }

h2 {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(32px, 4.2vw, 48px);
  text-transform: uppercase; letter-spacing: .01em; line-height: 1.05;
  margin: 22px 0 14px; color: var(--ink);
}
.lead { color: var(--muted); max-width: 640px; font-size: 17px; }

/* --------------------------------------------------------------- products */

/* A hairline grid: the gap is the background showing through. */
.prod-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
  background: var(--hair); border: 1px solid var(--hair); margin-top: 56px;
}
.prod { background: var(--bg-2); padding: 38px 32px 44px; display: flex; flex-direction: column; transition: background .2s; }
.prod:hover { background: #fff; }
.prod .id { font-family: var(--font-mono); font-size: 11px; letter-spacing: .2em; color: var(--instrument); margin-bottom: 26px; }

/* Reserve two lines for the name and two for the tagline. "Smart City" is one
   line and "Domain Awareness" wraps at narrower widths; without a floor here
   the cards in a row start their body copy at different heights and the grid
   reads as broken. Reserving space is cheaper than truncating a real name. */
.prod h3 {
  font-family: var(--font-display); font-weight: 700; font-size: 26px;
  color: var(--ink); text-transform: uppercase; line-height: 1.1;
  min-height: 2.2em;   /* 2 × line-height */
}
.prod .tag {
  font-size: 13px; font-weight: 600; color: var(--maroon);
  margin: 6px 0 16px; line-height: 1.4; min-height: 2.8em;   /* 2 × line-height */
}

/* One card per row on narrow screens: nothing to align against, so let both
   collapse to their content. */
@media (max-width: 900px) {
  .prod h3, .prod .tag { min-height: 0; }
}
/* Only the body copy flexes. A bare `.prod p` (0,1,1) also matches .id, .tag
   and .status — giving every paragraph `flex: 1`, so they each absorb a share
   of the card's leftover space and no two cards in a row line up. */
.prod .blurb { font-size: 14.5px; color: var(--muted); flex: 1; }
.prod a {
  margin-top: 26px; font-family: var(--font-mono); font-size: 12px; letter-spacing: .12em;
  color: var(--ink); border-bottom: 1px solid var(--red); padding-bottom: 3px; align-self: flex-start;
  transition: color .2s;
}
.prod a:hover { color: var(--red); }

/* Fill an incomplete final row. With 7 cards in a 3-column grid the last card
   sits alone, and the two empty tracks show the container's hairline background
   as a grey block. Letting a lone trailing card span the full width — or a
   trailing pair span the last two columns — keeps every row solid.
   `:nth-child(3n+1):last-child` is "first in its row AND the last card". */
.prod-grid > .prod:nth-child(3n + 1):last-child { grid-column: 1 / -1; }
.prod-grid > .prod:nth-child(3n + 2):last-child { grid-column: 2 / -1; }

@media (max-width: 900px) {
  .prod-grid { grid-template-columns: 1fr; }
  /* Single column: nothing to fill, so drop the spans. */
  .prod-grid > .prod:last-child { grid-column: auto; }
}

/* "See all …" link closing a homepage teaser section. */
.section-more { margin-top: 40px; }
.section-more a {
  font-family: var(--font-mono); font-size: 13px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--red); border-bottom: 1px solid var(--red); padding-bottom: 3px;
}
.section-more a:hover { color: var(--red-deep); }

/* A product's status is stated on its card. "In service" is the strong claim;
   anything else is toned down so it cannot be mistaken for one. */
.status {
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--red); margin-top: 18px;
  /* flex-start, not center: a two-line status ("Available — in discussion for
     Ahmedabad") would otherwise centre its dot against the whole block. */
  display: flex; align-items: flex-start; gap: 8px; line-height: 1.5;
}
.status::before {
  content: ""; width: 6px; height: 6px; background: var(--red);
  border-radius: 50%; flex: none; margin-top: 5px;   /* onto the first line's centre */
}
.status-soft { color: var(--muted); }
.status-soft::before { background: var(--muted); }

/* ---------------------------------------------------------------- GIS work */

.gis-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 40px; margin-top: 56px;
}
/* The first screenshot is the strongest; give it the full width. */
.gis-grid .gis:first-child { grid-column: 1 / -1; }

.gis { margin: 0; }
.gis img {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--hair); background: var(--bg-2);
}
.gis figcaption {
  margin-top: 14px; font-size: 14px; color: var(--muted); max-width: 60ch;
  border-left: 2px solid var(--red); padding-left: 14px;
}
@media (max-width: 900px) {
  .gis-grid { grid-template-columns: 1fr; gap: 32px; }
  .gis-grid .gis:first-child { grid-column: auto; }
}

/* -------------------------------------------- specification list (cap/ops) */

.cap-list { margin-top: 56px; border-top: 1px solid var(--hair); }
.cap {
  display: grid; grid-template-columns: 110px 300px 1fr; gap: 28px;
  padding: 30px 0; border-bottom: 1px solid var(--hair); align-items: baseline;
}
.cap .no { font-family: var(--font-mono); font-size: 12px; color: var(--instrument); letter-spacing: .15em; }
.cap h3 { font-family: var(--font-display); font-weight: 600; font-size: 22px; text-transform: uppercase; letter-spacing: .02em; color: var(--ink); }
.cap p { color: var(--muted); font-size: 15px; }
.cap .more {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .12em;
  color: var(--red); border-bottom: 1px solid transparent; white-space: nowrap;
}
.cap .more:hover { border-color: var(--red); }

/* A whole row that is itself a link (the case-study index). It keeps the .cap
   grid but the first column is the eyebrow, so the title spans wider; the row
   lifts its title and underlines the "more" cue on hover. The .more span is a
   plain span here (not an <a>), so its hover is driven by the row. */
.cap-link { text-decoration: none; color: inherit; transition: background .15s; grid-template-columns: 200px 1fr; }
.cap-link:hover { background: var(--bg-3); }
.cap-link:hover h3 { color: var(--red); }
/* Title, description and the "more" cue stack in the second column, so the row
   reads eyebrow-left, everything-else-right — not three items flowing across
   two grid tracks. */
.cap-body { min-width: 0; }
.cap-body h3 { margin-bottom: 8px; }
.cap-link .more { display: inline-block; margin-top: 10px; }
.cap-link:hover .more { border-color: var(--red); }

@media (max-width: 900px) {
  .cap { grid-template-columns: 1fr; gap: 8px; }
  .cap-link { grid-template-columns: 1fr; }
}

/* -------------------------------------------------------------------- why */

.why-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 48px; margin-top: 56px; }
.why h3 { font-family: var(--font-display); font-weight: 700; font-size: 21px; text-transform: uppercase; color: var(--ink); margin-bottom: 10px; }
.why h3::before { content: "— "; color: var(--red); }
.why p { font-size: 15px; color: var(--muted); }
@media (max-width: 900px) { .why-grid { grid-template-columns: 1fr; gap: 32px; } }

/* -------------------------------------------------------------------- FAQ */

/* Answers are always visible: an accordion would hide the exact sentences we
   want an answer engine to quote. */
.faq-list { margin-top: 56px; display: grid; grid-template-columns: repeat(2, 1fr); gap: 48px 56px; }
.faq h3 {
  font-family: var(--font-display); font-weight: 600; font-size: 20px;
  text-transform: none; letter-spacing: .01em; color: var(--ink); margin-bottom: 10px;
}
.faq h3::before { content: "— "; color: var(--red); }
.faq p { font-size: 15px; color: var(--muted); }
@media (max-width: 900px) { .faq-list { grid-template-columns: 1fr; gap: 36px; } }

/* ------------------------------------------------------------ breadcrumbs */

.crumbs {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 28px;
  display: flex; gap: 10px; flex-wrap: wrap;
}
.crumbs a { color: var(--instrument); border-bottom: 1px solid transparent; }
.crumbs a:hover { border-color: var(--instrument); }
.crumbs [aria-current="page"] { color: var(--ink); }

/* ---------------------------------------------------------------- founder */

.quote { max-width: 800px; }
.quote blockquote {
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(24px, 2.8vw, 32px); line-height: 1.3; color: var(--ink);
}
.quote blockquote em { color: var(--red); font-style: normal; }
.quote cite {
  display: block; margin-top: 26px; font-family: var(--font-mono);
  font-size: 12.5px; font-style: normal; letter-spacing: .12em; color: var(--muted); text-transform: uppercase;
}

/* -------------------------------------------------------------- final CTA */

/* The closing slide, in the brand's deep maroon. Black text on the bright red
   #ED1C24 "vibrated" — the harsh chromatic edge of saturated red under black —
   and white on that red fails AA at body size. The deeper maroon fixes both:
   white text on it is ~12:1, calm and clearly legible, and the band still reads
   as brand-red. The logo never appears on this band. */
.final { background: var(--maroon); color: #F8F8F8; }
.final .sheet { color: rgba(248, 248, 248, .78); }
.final .sheet::after { background: rgba(248, 248, 248, .28); }
.final h2 { color: #FFFFFF; }
.final p:not(.sheet) { max-width: 640px; color: #F1F1F1; font-size: 18px; line-height: 1.55; margin-bottom: 36px; }
/* A light button pops on the dark maroon; the dark-ink variant would recede. */
.final .btn-ink { background: #F8F8F8; color: var(--maroon); }
.final .btn-ink:hover { background: #FFFFFF; }
.final-ghost { border-color: rgba(248, 248, 248, .5); color: #F8F8F8; }
.final-ghost:hover { background: #F8F8F8; color: var(--maroon); border-color: #F8F8F8; }

/* ----------------------------------------------------------------- footer */

footer {
  border-top: 1px solid var(--hair); padding: 44px 0; background: var(--bg-3);
  font-family: var(--font-mono); font-size: 12px; color: var(--muted); letter-spacing: .06em;
}
.foot-in { display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap; align-items: center; }
.foot-links { display: flex; gap: 24px; flex-wrap: wrap; }
.foot-links a:hover { color: var(--ink); }

/* --------------------------------------------------- interior pages */

.page-hero { padding: 84px 0 56px; }
.page-hero h1 { font-size: clamp(36px, 5vw, 62px); max-width: 900px; }
.page-hero .lead { margin-top: 18px; }
.eyebrow {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .22em;
  color: var(--instrument); text-transform: uppercase; margin-bottom: 22px;
}
.page-metrics {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1px; background: var(--hair); border: 1px solid var(--hair); margin: 56px 0 0;
}
.metric { background: var(--bg-2); padding: 28px 24px; }
.metric .v { font-family: var(--font-display); font-weight: 700; font-size: 36px; color: var(--red); line-height: 1; }
.metric .l { font-size: 13px; color: var(--muted); margin-top: 8px; }

/* Prose sits in a narrow measure, but the column starts at the same left edge
   as every other section — re-centring a 780px column inside the 1180px wrap
   would indent the body text away from the headings above and below it. */
.page-body .page-section > * { max-width: 780px; }
.page-body h2 { font-size: clamp(24px, 2.6vw, 32px); margin-top: 0; }
.page-body p:not(.sheet) { color: var(--muted); font-size: 17px; }
.page-section { padding: 64px 0; border-bottom: 1px solid var(--hair); }
.page-section:last-of-type { border-bottom: 0; }

.pull {
  border-left: 2px solid var(--red); padding: 4px 0 4px 24px; margin: 40px 0;
  font-family: var(--font-display); font-weight: 500; font-size: 22px; line-height: 1.35; color: var(--ink);
}
.pull cite { display: block; margin-top: 14px; font-family: var(--font-mono); font-size: 12px; font-style: normal; letter-spacing: .12em; color: var(--muted); }

.credit-box { background: var(--bg-2); border: 1px solid var(--hair); padding: 28px; margin-top: 40px; }
.credit-box h3 { font-family: var(--font-display); font-size: 18px; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 8px; color: var(--ink); }
.credit-box p { font-size: 14px; color: var(--muted); margin-bottom: 16px; }
.credit-box code {
  display: block; font-family: var(--font-mono); font-size: 12.5px; line-height: 1.7;
  background: var(--bg); border: 1px solid var(--hair); padding: 14px 16px;
  color: var(--instrument); overflow-x: auto; white-space: pre-wrap; word-break: break-all;
}

.related { display: flex; gap: 20px; flex-wrap: wrap; margin-top: 40px; }
.related a { font-family: var(--font-mono); font-size: 12px; letter-spacing: .12em; color: var(--red); border-bottom: 1px solid transparent; text-transform: uppercase; }
.related a:hover { border-color: var(--red); }

/* ------------------------------------------------------------------ forms */

.form-page { padding: 72px 0 96px; }
.form-grid { display: grid; grid-template-columns: 1fr 380px; gap: 72px; align-items: start; margin-top: 48px; }
@media (max-width: 960px) { .form-grid { grid-template-columns: 1fr; gap: 48px; } }

.field { margin-bottom: 24px; }
.field label { display: block; font-family: var(--font-mono); font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--instrument); margin-bottom: 8px; }
.field .req { color: var(--red); }

.field input[type="text"], .field input[type="email"], .field input[type="tel"],
.field input[type="date"], .field input[type="file"], .field textarea, .field select {
  width: 100%; background: var(--bg-2); border: 1px solid var(--hair);
  color: var(--ink); font-family: var(--font-body); font-size: 16px;
  padding: 13px 15px; transition: border-color .2s;
}
.field textarea { min-height: 160px; resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: #9A9A9A; }
.field input:focus, .field textarea:focus, .field select:focus { border-color: var(--red); outline: none; }
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"] { border-color: var(--red); }
.field .err { color: #C4141B; font-size: 13.5px; margin-top: 7px; font-weight: 500; }
.field .hint { color: var(--muted); font-size: 13px; margin-top: 7px; }

/* The honeypot. Hidden from people, not from bots: `display:none` on a field
   some bots skip, so it is positioned away instead and hidden from a11y tree. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Altcha widget, themed to the brand via the custom properties it exposes. */
.captcha-field { margin-bottom: 24px; }
altcha-widget {
  --altcha-max-width: 100%;
  --altcha-border-width: 1px;
  --altcha-border-radius: 0;
  --altcha-color-border: var(--hair);
  --altcha-color-base: var(--bg-2);
  --altcha-color-text: var(--ink);
  --altcha-color-border-focus: var(--red);
  --altcha-color-error-text: #C4141B;
  display: block;
}

.radio-row { display: flex; gap: 24px; }
.radio-row label { display: flex; align-items: center; gap: 8px; font-family: var(--font-body); font-size: 15px; letter-spacing: 0; text-transform: none; color: var(--ink); margin: 0; }
.radio-row input { accent-color: var(--red); }

.flash { border-left: 2px solid var(--red); background: var(--bg-2); padding: 16px 20px; margin-bottom: 32px; font-size: 15px; }
.flash-ok { border-left-color: #2F7D4F; }

.contact-map { margin-top: 64px; }
#office-map {
  width: 100%; height: 380px; border: 1px solid var(--hair);
  background: var(--bg-3); z-index: 0;
}
/* Leaflet's controls in the brand's restrained style. */
.leaflet-container { font-family: var(--font-body); }
.leaflet-bar a { color: var(--ink); }
.leaflet-control-attribution { font-size: 10px; }
/* CSS pin — a red teardrop, no image asset. */
.office-pin {
  width: 20px; height: 20px;
  background: var(--red);
  border: 3px solid #fff;
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  box-shadow: 0 2px 6px rgba(11, 11, 13, .35);
}
.contact-map .map-link { margin-top: 12px; font-size: 12px; letter-spacing: .08em; }
.contact-map .map-link a { color: var(--red); border-bottom: 1px solid transparent; }
.contact-map .map-link a:hover { border-color: var(--red); }

/* ------------------------------------------------------------------ about */

.about-intro { max-width: 760px; margin-top: 32px; }
.about-intro p { font-size: 19px; line-height: 1.6; color: var(--ink-soft); margin-bottom: 22px; }
.about-intro p:first-child { font-size: 22px; color: var(--ink); }

.about-pillars {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 48px 56px; margin-top: 56px;
}
.pillar .no { font-family: var(--font-mono); font-size: 12px; letter-spacing: .2em; color: var(--instrument); margin-bottom: 12px; }
.pillar h3 { font-family: var(--font-display); font-weight: 700; font-size: 22px; text-transform: uppercase; color: var(--ink); margin-bottom: 10px; }
.pillar h3::before { content: "— "; color: var(--red); }
.pillar p { font-size: 15px; color: var(--muted); }
@media (max-width: 860px) { .about-pillars { grid-template-columns: 1fr; gap: 36px; } }

.about-creds {
  display: flex; gap: 12px 32px; flex-wrap: wrap; margin-top: 32px;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
}
.about-creds .k { color: var(--red); font-weight: 500; }
.about-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 28px; margin-top: 44px; }
.about-facts dt { font-family: var(--font-mono); font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--instrument); margin-bottom: 6px; }
.about-facts dd { font-size: 15px; color: var(--muted); }
.about-facts a { color: var(--red); }

/* News list — a date rail on the left, the item on the right. */
.news-list { margin-top: 48px; border-top: 1px solid var(--hair); }
.news-item {
  display: grid; grid-template-columns: 160px 1fr; gap: 28px;
  padding: 30px 0; border-bottom: 1px solid var(--hair); align-items: baseline;
}
.news-date { font-family: var(--font-mono); font-size: 12px; letter-spacing: .14em; color: var(--instrument); text-transform: uppercase; }
.news-body h3 { font-family: var(--font-display); font-weight: 600; font-size: 22px; text-transform: uppercase; color: var(--ink); margin-bottom: 10px; }
.news-body p { font-size: 15px; color: var(--muted); }
.news-body .more { display: inline-block; margin-top: 12px; }
@media (max-width: 720px) { .news-item { grid-template-columns: 1fr; gap: 8px; } }

.product-shot { margin: 40px 0 8px; }
.product-shot img {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--hair); background: var(--bg-2);
}
.product-shot figcaption {
  margin-top: 14px; font-size: 14px; color: var(--muted); max-width: 70ch;
  border-left: 2px solid var(--red); padding-left: 14px;
}

.aside-card { background: var(--bg-2); border: 1px solid var(--hair); padding: 32px; }
.aside-card h3 { font-family: var(--font-display); font-size: 18px; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 16px; color: var(--ink); }
.aside-card p, .aside-card li { font-size: 14.5px; color: var(--muted); }
.aside-card dl { display: grid; gap: 18px; }
.aside-card dt { font-family: var(--font-mono); font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--instrument); margin-bottom: 4px; }
.aside-card dd { font-size: 14.5px; color: var(--muted); }
.aside-card a:hover { color: var(--ink); }

/* ------------------------------------------------------------------- exam */

.exam-head {
  position: sticky; top: 68px; z-index: 20; background: rgba(248, 248, 248, .95);
  backdrop-filter: blur(8px); border-bottom: 1px solid var(--hair);
  padding: 16px 0; display: flex; justify-content: space-between; align-items: center; gap: 20px;
}
.timer { font-family: var(--font-mono); font-size: 15px; letter-spacing: .1em; color: var(--instrument); }
.timer.urgent { color: var(--red); font-weight: 500; }

.question { padding: 32px 0; border-bottom: 1px solid var(--hair); }
.question .qno { font-family: var(--font-mono); font-size: 11px; letter-spacing: .2em; color: var(--instrument); margin-bottom: 12px; }
.question .prompt { font-size: 18px; font-weight: 500; margin-bottom: 20px; }
.options { display: grid; gap: 10px; max-width: 720px; }
.option { display: flex; align-items: flex-start; gap: 12px; padding: 13px 16px; background: var(--bg-2); border: 1px solid var(--hair); cursor: pointer; transition: border-color .15s, background .15s; }
.option:hover { border-color: var(--instrument); }
.option input { margin-top: 4px; accent-color: var(--red); }
.option:has(input:checked) { border-color: var(--red); background: #fff; }

/* --------------------------------------------------------------- messages */

.centred { max-width: 720px; margin: 0 auto; text-align: center; padding: 120px 24px; }
.centred h1 { font-size: clamp(40px, 6vw, 72px); margin: 0 auto 24px; }
.centred p:not(.sheet) { color: var(--muted); font-size: 18px; margin-bottom: 32px; }
.centred .cta-row { justify-content: center; }
