/* =========================================================
   FUSION FORGE — DESIGN SYSTEM
   ========================================================= */
:root{
  /* Brand — Deep Navy + Electric Blue + Cyan.
     Navy is the chrome colour (nav, hero, page heroes, footer). --deep is a
     second, lifted navy for the divider sections, so the page alternates
     white -> soft -> navy without every dark band reading as chrome. */
  --midnight:#07111F;
  --midnight-2:#0B1626;

  --deep:#0D1B2A;
  --deep-2:#132436;
  --on-deep:#F8FAFC;
  --on-deep-muted:#94A3B8;   /* 6.8:1 on --deep, 7.1:1 on --midnight-2 */

  /* Blue needs two tiers: no single blue is readable on both grounds.
     --accent carries text on white at 4.87:1, but only 3.9:1 on navy, so
     --accent-soft (8.8:1 on navy) is the dark-ground tier. --accent-bright
     is cyan and is a FILL for dark grounds only — 2.2:1 on white, never text.
     --accent-tint is the light end of the clipped-text gradient. */
  --accent:#2563EB;
  --accent-hover:#1D4ED8;
  --accent-bright:#06B6D4;
  --accent-soft:#38BDF8;
  --accent-tint:#7DD3FC;

  --white:#FFFFFF;
  --soft:#F5F7FA;
  --slate:#5C6A80;   /* light-ground muted text; 4.9:1 on --soft */
  --charcoal:#1E293B;

  --line:rgba(148,163,184,.16);
  --line-dark:rgba(148,163,184,.10);
  --ink:#07111F;
  --ink-soft:#3A4256;

  /* --grad has to carry white text (CTA band), so its lightest stop is blue-700
     (6.7:1 with white) rather than --accent, which would only give 4.9:1.
     --grad-bright is decorative fill only; --grad-text is clipped to text on navy. */
  --grad: linear-gradient(120deg,#07111F 0%,#1E3A8A 55%,#1D4ED8 100%);
  --grad-bright: linear-gradient(120deg,var(--accent) 0%,var(--accent-bright) 100%);
  --grad-text: linear-gradient(100deg,var(--accent-tint) 0%,var(--accent-tint) 100%);

  /* Corners are intentional, not uniformly pill: buttons and cards use a tight
     radius, only genuine tags/filters stay fully rounded. */
  --r-sm:8px; --r:12px; --r-lg:18px; --r-xl:24px;
  --shadow-1:0 1px 2px rgba(7,17,31,.06),0 8px 24px rgba(7,17,31,.06);
  --shadow-2:0 30px 60px -20px rgba(7,17,31,.35);
  --shadow-accent:0 20px 45px -18px rgba(37,99,235,.55);

  --ff-head:"Plus Jakarta Sans",system-ui,sans-serif;
  --ff-body:"Inter",system-ui,sans-serif;

  /* 1200 left ~190px of dead margin each side at 1510 and 360 at 1920, which read
     as a shrunken page on the wide desktop sizes the brief targets. 1320 with a
     wider top-end gutter fills those without stretching text lines — the reading
     measures (.sec-head, .phero-inner) keep their own caps. */
  --wrap:1320px;
  --gap:clamp(1rem,2vw,1.75rem);
  --sp:clamp(64px,9vw,128px);
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  font-family:var(--ff-body);
  color:var(--ink);
  background:var(--white);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
a{color:inherit;text-decoration:none}
img{max-width:100%;height:auto;display:block}   /* height:auto or a width-capped img keeps its height ATTRIBUTE and distorts */
button{font-family:inherit;cursor:pointer;border:none;background:none}

/* Focus visibility. Nothing here resets the UA ring — it replaces it with one that
   is legible on both ground families, since the default is tuned for neither.
   --accent clears 3:1 on white and .soft (5.48 / 5.01); on the midnight and deep
   grounds it would not, so those swap to --accent-tint (12.42 / 8.20). */
:focus-visible{outline:3px solid var(--accent);outline-offset:2px;border-radius:3px}

/* Skip link — every page opens with ~10 nav links before the content starts. */
.skip{position:absolute;left:8px;top:-60px;z-index:300;background:var(--midnight);color:#fff;
  padding:12px 18px;border-radius:0 0 10px 10px;font-weight:600;font-size:14px;transition:top .2s}
.skip:focus{top:0}
.nav :focus-visible,.mobilenav :focus-visible,.hero :focus-visible,.phero :focus-visible,
.dark :focus-visible,.ctaband :focus-visible,footer :focus-visible{outline-color:var(--accent-tint)}
h1,h2,h3,h4{font-family:var(--ff-head);line-height:1.06;letter-spacing:-.02em;font-weight:600}
::selection{background:var(--accent);color:#fff}

.wrap{width:100%;max-width:var(--wrap);margin-inline:auto;padding-inline:clamp(20px,5vw,48px)}
.section{padding-block:var(--sp)}
.dark{background:var(--deep);color:#F8FAFC}
.dark h1,.dark h2,.dark h3{color:#fff}
.soft{background:var(--soft)}

/* type scale */
.display{font-size:clamp(38px,7vw,80px);line-height:1.0}
.h1{font-size:clamp(34px,5vw,60px)}
.h2{font-size:clamp(28px,3.6vw,46px)}
.h3{font-size:clamp(21px,2.4vw,28px)}
.lead{font-size:clamp(17px,1.4vw,20px);color:var(--ink-soft);max-width:60ch}
.dark .lead{color:var(--on-deep)}
.muted{color:var(--slate)}
.dark .muted{color:var(--on-deep-muted)}
.grad-word{background:var(--grad-text);-webkit-background-clip:text;background-clip:text;color:transparent}

.eyebrow{
  font-family:var(--ff-body);font-weight:600;font-size:13.5px;letter-spacing:.01em;
  color:var(--accent);display:inline-flex;align-items:center;gap:9px;margin-bottom:20px;
}
.dark .eyebrow{color:var(--accent-tint)}
.eyebrow::before{content:"";width:26px;height:2px;background:currentColor;border-radius:2px;opacity:.7}

/* buttons */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-family:var(--ff-body);font-weight:600;font-size:15.5px;
  padding:14px 26px;border-radius:var(--r);transition:.25s ease;white-space:nowrap;
  border:1px solid transparent;
}
.btn svg{width:17px;height:17px}
.btn-primary{background:var(--accent);color:#fff;box-shadow:var(--shadow-accent)}
.btn-primary:hover{background:var(--accent-hover);transform:translateY(-2px)}
/* On midnight grounds the deep emerald goes muddy, so the button inverts:
   bright emerald with midnight text (7.4:1) instead of white on deep (5.5:1). */
.nav .btn-primary,.mobilenav .btn-primary,.hero .btn-primary,.phero .btn-primary,.dark .btn-primary,.ctaband .btn-primary{
  background:var(--accent-bright);color:var(--midnight);box-shadow:0 18px 40px -18px rgba(6,182,212,.55);
}
.nav .btn-primary:hover,.mobilenav .btn-primary:hover,.hero .btn-primary:hover,.phero .btn-primary:hover,.dark .btn-primary:hover,.ctaband .btn-primary:hover{
  background:var(--accent-tint);color:var(--midnight);
}
.btn-ghost{background:transparent;border-color:var(--line);color:inherit}
.dark .btn-ghost{border-color:rgba(255,255,255,.22);color:#fff}
.btn-ghost:hover{border-color:var(--accent);color:var(--accent)}
.dark .btn-ghost:hover{border-color:var(--accent-tint);color:var(--accent-tint)}
.btn-light{background:#fff;color:var(--midnight)}
.btn-light:hover{transform:translateY(-2px);box-shadow:0 14px 30px rgba(0,0,0,.25)}
.textlink{display:inline-flex;align-items:center;gap:8px;font-weight:600;color:var(--accent);transition:.2s}
.dark .textlink{color:var(--accent-tint)}
.textlink:hover{gap:13px}
.textlink svg{width:16px;height:16px;transition:.2s}

/* =================== HEADER =================== */
header{position:sticky;top:0;z-index:100;transition:.35s}
/* The header is sticky but in flow, so at scroll 0 it sits ABOVE the hero
   rather than over it — a translucent ground there composites against the white
   page, not the midnight below it, and the bar rendered slate grey (79,83,94).
   That dropped the brand small to 4.0:1 and the nav links to 4.89:1. At rest the
   nav is solid midnight, which also reads continuous with the hero beneath it;
   the translucency is kept for .scrolled, where it genuinely overlays content. */
.nav{
  background:var(--midnight);backdrop-filter:blur(18px);
  border-bottom:1px solid rgba(255,255,255,.06);
}
.nav.scrolled{background:rgba(7,17,31,.94)}
.nav-inner{display:flex;align-items:center;justify-content:space-between;height:72px}
.brand{display:flex;align-items:center;gap:12px;color:#fff;font-family:var(--ff-head);font-weight:700;font-size:19px;letter-spacing:-.02em;flex:none}
.brand span{white-space:nowrap}
.brand .mark{width:34px;height:34px;flex:none}
.brand small{display:block;font-family:var(--ff-body);font-weight:500;font-size:10.5px;letter-spacing:.14em;color:var(--accent-tint);text-transform:uppercase;margin-top:2px}

.menu{display:flex;align-items:center;gap:4px;list-style:none}
.menu > li{position:relative}
.menu > li > a,.menu > li > button{
  color:#CBD5E1;font-weight:500;font-size:15px;padding:10px 15px;border-radius:10px;
  display:inline-flex;align-items:center;gap:6px;transition:.2s;
}
.menu > li > a:hover,.menu > li > button:hover,.menu > li.active > a{color:#fff;background:rgba(255,255,255,.05)}
.menu .caret{width:10px;height:10px;opacity:.7;transition:.2s}
.menu > li:hover .caret{transform:rotate(180deg)}

.mega{
  position:absolute;top:calc(100% + 12px);left:50%;transform:translateX(-50%) translateY(8px);
  background:#132436;border:1px solid rgba(255,255,255,.08);border-radius:18px;
  padding:22px;box-shadow:var(--shadow-2);opacity:0;visibility:hidden;transition:.24s;
  display:grid;gap:6px;min-width:290px;
}
.mega.wide{grid-template-columns:1fr 1fr;min-width:520px}
.menu > li:hover .mega{opacity:1;visibility:visible;transform:translateX(-50%) translateY(0)}
.mega a{display:flex;gap:12px;padding:11px 13px;border-radius:12px;transition:.18s;align-items:flex-start}
.mega a:hover{background:rgba(6,182,212,.16)}
.mega .ic{width:34px;height:34px;border-radius:9px;flex:none;display:grid;place-items:center;background:rgba(6,182,212,.16);color:var(--accent-tint)}
.mega .ic svg{width:17px;height:17px}
.mega b{color:#fff;font-family:var(--ff-body);font-weight:600;font-size:14.5px;display:block}
.mega span{color:#94A3B8;font-size:12.5px;line-height:1.4}
.nav-cta{display:flex;align-items:center;gap:14px}

.burger{display:none;flex-direction:column;align-items:center;justify-content:center;gap:5px;width:44px;height:44px;padding:0}
.burger span{width:24px;height:2px;background:#fff;border-radius:2px;transition:.3s}

/* mobile nav */
.mobilenav{position:fixed;inset:0;z-index:200;background:var(--midnight);transform:translateX(100%);transition:.4s cubic-bezier(.6,.05,.2,1);overflow-y:auto;display:none}
.mobilenav.open{transform:translateX(0)}
.mobilenav-top{display:flex;justify-content:space-between;align-items:center;height:72px;border-bottom:1px solid rgba(255,255,255,.08)}
.mclose{color:#fff;font-size:26px;line-height:1;width:40px;height:40px;display:grid;place-items:center;border-radius:10px}
.macc{border-bottom:1px solid rgba(255,255,255,.07)}
.macc > button,.macc > a{width:100%;display:flex;justify-content:space-between;align-items:center;color:#fff;font-family:var(--ff-head);font-size:22px;font-weight:500;padding:20px 0;text-align:left}
.macc .sub{max-height:0;overflow:hidden;transition:.35s}
.macc.open .sub{max-height:600px}
.macc .sub a{display:block;color:#AEB7CE;font-family:var(--ff-body);font-size:16px;font-weight:400;padding:11px 0 11px 16px}
.macc .plus{color:var(--accent-tint);font-size:24px;transition:.3s}
.macc.open .plus{transform:rotate(45deg)}

/* =================== HERO =================== */
.hero{position:relative;background:var(--midnight);color:#fff;overflow:hidden;padding-block:clamp(70px,10vw,120px)}
.hero-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(30px,4vw,60px);align-items:center}
#heroflow{position:absolute;inset:0;width:100%;height:100%;z-index:0}
.hero-content{position:relative;z-index:3}
.hero .display{margin:14px 0 22px}
.hero-actions{display:flex;gap:14px;flex-wrap:wrap;margin-top:34px}
.metrics{container-type:inline-size;display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(12px,2.2vw,28px);margin-top:52px}   /* vw, not cqi: an element is not its own query container, so cqi here would silently fall back to the viewport anyway */
.metrics>*{min-width:0}
.metric b{font-family:var(--ff-head);font-size:clamp(16px,5.4cqi,44px);display:block;background:var(--grad-text);-webkit-background-clip:text;background-clip:text;color:transparent;overflow-wrap:break-word}
.metric span{color:#94A3B8;font-size:13.5px;overflow-wrap:break-word}

/* marquee trust */
/* Carries .dark in the markup: the band is a midnight ground, so the dark variants
   of .techitem and .logo-tile.ic have to win over the light-ground defaults. .trust
   is declared after .dark, so its own background still holds. */
.trust{border-block:1px solid var(--line-dark);padding-block:clamp(40px,5vw,60px);background:var(--midnight-2)}
.trust-label{color:#94A3B8;font-size:13px;text-align:center;margin-bottom:26px}
.chips{display:flex;flex-wrap:wrap;justify-content:center;gap:12px}
.chip{border:1px solid rgba(255,255,255,.12);color:#CBD5E1;font-size:13.5px;font-weight:500;padding:9px 16px;border-radius:999px}

/* generic grids */
.grid{display:grid;gap:var(--gap)}
.g2{grid-template-columns:repeat(2,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g4{grid-template-columns:repeat(4,1fr)}

.sec-head{max-width:720px;margin-bottom:clamp(36px,5vw,56px)}
.sec-head.center{margin-inline:auto;text-align:center}
.sec-head .lead{margin-top:16px}
.sec-head.center .lead{margin-inline:auto}

/* cards — varied, not identical */
.card{background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);padding:28px;transition:.28s}
.dark .card{background:var(--deep-2);border-color:rgba(255,255,255,.08)}
.card:hover{transform:translateY(-4px);border-color:var(--accent);box-shadow:var(--shadow-1)}
.card .ci{width:48px;height:48px;border-radius:12px;display:grid;place-items:center;background:linear-gradient(135deg,rgba(37,99,235,.14),rgba(6,182,212,.20));color:var(--accent);margin-bottom:20px}
.dark .card .ci{color:var(--accent-tint)}
.card .ci svg{width:23px;height:23px}
.card h3{font-size:20px;margin-bottom:9px}
.card p{color:var(--slate);font-size:15px}
.dark .card p{color:var(--on-deep-muted)}
.card .more{margin-top:16px;font-size:14px}
/* "Best when ..." qualifier under a card's blurb: a hairline separates it from
   the description so it reads as a decision aid rather than as more copy. */
.card .fit{margin-top:14px;padding-top:14px;border-top:1px solid var(--line);font-size:13.5px}
.dark .card .fit{border-top-color:rgba(255,255,255,.1)}
.card .fit b{font-family:var(--ff-head);font-weight:600;color:var(--ink)}
.dark .card .fit b{color:#F8FAFC}
/* A badge used as a link inside a card (solution pairings). */
a.badge{transition:.2s}
a.badge:hover{border-color:var(--accent);color:var(--accent)}

/* service card — left accent variant */
.svc{position:relative;padding-left:26px}
.svc::before{content:"";position:absolute;left:0;top:4px;bottom:4px;width:3px;border-radius:3px;background:var(--grad-bright)}

/* numbered process — real sequence */
/* auto-fit, not repeat(6,1fr): a four-step list left two empty columns and a
   large dead area to the right of the row. Empty tracks now collapse, so four
   steps fill the width and six still lay out six across. */
.steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,180px),1fr));gap:0;counter-reset:s;position:relative}
.step{padding:26px 20px 26px 0;position:relative}
.step .n{font-family:var(--ff-head);font-size:15px;font-weight:600;color:var(--accent);margin-bottom:14px;display:flex;align-items:center;gap:10px}
.dark .step .n{color:var(--accent-tint)}
.step .n::after{content:"";flex:1;height:1px;background:var(--line)}
.step:last-child .n::after{display:none}
.step .dot{width:11px;height:11px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 4px rgba(37,99,235,.18)}
.dark .step .dot{background:var(--accent-tint);box-shadow:0 0 0 4px rgba(6,182,212,.22)}
.step h4{font-family:var(--ff-head);font-size:18px;margin-bottom:7px}
.step p{color:var(--slate);font-size:13.5px}
.dark .step p{color:var(--on-deep-muted)}

/* split feature */
.split{display:grid;grid-template-columns:1fr 1fr;gap:clamp(30px,5vw,70px);align-items:center}
.panel{border-radius:var(--r-xl);overflow:hidden;border:1px solid var(--line);background:linear-gradient(160deg,#132436,#07111F);min-height:340px;position:relative}
/* .split centres its items rather than stretching them, so the panel keeps its own
   340px height and the photo fills it from the corners — same approach as .phero-img. */
.panel-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
/* Was a wrapping flex row: at the .split column width the third stat fell to its own
   line, leaving "Growth" orphaned under a half-empty row. A grid keeps the three on one
   row and still collapses cleanly — auto-fit suits both the 3-stat and 2-stat uses. */
.stat-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,132px),1fr));gap:26px 24px;margin-top:28px}
/* 32px made "Engineering" 185px wide — three of those need 603px in a 528px column, so
   the row could never sit on one line. 26px is the largest that fits three across; min-width:0
   and the wrap guard stop any longer label colliding with its neighbour instead of wrapping. */
.stat-row>*{min-width:0}
.stat-row b{font-family:var(--ff-head);font-size:26px;display:block;color:var(--accent);overflow-wrap:break-word}
.dark .stat-row b{color:var(--accent-tint)}
.stat-row span{font-size:13.5px;color:var(--slate)}

.check{list-style:none;display:grid;gap:14px;margin-top:8px}
.check li{display:flex;gap:12px;align-items:flex-start;font-size:15.5px}
.check svg{width:20px;height:20px;flex:none;color:var(--accent);margin-top:2px}
.dark .check svg{color:var(--accent-tint)}

/* tabs (technology) */
.tabs{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:34px}
.tab{padding:11px 20px;min-height:44px;border-radius:999px;border:1px solid var(--line);font-weight:500;font-size:14.5px;transition:.2s;color:var(--slate)}
.dark .tab{border-color:rgba(255,255,255,.14);color:var(--on-deep)}
.tab.on{background:var(--accent);color:#fff;border-color:var(--accent)}
.techgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.techitem{border:1px solid var(--line);border-radius:14px;padding:18px;font-weight:500;font-size:15px;display:flex;align-items:center;gap:12px;transition:.2s}
.dark .techitem{border-color:rgba(255,255,255,.1)}
.techitem:hover{border-color:var(--accent);transform:translateY(-2px)}
.techitem .d{width:9px;height:9px;border-radius:50%;background:var(--accent-hover);flex:none}
.dark .techitem .d{background:var(--accent-tint)}

/* stack logos — white tiles so brand marks read on light and dark sections */
.logos{display:flex;align-items:center;gap:8px;flex:none}
.logo-tile{width:36px;height:36px;border-radius:10px;flex:none;display:grid;place-items:center;background:#fff;border:1px solid var(--line);box-shadow:0 1px 2px rgba(7,17,31,.06)}
.dark .logo-tile{border-color:rgba(255,255,255,.16)}
.logo-tile img{width:21px;height:21px;object-fit:contain}
.logo-tile.ic{background:linear-gradient(135deg,rgba(37,99,235,.16),rgba(6,182,212,.20));border-color:transparent;color:var(--accent)}
.dark .logo-tile.ic{color:var(--accent-tint);border-color:rgba(255,255,255,.12)}
.logo-tile.ic svg{width:19px;height:19px}
.stack-item{flex-direction:column;align-items:flex-start;gap:14px;padding:20px}
.stack-item .t{font-size:14.5px;line-height:1.35}
.svc-stack{margin-top:clamp(48px,6vw,68px);padding-top:clamp(38px,4vw,48px);border-top:1px solid var(--line)}
.dark .svc-stack{border-top-color:rgba(255,255,255,.1)}

/* accordion / FAQ */
.faq{border-top:1px solid var(--line)}
.faq-item{border-bottom:1px solid var(--line)}
.faq-q{width:100%;text-align:left;display:flex;justify-content:space-between;align-items:center;gap:20px;padding:22px 0;font-family:var(--ff-head);font-size:18px;font-weight:500;color:inherit}
.faq-q .pm{color:var(--accent);font-size:22px;flex:none;transition:.3s}
.dark .faq-q .pm{color:var(--accent-tint)}
.faq-a{max-height:0;overflow:hidden;transition:.3s;color:var(--slate)}
.dark .faq-a{color:var(--on-deep-muted)}
.faq-item.open .faq-a{max-height:300px}
.faq-item.open .pm{transform:rotate(45deg)}
.faq-a p{padding-bottom:22px;font-size:15.5px;max-width:70ch}

/* CTA band */
.ctaband{background:var(--grad);border-radius:var(--r-xl);padding:clamp(38px,6vw,68px);text-align:center;color:#fff;position:relative;overflow:hidden}
.ctaband h2{color:#fff;max-width:18ch;margin-inline:auto}
/* .86 lands at 4.49:1 against --grad's lightest stop (#2563EB) — a hair under
   AA at the light end of the band. .92 clears it with room. */
.ctaband .lead{color:rgba(255,255,255,.92);margin:16px auto 30px}
.ctaband .hero-actions{justify-content:center}

/* breadcrumb */
.crumb{font-size:13.5px;color:var(--slate);display:flex;gap:8px;align-items:center;margin-bottom:22px}
.dark .crumb{color:var(--on-deep-muted)}
/* Bare inline links here measured 38x22 — under the 24x24 minimum target size.
   inline-block lets the vertical padding actually build the hit area; the -5px
   margin keeps the row's visual height and rhythm unchanged. */
.crumb a{display:inline-block;padding-block:5px;margin-block:-5px}
.crumb a:hover{color:var(--accent)}
.phero .crumb a:hover,.dark .crumb a:hover{color:var(--accent-tint)}
/* Still recessed against the crumb links, but .5 put a text glyph at 2.5:1 on
   the hero scrim and .72 at 3.9:1; .85 clears 4.5:1 at the ramp's lightest point. */
.crumb .sep{opacity:.85}

/* page hero (interior) */
.phero{
  background:var(--midnight);color:#fff;position:relative;overflow:hidden;isolation:isolate;
  padding-block:clamp(56px,8vw,84px);min-height:clamp(340px,44vh,500px);
  display:grid;align-items:center;
}
/* Stock photo layer. A touch of contrast keeps the image from going flat once
   the scrim sits on top of it. */
.phero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;filter:contrast(1.06) saturate(1.05)}

/* Scrim alphas are set against the worst case a photo can present — a pure
   white pixel behind the text. The alphas below are what that costs once the
   ramp is measured where the text actually sits rather than at its plateau:
   the emerald tail lifts the ground under a lead that runs into the lower
   third, and the eyebrow (--accent-tint) is the lightest ink in the hero, so
   .70 left both at ~4.4:1. .75 through the copy and .84 into the tail clear
   4.5:1 with margin for every tone here — the tail carries the heavier alpha
   because at 390px a long lead wraps down into it, where the emerald is the
   lightest thing in the ramp. Narrow screens get that vertical
   ramp; from 1100px up the copy is a 620px column on the left, which frees the
   right third of the frame to show the photo at roughly 60-75% strength. */
.phero::before{
  content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg,rgba(7,17,31,.76) 0%,rgba(7,17,31,.75) 55%,rgba(6,59,50,.84) 100%);
}
@media(min-width:1100px){
  .phero::before{
    background:linear-gradient(100deg,rgba(7,17,31,.86) 0%,rgba(7,17,31,.80) 62%,rgba(7,17,31,.40) 84%,rgba(6,59,50,.24) 100%);
  }
}
/* Kept as a brand tint only. At its old .26 it sat right over the reveal zone
   and veiled the photo — the image is the visual interest here now. */
.phero::after{content:"";position:absolute;right:-140px;top:-140px;width:420px;height:420px;z-index:1;background:radial-gradient(circle,rgba(6,182,212,.12),transparent 68%);filter:blur(24px)}
/* Photoless variant. There is no image to scrim, so the heavy ramp above would
   only bury the field — it drops to a soft vignette and the grid reads through.
   Text contrast here comes from the midnight ground itself, not from the scrim. */
.phero-grid{position:absolute;inset:0;width:100%;height:100%;z-index:0}
.phero.tech::before{background:linear-gradient(100deg,rgba(7,17,31,.55) 0%,rgba(7,17,31,.30) 60%,rgba(7,17,31,0) 100%)}
@media(min-width:1100px){.phero.tech::before{background:linear-gradient(100deg,rgba(7,17,31,.55) 0%,rgba(7,17,31,.28) 62%,rgba(7,17,31,0) 100%)}}
.phero.tech::after{background:radial-gradient(circle,rgba(37,99,235,.22),transparent 66%)}

/* The wrap stays full width so the scrim's 62% plateau lines up with the page
   grid; the copy itself is capped at 620px, which keeps it inside that plateau
   at every width from 1100px up. */
.phero-inner{position:relative;z-index:2}
.phero-inner > *{max-width:620px}
/* The page hero is a dark ground but carries no .dark class, so the light-ground
   text colours leaked in: the lead sat at 1.89:1 and the breadcrumb at 3.45:1.
   These tones are also what let the scrim above run as light as it does. */
/* The home hero has the same problem for the same reason — it is a midnight
   ground with no .dark class, so its lead was inheriting the light-ground ink
   (1.89:1) and its eyebrow the light-ground emerald (2.87:1). */
.phero .lead,.hero .lead{color:#CBD5E1}
.phero .crumb{color:#CBD5E1}
.phero .muted,.hero .muted{color:#CBD5E1}
.phero .eyebrow,.hero .eyebrow{color:var(--accent-tint)}
.phero h1,.phero .lead,.phero .crumb,.phero .eyebrow{text-shadow:0 1px 14px rgba(7,17,31,.45)}

/* insights cards */
.post{border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;transition:.28s;background:#fff;display:flex;flex-direction:column}
.dark .post{background:var(--deep-2);border-color:rgba(255,255,255,.08)}
.post:hover{transform:translateY(-4px);box-shadow:var(--shadow-1);border-color:var(--accent)}
/* The gradient is now only a placeholder tint behind the photo while it loads. */
.post .thumb{height:170px;background:var(--grad-bright);position:relative;overflow:hidden}
.post .thumb img{width:100%;height:100%;object-fit:cover;display:block}
/* The chip used to sit on that fixed dark gradient, where .55 gave 7.91:1. Over a photo
   its ground is whatever the image happens to be, so the alpha is set against the worst
   case — a pure white pixel — where .55 was only 4.20:1. .68 holds 6.62:1 there. */
.post .thumb .tag{position:absolute;left:16px;top:16px;background:rgba(7,17,31,.68);backdrop-filter:blur(6px);color:#fff;font-size:12px;font-weight:600;padding:6px 12px;border-radius:999px}
.post .body{padding:22px;flex:1;display:flex;flex-direction:column}
.post h3{font-size:18.5px;margin-bottom:10px}
.post p{color:var(--slate);font-size:14px;flex:1}
.dark .post p{color:var(--on-deep-muted)}
.post .meta{margin-top:16px;font-size:12.5px;color:var(--slate);display:flex;gap:8px}
/* The single agreed metric, called out under the summary. flex:none keeps it
   from absorbing the card's spare height the way .post p does. */
.post .cs-metric{color:var(--accent);font-weight:600;flex:none;margin-top:12px;font-size:14.5px}
.dark .post .cs-metric{color:var(--accent-tint)}
.post .badges{margin-top:14px}

/* contact form */
.formgrid{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.field{display:flex;flex-direction:column;gap:8px}
.field.full{grid-column:1/-1}
.field label{font-size:13.5px;font-weight:600;color:var(--charcoal)}
.dark .field label{color:#CBD5E1}
.field input,.field select,.field textarea{
  font-family:inherit;font-size:15px;padding:14px 16px;border-radius:12px;
  border:1px solid var(--line);background:#fff;color:var(--ink);transition:.2s;width:100%;
}
.dark .field input,.dark .field select,.dark .field textarea{background:var(--deep-2);border-color:rgba(255,255,255,.12);color:#fff}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(6,182,212,.20)}
.field textarea{resize:vertical;min-height:120px}
/* Validation state. The message carries the meaning; the red border only reinforces
   it, so the form does not signal errors by colour alone. #B91C1C is 6.47:1 on white
   (the old #EF4444 was 3.76:1 and failed AA as text). */
.field-err{display:none;margin-top:7px;font-size:13px;font-weight:500;color:#B91C1C}
.field-err.show{display:block}
.field :is(input,select,textarea)[aria-invalid="true"]{border-color:#B91C1C}
.field :is(input,select,textarea)[aria-invalid="true"]:focus{box-shadow:0 0 0 3px rgba(185,28,28,.18)}
.dark .field-err{color:#FCA5A5}
.success{text-align:center;padding:48px 20px;display:none}
.success.show{display:block;animation:pop .5s cubic-bezier(.2,.9,.3,1.3)}
.success .ok{width:76px;height:76px;border-radius:50%;background:linear-gradient(135deg,#1E3A8A,#059669);display:grid;place-items:center;margin:0 auto 24px}
.success .ok svg{width:36px;height:36px;color:#fff}
@keyframes pop{from{opacity:0;transform:scale(.85)}to{opacity:1;transform:scale(1)}}

.contact-aside{display:grid;gap:22px;align-content:start}
.cinfo{display:flex;gap:14px;align-items:flex-start}
.cinfo .ci{width:44px;height:44px;border-radius:12px;background:rgba(37,99,235,.12);color:var(--accent);display:grid;place-items:center;flex:none}
.dark .cinfo .ci{color:var(--accent-tint)}
.cinfo b{display:block;font-family:var(--ff-head);font-size:16px;margin-bottom:3px}
.cinfo span{color:var(--slate);font-size:14.5px}
.cinfo .ph{font-size:12px}   /* .cinfo span would otherwise out-specify .ph and resize the chip */
.dark .cinfo span{color:var(--on-deep-muted)}

/* footer */
footer{background:var(--midnight);color:#AEB7CE;padding-top:clamp(56px,7vw,88px)}
.foot-grid{display:grid;grid-template-columns:1.6fr repeat(4,1fr);gap:40px}
.foot-brand .brand{margin-bottom:18px}
.foot-brand p{font-size:14.5px;max-width:32ch;color:#94A3B8}
.foot-col h2{font-family:var(--ff-head);color:#fff;font-size:15px;margin-bottom:18px;font-weight:600}
.foot-col a{display:block;color:#94A3B8;font-size:14px;padding:6px 0;transition:.18s}
.foot-col a:hover{color:var(--accent-tint)}
.foot-bottom{border-top:1px solid rgba(255,255,255,.08);margin-top:clamp(44px,6vw,72px);padding-block:26px;display:flex;justify-content:space-between;align-items:center;gap:20px;flex-wrap:wrap}
.foot-bottom .statement{font-family:var(--ff-head);color:#fff;font-size:16px}
.socials{display:flex;gap:10px}
.socials a{width:38px;height:38px;border-radius:10px;border:1px solid rgba(255,255,255,.12);display:grid;place-items:center;color:#AEB7CE;transition:.2s}
.socials a:hover{border-color:var(--accent-bright);color:#fff;background:rgba(6,182,212,.20)}
.socials svg{width:17px;height:17px}

/* reveal — gated on .js (set by an inline script in <head>) so the hidden state
   only ever exists where the observer that clears it can run. Without that gate
   a JS failure leaves 48 blocks per page permanently at opacity 0. */
.js .reveal{opacity:0;transform:translateY(24px);transition:.7s cubic-bezier(.2,.7,.2,1)}
.js .reveal.in{opacity:1;transform:none}

/* placeholder note */
/* --accent on its own 10% tint composites to 4.21:1 at 12px — under AA. The
   darker tier clears it at 5.45:1 on the same ground. That ground is stated as
   a solid rather than an alpha tint: as a tint it composited with whatever
   section was behind it, which put the chip at 4.47:1 on .soft. */
.ph{display:inline-block;font-size:12px;font-weight:600;color:var(--accent-hover);background:#E9EFFD;padding:4px 10px;border-radius:6px;margin-left:8px;vertical-align:middle}
/* Same leak as the hero text above: .ph is used inside .phero .eyebrow on the
   case-study pages, where the light-ground emerald drops to 3.21:1 and its .10
   tint disappears into the midnight. Dark grounds get the bright tier.
   The chip's own ground has to be a dark cyan rather than a cyan wash: over a
   photo hero the wash composites toward the image, which pulled the tint down
   to 3.7:1 there while still measuring 8.5:1 on solid midnight. */
.phero .ph,.hero .ph,.dark .ph{color:var(--accent-tint);background:rgba(8,74,88,.62)}
/* A chip sitting at the foot of a card rather than inline after a heading: the
   inline offsets would push it out of line with the card's own text column. */
.card > .ph{margin-left:0;margin-top:18px}

/* Solution approach sections: heading and diagram share the top row, the step
   list runs full width beneath. */
.approach-top{margin-bottom:clamp(36px,5vw,56px)}

/* ============ HERO VISUAL (Section 02) ============
   The stock photo is gone — the brief rules out corporate photography — and the
   right column now carries the capability system as inline SVG. It sits above
   the flow canvas that spans the whole hero, so the bands read behind it. */
.hero-visual{position:relative;z-index:2;display:grid;place-items:center}
.eco{width:100%;max-width:520px;height:auto;overflow:visible;color:#CBD5E1}
.eco-links line{stroke:var(--accent-tint);stroke-opacity:.30;stroke-width:1.2}
.eco-ring{stroke-dasharray:3 7;stroke-opacity:.18!important}
/* Dash travel reads as data moving between capabilities. One shared keyframe,
   staggered per spoke by --d, so five nodes cost one animation definition. */
.eco-spoke{stroke-dasharray:5 9;animation:ecoflow 2.6s linear infinite;animation-delay:var(--d)}
@keyframes ecoflow{to{stroke-dashoffset:-28}}
.eco-halo{fill:rgba(37,99,235,.16);stroke:rgba(56,189,248,.28);stroke-width:1}
.eco-disc{fill:#0B1626;stroke:rgba(56,189,248,.45);stroke-width:1.4}
.eco-ic{fill:none;stroke:var(--accent-tint);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.eco-label{fill:currentColor;font-family:var(--ff-body);font-size:13px;font-weight:500;letter-spacing:.01em}
.eco-node{animation:ecopulse 4.5s ease-in-out infinite;animation-delay:var(--d);transform-box:fill-box;transform-origin:center}
@keyframes ecopulse{0%,100%{opacity:.86}50%{opacity:1}}
.eco-core-halo{fill:rgba(37,99,235,.20);stroke:rgba(56,189,248,.22);stroke-width:1}
.eco-core-disc{fill:url(#eco-core);fill-opacity:.14;stroke:url(#eco-core);stroke-width:1.8}
.eco-core-t{fill:#F8FAFC;font-family:var(--ff-head);font-size:16px;font-weight:700}

/* ============ CONVERGENCE (Section 05) ============ */
/* The diagram appears on both grounds — dark on solution pages, .soft on service
   pages — so every colour needs a light-ground default with a .dark override.
   Defaulting to the dark-ground tokens put near-white text on light grey at
   1.03:1, which is invisible rather than merely low contrast. */
.cv{width:100%;max-width:520px;height:auto;overflow:visible;color:var(--slate)}
.dark .cv{color:var(--on-deep)}
.cv-path{stroke-width:1.6;stroke-opacity:.75;stroke-dasharray:4 8;
  animation:ecoflow 3.2s linear infinite;animation-delay:var(--d)}
.dark .cv-path{stroke-opacity:.55}
.cv-dot{fill:var(--accent)}
.dark .cv-dot{fill:var(--accent-tint)}
.cv-label{fill:currentColor;font-family:var(--ff-body);font-size:14px;font-weight:500}
.cv-out rect{fill:rgba(37,99,235,.08);stroke-width:1.6}
.dark .cv-out rect{fill:rgba(37,99,235,.16)}
.cv-outt{fill:var(--ink);font-family:var(--ff-head);font-size:15px;font-weight:700}

/* coverage globe (contact) — same conventions as .cv above: labels inherit
   currentColor so the panel reads on light and dark grounds, and the accent
   dots move to the midnight tier under .dark. */
.globe{width:100%;max-width:520px;height:auto;display:block;margin-inline:auto;color:var(--slate)}
.globe .g-sphere{fill:rgba(37,99,235,.05)}
.dark .globe .g-sphere{fill:rgba(37,99,235,.14)}
.globe .g-grid{stroke:var(--line);stroke-width:1.1;fill:none}
.dark .globe .g-grid{stroke:var(--line-dark)}
.globe .g-route{stroke-width:1.6;stroke-opacity:.75;stroke-dasharray:4 8}
.globe .g-node{fill:var(--accent)}
.dark .globe .g-node{fill:var(--accent-tint)}
.globe .g-halo{fill:rgba(6,182,212,.16)}
.globe .g-lead{stroke:var(--line);stroke-width:1;fill:none}
.dark .globe .g-lead{stroke:var(--line-dark)}
.globe .g-label{fill:currentColor;font-family:var(--ff-body);font-size:13.5px;font-weight:500}
/* careers role rows — the arrow tracks on hover the way .card.build does, so a
   row reads as a link rather than as a panel that happens to be clickable. */
.rolelist{display:grid;gap:14px;margin-top:24px}
.role{display:flex;justify-content:space-between;align-items:center;gap:18px;flex-wrap:wrap;
  background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);padding:22px 26px;transition:.28s}
.role:hover{transform:translateY(-2px);border-color:var(--accent);box-shadow:var(--shadow-1)}
.role-t{display:grid;gap:4px}
.role-t b{font-family:var(--ff-head);font-size:18px}
.role-meta{color:var(--slate);font-size:14px}
.role .textlink svg{transition:.25s}
.role:hover .textlink svg{transform:translateX(4px)}

.regions{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,180px),1fr));gap:20px 24px}
.regions>*{min-width:0}
/* direct children only: `.regions span` would otherwise out-specify .ph and
   resize a chip nested inside the value. */
.regions > div > b{display:block;font-family:var(--ff-head);font-size:15.5px;margin-bottom:4px}
.regions > div > span{color:var(--slate);font-size:14.5px}
.dark .cv-outt{fill:#F8FAFC}
.define{margin-bottom:26px}
.define h3{margin-bottom:8px}
.define p{color:var(--on-deep-muted);font-size:15.5px}

/* ============ TECHNOLOGY BADGES ============ */
.badges{display:flex;flex-wrap:wrap;gap:7px;margin-top:16px}
.badge{font-size:12px;font-weight:500;letter-spacing:.01em;padding:4px 9px;border-radius:var(--r-sm);
  border:1px solid var(--line);color:var(--slate);background:var(--soft)}
.dark .badge{border-color:rgba(255,255,255,.14);color:var(--on-deep-muted);background:rgba(255,255,255,.04)}
/* The arrow only appears on hover/focus, so a five-card row stays quiet at rest. */
.card.build .more,.card.ind .more{opacity:.62;transition:.25s}
.card.build:hover .more,.card.ind:hover .more,
.card.build:focus-visible .more,.card.ind:focus-visible .more{opacity:1}
.card.build:hover .more svg,.card.ind:hover .more svg{transform:translateX(4px)}
.card.build .more svg,.card.ind .more svg{transition:transform .25s}

/* Card thumbnails. Only `.post .thumb` was ever styled, so the same helper
   inside a `.card` had no height rule: the 800x384 image fell back to its height
   ATTRIBUTE (384px) while max-width squeezed the width to the card, leaving it
   tall and horizontally stretched. A fixed height with object-fit crops instead,
   and the tag becomes an overlay pill rather than a stray line of text. */
.card .thumb{height:150px;border-radius:var(--r);overflow:hidden;position:relative;background:var(--grad-bright)}
.card .thumb img{width:100%;height:100%;object-fit:cover}
.card .thumb .tag{position:absolute;left:12px;top:12px;background:rgba(7,17,31,.68);
  backdrop-filter:blur(6px);color:#fff;font-size:12px;font-weight:600;padding:5px 11px;border-radius:999px}

/* ============ CASE STUDIES (Section 06) ============
   Editorial rows rather than a portfolio grid: the media leads on desktop and
   stacks above the copy below 860px. */
.cstudies{display:grid;gap:26px}
.cstudy{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);gap:clamp(24px,4vw,52px);
  align-items:center;padding:clamp(20px,2.4vw,28px);border:1px solid var(--line);
  border-radius:var(--r-lg);background:#fff;transition:.28s}
.cstudy:hover{border-color:var(--accent);box-shadow:var(--shadow-1);transform:translateY(-3px)}
.cstudy-media .thumb{margin:0}
.cstudy-n{display:block;font-family:var(--ff-head);font-size:13px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--accent);margin-bottom:10px}
.cstudy-body h3{margin-bottom:18px}
.cstudy-flow{display:flex;flex-wrap:wrap;gap:8px;list-style:none;margin-bottom:20px}
.cstudy-flow li{font-size:13px;font-weight:500;color:var(--slate);padding:5px 11px;
  border:1px solid var(--line);border-radius:999px}
/* The chevron between stages is drawn, not typed, so it never lands at the start
   of a wrapped line the way a literal separator character would. */
.cstudy-flow li+li{position:relative}
.cstudy-flow li+li::before{content:"";position:absolute;left:-6px;top:50%;width:4px;height:4px;
  border-top:1.4px solid var(--line);border-right:1.4px solid var(--line);
  transform:translateY(-50%) rotate(45deg)}

/* ============ TECHNOLOGY ECOSYSTEM (Section 07) ============ */
.ecogrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,250px),1fr));gap:18px}
.ecocard{border:1px solid var(--line);border-radius:var(--r-lg);padding:24px;background:#fff;transition:.25s}
.ecocard:hover{border-color:var(--accent);transform:translateY(-3px);box-shadow:var(--shadow-1)}
.ecocard-h{display:flex;align-items:center;gap:12px;margin-bottom:16px}
.ecocard-h h3{font-size:18px}
.ecocard ul{list-style:none;display:grid;gap:9px}
.ecocard li{color:var(--slate);font-size:14.5px;padding-left:16px;position:relative}
.ecocard li::before{content:"";position:absolute;left:0;top:9px;width:6px;height:6px;
  border-radius:50%;background:var(--accent);opacity:.55}

/* ============ CLOSING CTA (Section 11) ============
   Full-bleed navy rather than the inset gradient band: this is the end of the
   page, so it reads as a destination instead of one more card. */
.finale{position:relative;overflow:hidden;background:var(--midnight);color:#F8FAFC;
  padding-block:clamp(80px,11vw,140px);text-align:center}
.finale #ctaflow{position:absolute;inset:0;width:100%;height:100%;z-index:0}
.finale::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(ellipse at 50% 40%,rgba(37,99,235,.22),transparent 62%)}
.finale-inner{position:relative;z-index:2}
.finale .lead{color:#CBD5E1;margin-top:16px}
.finale .hero-actions{justify-content:center}

/* ============ RESPONSIVE ============ */
@media(max-width:1024px){
  .hero-grid{grid-template-columns:1fr}
  .steps{grid-template-columns:repeat(3,1fr)}
  .g4{grid-template-columns:repeat(2,1fr)}
  .techgrid{grid-template-columns:repeat(3,1fr)}
  .foot-grid{grid-template-columns:1fr 1fr 1fr}
  .foot-brand{grid-column:1/-1}
}
/* The nav switches to the burger on its own width, not the layout's. Brand (197)
   + seven menu items (716) + CTA (124) + gutters needs ~1175px; when the bar is
   wider than the step, it overflows the viewport in the band between them and
   gives the whole page a horizontal scrollbar. Re-measure this after adding or
   renaming a nav item. */
@media(max-width:1200px){
  .menu,.nav-cta .btn{display:none}
  .burger{display:flex}
  .mobilenav{display:block}
}
@media(max-width:860px){
  .split,.g3,.g2,.hero-grid,.cstudy{grid-template-columns:1fr}
  .cstudy-media{order:-1}
  .steps{grid-template-columns:repeat(2,1fr)}
  .techgrid{grid-template-columns:repeat(2,1fr)}
  .formgrid{grid-template-columns:1fr}
  .foot-grid{grid-template-columns:1fr 1fr}
  .foot-bottom{flex-direction:column;align-items:flex-start}
}
@media(max-width:480px){
  .g4,.techgrid,.steps{grid-template-columns:1fr}
  /* 24px of the 280px row at 320w left 85px columns, and "Modernise" broke mid-word. */
  .metrics{gap:12px}
  .foot-grid{grid-template-columns:1fr}
  .hero-actions{flex-direction:column}
  .hero-actions .btn{width:100%}
}
/* Applied AI split on the home page: a 2x2 of icon + label + one-line descriptor
   between the copy and the CTA. The icon shares row 1 with the label and the
   descriptor sits under the label, not under the icon, so the two text lines
   share a left edge. */
/* auto-fit, not repeat(2,1fr): between 861px and 1024px the .split is still two
   columns but narrow, which squeezed these cells to ~170px and wrapped both the
   label and its descriptor onto two lines. The 210px floor drops to one column
   there instead, and goes back to two as soon as the column can hold them. */
.featgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr));gap:24px 30px;margin:28px 0 34px}
.featgrid>*{min-width:0}
.feat{display:grid;grid-template-columns:auto 1fr;column-gap:10px;row-gap:3px;align-items:start}
.feat .fi{display:grid;place-items:center;color:var(--accent);grid-row:1}
.dark .feat .fi{color:var(--accent-tint)}
.feat .fi svg{width:19px;height:19px;stroke-width:1.8}
.feat b{font-family:var(--ff-head);font-size:16px;align-self:center}
.feat>span:last-child{grid-column:2;color:var(--slate);font-size:14px}
.dark .feat>span:last-child{color:var(--on-deep-muted)}
/* The About panel's 340px floor is short for a section whose whole right half is
   the image; this one carries the section on its own. */
.panel.tall{min-height:clamp(340px,42vw,520px)}

/* About page in-page nav. Vision & Mission and Our Approach are anchored sections
   of about.html now, so every jump target has to clear the sticky header --
   without scroll-margin-top the heading lands underneath it. */
.jumpwrap{padding-block:24px;border-bottom:1px solid var(--line);background:#fff;position:relative;z-index:1}
.jumpnav{margin-bottom:0;justify-content:center}
a.tab:hover{border-color:var(--accent);color:var(--accent)}
.jumped{scroll-margin-top:96px}

/* Home capability strip. Eight labels sat in a plain pill row; the .techitem card
   gives each one an icon and a link to its service page. Its own steps are needed
   because .techgrid's 3-column step would break eight items into a ragged 3+3+2. */
.capgrid{gap:12px}
@media(max-width:1024px){.capgrid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:480px){.capgrid{grid-template-columns:1fr}}

@media(prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important;scroll-behavior:auto!important}
  .js .reveal{opacity:1;transform:none}
}
