/* ==========================================================================
   Sentinel Security Technology - Design System
   White and cream paper, a four stop green ramp, lime accent.
   Shape language: soft capsules, 28px cards, notched CTA tabs, pill buttons.
   ========================================================================== */

/* ---------- 0. Type ---------- */
/* Manrope (SIL OFL) carries body copy, headings and every number. */
@font-face { font-family: "Manrope"; src: url("../fonts/manrope-400.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Manrope"; src: url("../fonts/manrope-500.woff2") format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "Manrope"; src: url("../fonts/manrope-600.woff2") format("woff2"); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: "Manrope"; src: url("../fonts/manrope-700.woff2") format("woff2"); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: "Manrope"; src: url("../fonts/manrope-800.woff2") format("woff2"); font-weight: 800; font-style: normal; font-display: swap; }
/* Caveat (SIL OFL) is a handwriting face, used only for short
   symbolic phrases. Upright rather than oblique so it sits level with the grid. */
@font-face { font-family: "Marker"; src: url("../fonts/marker.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Caveat"; src: url("../fonts/caveat.woff2") format("woff2"); font-weight: 600; font-style: normal; font-display: swap; }

/* ---------- 1. Tokens ---------- */
:root {
  /* Green ramp.
     The dark end carries most of this site, so it is a real scale rather than
     one value: seven steps whose hue drifts 158 to 147 as they lighten, meeting
     the brand mid at 146. Depth on dark surfaces comes from picking a different
     step, never from washing white over the same one. */
  --g-950:   #03140E;  /* deepest: the footer, the foot of the hero scrim */
  --g-900:   #051D14;  /* dark section grounds, the mobile drawer */
  --g-850:   #06291B;  /* the default dark, and every dark heading */
  --g-800:   #093522;  /* surfaces sitting ON a dark ground, so they lift */
  --g-750:   #0B4328;  /* those surfaces on hover */
  --g-700:   #0C522E;  /* mid dark accents */
  --g-650:   #0C5F31;  /* the step just below the brand green */

  --g-dark:  var(--g-850);
  --g-mid:   #0C6934;  /* the logo green */
  --g-light: #3FB56F;
  /* The accent: the logo's hue, at the lightness the dark ground needs.
     The mark itself (#0C6934) measures 2.78:1 on --g-950 and cannot carry
     type there; this is the same green at 54% lightness, 9.7:1 on the dark
     and 8.0:1 for ink set on top of it. */
  /* The dark ground's channels, so an overlay can take an alpha and still
     follow the theme. Every scrim uses rgb(var(--shade-rgb) / x). */
  --shade-rgb:  3 20 14;
  --accent-rgb: 53 222 126;

  --accent:   #35DE7E;
  --accent-2: #22C96B;  /* pressed and hover */
  --accent-3: #8FEFBB;  /* tint */
  --accent-4: #DCF8E8;  /* wash */

  /* The old names, kept: they are used in seventy places and renaming them
     for its own sake is churn rather than clarity. */
  --lime:    var(--accent);
  --lime-2:  var(--accent-2);
  --lime-3:  var(--accent-3);
  --lime-4:  var(--accent-4);

  /* Aliases kept so component rules read naturally */
  --green:   var(--g-mid);
  --green-2: #0F8442;
  --green-3: var(--g-light);
  --ink:     var(--g-850);
  --ink-2:   var(--g-800);
  --ink-3:   var(--g-700);

  /* The full ramp, for any surface that wants all four */
  --ramp:      linear-gradient(118deg, var(--g-950) 0%, var(--g-800) 22%, var(--g-mid) 52%, var(--g-light) 78%, var(--lime) 100%);
  --ramp-soft: linear-gradient(118deg, var(--g-950) 0%, var(--g-800) 26%, var(--g-mid) 60%, var(--g-light) 94%, var(--lime) 124%);

  /* Paper */
  --white:   #FFFFFF;
  --cream:   #F7F7EF;
  --cream-2: #F1F1E6;
  --line:    #E4E6DA;
  --line-2:  rgba(255, 255, 255, .14);

  /* Links in running text. Two colours, because a link that only changes its
     underline on hover gives nothing back; one that brightens does.
     The resting colour is the logo green itself. */
  --link:      var(--g-mid);   /* #0C6934 - 6.3:1 on cream, 6.8:1 on white */
  --link-hi:   #0C522E;        /* firmer, 8.2:1 over the wash below */
  --link-wash: var(--accent-4);/* the pale mint highlighter */

  /* Text */
  --body:    #55655B;  /* 5.7:1 on cream */
  --body-2:  #647269;  /* muted, still 4.7:1 on cream. Anything lighter fails AA. */
  --on-dark:      rgba(255, 255, 255, .95);
  --on-dark-soft: rgba(255, 255, 255, .66);

  /* Type */
  --ff:        'Manrope', 'Segoe UI', system-ui, -apple-system, sans-serif;
  --ff-accent: 'Caveat', 'Manrope', cursive;

  /* Shape */
  /* Corner language. Two states only, square or round, never an angled cut.
     Surfaces get a flat top edge that lines up with the grid and a bottom that
     releases; anything you can press is a full capsule. That contrast is the
     point, and it stays readable because there is no third shape. */
  --r-card: 26px;   /* bottom radius, large surfaces */
  --r-lg: 20px;     /* bottom radius, medium surfaces */
  --r-md: 11px;     /* bottom radius, small surfaces */
  --r-pill: 999px;  /* anything you can click */

  /* Ready made corner sets */
  --corner-xl: 0 0 var(--r-card) var(--r-card);
  --corner-lg: 0 0 var(--r-lg) var(--r-lg);
  --corner-md: 0 0 var(--r-md) var(--r-md);
  --notch: 18px;    /* concave joint radius */
  --gap-tab: 26px;  /* horizontal gutter: must clear the fillet */
  --tab-drop: 9px;  /* how far the CTA tab drops below the card body */

  /* Rhythm */
  --container: 1280px;
  --topbar-h: 40px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
  --section-y: clamp(4.5rem, 8vw, 7.5rem);
  --header-h: 82px;

  --sh-1: 0 2px 6px rgba(6, 41, 27, .04);
  --sh-2: 0 8px 28px rgba(6, 41, 27, .08);
  --sh-3: 0 24px 60px rgba(6, 41, 27, .14);

  --ease: cubic-bezier(.22, .61, .36, 1);

  /* Patterns. Drafting grids and dot matrices, drawn as background layers so
     they cost no DOM and no image request. Keep them near the threshold of
     visibility: they should register as texture, never as decoration. */
  --pat-grid-ink:  linear-gradient(rgba(6, 41, 27, .05) 1px, transparent 1px),
                   linear-gradient(90deg, rgba(6, 41, 27, .05) 1px, transparent 1px);
  --pat-grid-lt:   linear-gradient(rgba(255, 255, 255, .045) 1px, transparent 1px),
                   linear-gradient(90deg, rgba(255, 255, 255, .045) 1px, transparent 1px);
  /* The dot and hatch tokens that used to live here are now .pat-dots and
     .pat-hatch in the pattern library, which draws both from one colour
     token instead of keeping an ink copy and a light copy of each. */
  --cell: 34px;
}

/* ---------- Pattern library ----------
   One colour token per ground, eight patterns on top of it. Every pattern
   paints on a pseudo element rather than on the section's own background,
   because the dark bands already use all three background layers for their
   bloom and their ramp, and a pattern written into that list would have to
   know what else was in it.

   At z-index -1 the layer sits above the section's background and below its
   content, which is where a texture belongs.

   Kept near the threshold: these should register as grain when you look for
   them and as nothing when you do not. */
.pat {
  --pat-s: 30px;
  position: relative;
  isolation: isolate;
}
/* The ink colour belongs to the ground, not to the pattern, so a patterned
   card inside a dark band inherits the light one instead of redeclaring the
   dark one and drawing black on black. */
:root { --pat-c: rgb(var(--shade-rgb) / .035); }
.section--dark, .cta, .footer, .phero, .hero,
.card--dark, .ncard--dark, .ncard--green, .unit, .step {
  --pat-c: rgba(255, 255, 255, .038);
}
/* On the accent card the ink has to be the ink: white on that green is a
   haze rather than a texture. */
.ncard--lime { --pat-c: rgb(var(--shade-rgb) / .05); }
.pat::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: var(--pat-img);
  background-size: var(--pat-size, var(--pat-s) var(--pat-s));
  background-position: var(--pat-pos, 0 0);
  opacity: var(--pat-o, 1);
  border-radius: inherit;
}

/* 1. Drafting grid. The default frame of reference. */
.pat-grid  { --pat-img: linear-gradient(var(--pat-c) 1px, transparent 1px),
                        linear-gradient(90deg, var(--pat-c) 1px, transparent 1px);
             --pat-size: var(--pat-s) var(--pat-s), var(--pat-s) var(--pat-s); }

/* 2. Graph paper. The same grid with every fifth line drawn heavier, which
      is what an engineer's pad looks like and what a chart deserves. */
.pat-graph { --pat-img:
               linear-gradient(var(--pat-c) 1px, transparent 1px),
               linear-gradient(90deg, var(--pat-c) 1px, transparent 1px),
               linear-gradient(var(--pat-c) 1px, transparent 1px),
               linear-gradient(90deg, var(--pat-c) 1px, transparent 1px);
             --pat-o: .72;
             --pat-size: 100px 100px, 100px 100px, 20px 20px, 20px 20px; }

/* 3. Dot matrix. */
.pat-dots  { --pat-img: radial-gradient(var(--pat-c) 1.2px, transparent 1.6px);
             --pat-size: 22px 22px; }

/* 4. Offset dots. The same field half a step out on alternate rows, which
      stops the eye finding columns in it. */
.pat-weave { --pat-img: radial-gradient(var(--pat-c) 1.2px, transparent 1.6px),
                        radial-gradient(var(--pat-c) 1.2px, transparent 1.6px);
             --pat-size: 26px 26px, 26px 26px;
             --pat-pos: 0 0, 13px 13px; }

/* 5. Windowpane. Wide bars rather than hairlines, at a wide pitch: a grid
      read as a plan rather than as graph paper. Gradients can only vary
      along one axis, so a true cross is not available here - two broad
      bands crossing is, and it is a different mark from the hairline grid,
      which is what the band needs. */
.pat-cross { --pat-img:
               linear-gradient(90deg, transparent calc(50% - 2px), var(--pat-c) calc(50% - 2px) calc(50% + 2px), transparent calc(50% + 2px)),
               linear-gradient(transparent calc(50% - 2px), var(--pat-c) calc(50% - 2px) calc(50% + 2px), transparent calc(50% + 2px));
             --pat-size: 64px 64px, 64px 64px; }

/* 6. Scan lines. A monitor seen close up, for the bands that are about
      watching something. */
.pat-scan  { --pat-img: repeating-linear-gradient(0deg, var(--pat-c) 0 1px, transparent 1px 7px);
             --pat-size: auto; }

/* 7. Diagonal hatch. */
.pat-hatch { --pat-img: repeating-linear-gradient(135deg, var(--pat-c) 0 1px, transparent 1px 11px);
             --pat-size: auto; }

/* 8. Rings. A sweep leaving a corner, for the places that are about
      detection and for the foot of the page. */
.pat-rings { --pat-img: repeating-radial-gradient(circle at var(--pat-at, 12% 120%),
                          var(--pat-c) 0 1px, transparent 1px 44px);
             --pat-size: auto; }

/* 9. Traces. Right angles and nodes: a board, for the technology pages. */
.pat-trace { --pat-img:
               repeating-linear-gradient(90deg, var(--pat-c) 0 1px, transparent 1px 38px),
               repeating-linear-gradient(0deg, var(--pat-c) 0 1px, transparent 1px 38px),
               radial-gradient(circle at 38px 38px, var(--pat-c) 0 2.4px, transparent 2.6px);
             --pat-size: auto, auto, 38px 38px; }

/* Two components already draw a rule on ::before - the hover line along a
   card's top edge - so for those the texture moves to ::after rather than
   fighting over the same pseudo element and losing. */
.pat--after::before { content: none; }
.pat--after::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  border-radius: inherit;
  background-image: var(--pat-img);
  background-size: var(--pat-size, var(--pat-s) var(--pat-s));
  background-position: var(--pat-pos, 0 0);
  opacity: var(--pat-o, 1);
}

/* The notched card is two surfaces - the body and the filler beside the tab
   - so the texture is painted on both from one property inherited off the
   article. Painted on ::after, because ::before is the hover rule. */
.ncard__main, .ncard__fill { position: relative; isolation: isolate; }
.ncard__main::after, .ncard__fill::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  border-radius: inherit;
  background-image: var(--pat-img);
  background-size: var(--pat-size, var(--pat-s, 30px) var(--pat-s, 30px));
  background-position: var(--pat-pos, 0 0);
}

/* A band carrying a photograph is already carrying a texture. */
.section--photo.pat::before { display: none; }

/* ---------- 2. Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  overflow-x: clip;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 20px);
}

body {
  margin: 0;
  background: var(--white);
  color: var(--body);
  font-family: var(--ff);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}
body.is-locked { overflow: hidden; }

img, svg, video, iframe { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }
ul, ol { margin: 0; padding: 0; list-style: none; }

::selection { background: var(--lime); color: var(--ink); }

:focus-visible { outline: 3px solid var(--green-3); outline-offset: 3px; border-radius: 4px; }

.skip-link {
  position: absolute; left: 1rem; top: -100px; z-index: 300;
  background: var(--ink); color: #fff;
  padding: .8rem 1.3rem; border-radius: 0 0 var(--r-md) var(--r-md);
  font-weight: 700;
  transition: top .2s var(--ease);
}
.skip-link:focus { top: 0; }

/* ---------- 3. Typography ---------- */
h1, h2, h3, h4, h5 {
  margin: 0 0 .5em;
  color: var(--g-dark);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -.032em;
  text-wrap: balance;
}

.h-hero {
  font-size: clamp(2.3rem, min(6.4vw, 7.6vh), 4.9rem);
  font-weight: 800;
  line-height: .95;
  letter-spacing: -.035em;
  text-transform: uppercase;
  /* pretty, not balance: balance equalises line lengths and will strand a
     single word to do it, which is exactly what it did here. */
  text-wrap: pretty;
}

/* The one drawn word per headline. Baseline aligned by metrics, six percent
   up on size because an irregular stroke reads smaller than a solid one, and
   tracked open because marker letterforms crowd. */
.h-hero .accent-lime {
  font-family: "Marker", "Caveat", cursive;
  font-weight: 400;
  font-size: 1.06em;
  letter-spacing: .012em;
  padding-right: .06em;
}
.h-1 { font-size: clamp(2.2rem, 5vw, 3.9rem); letter-spacing: -.032em; }
.h-2 { font-size: clamp(1.9rem, 3.8vw, 3.05rem); }
.h-3 { font-size: clamp(1.35rem, 2.1vw, 1.7rem); letter-spacing: -.022em; }
.h-4 { font-size: clamp(1.1rem, 1.6vw, 1.3rem); letter-spacing: -.018em; }

p { margin: 0 0 1.1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

.lead { font-size: clamp(1.02rem, 1.25vw, 1.14rem); line-height: 1.7; }
.muted { color: var(--body-2); }

/* Every figure on the site: Manrope, lining and tabular so columns line up. */
.num { font-variant-numeric: tabular-nums lining-nums; font-feature-settings: "tnum" 1, "lnum" 1; letter-spacing: -.03em; }

/* Short symbolic phrases only, never numbers. Caveat's cap height is small
   against Manrope, so every accent line carries its own size bump rather than
   inheriting the body size. */
.script {
  font-family: var(--ff-accent);
  font-weight: 600;
  font-size: 1.32em;
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.15;
}
.script--lg {
  display: block;
  font-size: clamp(1.75rem, 3.1vw, 2.45rem);
  color: var(--g-mid);
  margin: -.2rem 0 1.1rem;
}
.section--lime .script--lg { color: var(--g-dark); opacity: .72; }

/* Eyebrow — outlined capsule with a six-point asterisk */
/* Section overline: a rule and a label. The pill it replaces was the single
   most recognisable component on a generated landing page. */
.overline {
  display: block;
  margin: 0 0 1.1rem;
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--g-mid);
}
/* No rule above the overline. There was a 26px dash over every one of them,
   which on a page with this many sections became the most repeated mark on
   the site - and under an icon it read as an underline the icon did not
   ask for. The overline is already set apart by its size, its weight, its
   tracking and its colour; it does not need a fifth signal. */
.overline--dark { color: var(--lime); }
.overline--lime { color: var(--g-850); }

/* The figures band: three numbers, no boxes. */
.figures {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1rem, 2.5vw, 2rem);
  margin: 2rem 0 0;
  padding-top: 1.6rem;
  border-top: 1px solid var(--line);
}
.figures dt {
  font-size: clamp(1.8rem, 3.4vw, 2.6rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.035em;
  color: var(--ink);
}
.figures dd {
  margin: .45rem 0 0;
  font-size: .82rem;
  line-height: 1.35;
  color: var(--body-2);
}

.accent { color: var(--green); }
.accent-lime { color: var(--lime); }

/* ---------- 3b. Phosphor icons ---------- */
.ph, .ph-duotone, .ph-fill { font-size: 1em; line-height: 1; vertical-align: middle; }
/* The Sentinel glyphs are SVG rather than a font, so they take their size
   from the same scale and their colour from `color`. */
.si {
  width: 1em; height: 1em;
  display: inline-block;
  flex: none;
  vertical-align: -0.145em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Carried by a number's hidden twin while the visible one is mid flight,
   so a screen reader never reads a half rolled phone number. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- 3c. The mark on a line item ----------
   Every line in a capability list names a specific thing, so it is marked
   with the glyph for that thing: a dome against the cameras, a beam sensor
   against the beams, a lorry against the delivery. A repeated chevron or a
   repeated square says only "this is a list", which the layout already said.

   The glyph sits in a fixed slot so the text edges stay straight however wide
   the icons draw, and the slot is as tall as one line so the mark centres on
   the first line of a wrapped item rather than drifting to the middle of it.

   Marked aria-hidden in the markup: the line already says what it is, and a
   screen reader announcing "dome camera, CCTV surveillance systems" is worse
   than one announcing the line. */
.card__list li,
.dcard__list li,
.unit__list li,
.footer__links li,
.leader__quals li { display: flex; align-items: flex-start; gap: .62rem; }
.footer__links li { gap: .55rem; }

.li-ico {
  flex: none;
  display: grid;
  place-items: center;
  width: 19px;
  height: 1.5em;              /* one line of the item's own leading */
  color: var(--bullet, var(--green));
  transition: color .4s var(--ease);
}
.li-ico .si  { font-size: 18px; stroke-width: 1.65; }
.li-ico .ph  { font-size: 17px; }

.i-xs { font-size: 14px; }
.i-sm { font-size: 17px; }
.i-md { font-size: 22px; }
.i-lg { font-size: 26px; }
.i-xl { font-size: 34px; }
.i-2xl { font-size: 44px; }

/* ---------- 4. Layout ---------- */
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.container--narrow { max-width: 880px; }

.section { padding-block: var(--section-y); position: relative; }
/* Three tiers, so the page has a rhythm rather than a metronome. */
.section--tight { padding-block: calc(var(--section-y) * .62); }
.section--open { padding-block: calc(var(--section-y) * 1.3); }
.section--cream { background-color: var(--cream); }
.section--white { background: var(--white); }
.section--dark {
  position: relative;
  background-color: var(--g-900);
  background-image:
    radial-gradient(90% 60% at 18% 0%, rgb(var(--accent-rgb) / .14) 0%, rgb(var(--accent-rgb) / 0) 60%),
    linear-gradient(180deg, var(--g-900) 0%, var(--g-850) 46%, var(--g-900) 100%);
  background-size: cover, cover;
  color: var(--on-dark-soft);
}
.section--dark h1, .section--dark h2, .section--dark h3, .section--dark h4 { color: #fff; }
.section--lime {
  background-color: var(--lime);
  background-image: var(--pat-grid-ink);
  background-size: var(--cell) var(--cell);
  color: var(--ink-2);
}
.section--lime h2, .section--lime h3 { color: var(--ink); }

/* Section head — title left, supporting copy right (the reference's signature) */
.shead {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: end;
  margin-bottom: clamp(2.5rem, 4.5vw, 3.75rem);
}
.shead__title { margin: 0; max-width: 16ch; }
.shead__aside { padding-bottom: .5rem; color: var(--body-2); font-size: .98rem; max-width: 46ch; }
.section--dark .shead__aside { color: var(--on-dark-soft); }
.shead--center { grid-template-columns: 1fr; justify-items: center; text-align: center; }
.shead--center .shead__title { max-width: 20ch; }
.shead--center .shead__aside { padding-bottom: 0; }
.shead__cta { display: flex; justify-content: flex-end; align-self: end; padding-bottom: .35rem; }

.grid { display: grid; gap: clamp(1rem, 1.6vw, 1.4rem); }
.g-2 { grid-template-columns: repeat(2, 1fr); }
.g-3 { grid-template-columns: repeat(3, 1fr); }
.g-4 { grid-template-columns: repeat(4, 1fr); }

.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 4.5vw, 4.5rem); align-items: center; }

/* Column rules. Hairlines dropped down the container edges and thirds, so a
   section reads as if it were set on a drawing sheet. Decorative only. */

/* ---------- 5. Buttons ---------- */

/* The signature pill-in-pill: coloured capsule, inner capsule, chevrons */
.pbtn {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: 6px 1.15rem 6px 6px;
  background: var(--lime);
  border: 0;
  border-radius: var(--r-pill);
  color: var(--ink);
  cursor: pointer;
  font-size: .95rem;
  line-height: 1;
  transition: background-color .3s var(--ease), transform .3s var(--ease), box-shadow .3s var(--ease);
}
.pbtn__label {
  display: inline-block;
  padding: .82rem 1.35rem;
  background: var(--ink);
  border-radius: var(--r-pill);
  color: #fff;
  font-weight: 700;
  letter-spacing: -.005em;
  transition: background-color .3s var(--ease), color .3s var(--ease);
}
.pbtn__chev { display: inline-flex; align-items: center; flex: none; transition: transform .35s var(--ease); }
.lbl-brief { display: none; }
.pbtn:hover { background: var(--lime-2); transform: translateY(-2px); box-shadow: 0 10px 24px rgba(12, 105, 52, .22); }
.pbtn:hover .pbtn__chev { transform: translateX(4px); }

.pbtn--light .pbtn__label { background: var(--white); color: var(--ink); }
.pbtn--dark { background: var(--ink); color: var(--lime); }
.pbtn--dark .pbtn__label { background: var(--lime); color: var(--ink); }
.pbtn--dark:hover { background: var(--ink-2); }
.pbtn--outline { background: transparent; border: 1px solid var(--line-2); color: #fff; }
.pbtn--outline .pbtn__label { background: transparent; color: #fff; padding-left: .9rem; }
.pbtn--outline:hover { background: rgba(255,255,255,.08); }
.pbtn--block { width: 100%; justify-content: center; }
.pbtn--block .pbtn__label { flex: 1; text-align: center; }

/* Small capsule link */
.plink {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .6rem 1.1rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--ink);
  font-size: .88rem;
  font-weight: 700;
  transition: background-color .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease), gap .3s var(--ease);
}
.plink:hover { background: var(--ink); border-color: var(--ink); color: #fff; gap: .75rem; }

/* Round icon button */
.rbtn {
  width: 52px; height: 52px;
  display: grid; place-items: center;
  flex: none;
  background: var(--lime);
  border-radius: 50%;
  color: var(--ink);
  transition: transform .3s var(--ease), background-color .3s var(--ease);
}
.rbtn:hover { transform: scale(1.07); background: var(--lime-2); }

/* ---------- 6. Top bar ---------- */
.topbar {
  position: relative;
  z-index: 110;
  background: var(--lime);
  color: var(--ink);
  font-size: .82rem;
  font-weight: 500;
}
.topbar__inner { display: flex; align-items: center; gap: 1.5rem; min-height: 40px; padding-block: .35rem; }
.topbar__list { display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap; }
.topbar__list li { display: flex; align-items: center; gap: .45rem; }
.topbar__list i { flex: none; color: var(--g-dark); opacity: .75; }
.topbar__list a:hover { text-decoration: underline; text-underline-offset: 3px; }
.topbar__social { margin-left: auto; display: flex; align-items: center; gap: .85rem; }
.topbar__social span.script { font-size: 1.3rem; white-space: nowrap; opacity: 1; margin-right: .45rem; }
.topbar__social i { display: block; }
.topbar__social a { opacity: .82; transition: opacity .25s var(--ease), transform .25s var(--ease); }
.topbar__social a:hover { opacity: 1; transform: translateY(-2px); }

/* ---------- 7. Header ---------- */
.header {
  position: absolute;
  inset: auto 0 auto 0;
  z-index: 100;
  transition: background-color .35s var(--ease), box-shadow .35s var(--ease);
}
/* The transparent header sits over whichever hero slide is showing, and the
   client will swap those photographs. A scrim of its own means the navigation
   keeps its contrast whatever ends up behind it, rather than depending on the
   picture being dark in the right places. */
.header::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: calc(var(--header-h) + 26px);
  pointer-events: none;
  background: linear-gradient(180deg,
    rgb(var(--shade-rgb) / .76) 0%,
    rgb(var(--shade-rgb) / .48) 55%,
    rgb(var(--shade-rgb) / 0) 100%);
  transition: opacity .35s var(--ease);
}
.header--solid::before { opacity: 0; }
.header__inner { position: relative; }
.header--fixed { position: fixed; top: 0; }
.header__inner { display: flex; align-items: center; gap: 1.25rem; height: var(--header-h); }

.header--solid {
  background: rgba(255, 255, 255, .95);
  backdrop-filter: saturate(1.5) blur(14px);
  -webkit-backdrop-filter: saturate(1.5) blur(14px);
  box-shadow: 0 6px 30px rgba(6, 41, 27, .09);
}
.header--solid .header__inner { height: 70px; }

.brand { display: flex; align-items: center; flex: none; }
.brand img { height: 50px; width: auto; transition: height .35s var(--ease); }
.header--solid .brand img { height: 42px; }
.brand__light { display: block; }
.brand__dark { display: none; }
.header--solid .brand__light { display: none; }
.header--solid .brand__dark { display: block; }

.nav { margin-left: auto; }
.nav__list { display: flex; align-items: center; gap: clamp(.3rem, 1.3vw, 1rem); }
.nav__link {
  display: block;
  padding: .5rem .55rem;
  color: rgba(255, 255, 255, .86);
  font-size: .95rem;
  font-weight: 600;
  border-radius: var(--r-pill);
  transition: color .25s var(--ease);
}
.nav__link:hover, .nav__link[aria-current="page"] { color: var(--lime); }
.header--solid .nav__link { color: var(--ink-2); }
.header--solid .nav__link:hover, .header--solid .nav__link[aria-current="page"] { color: var(--green); }

.header__cta { flex: none; margin-left: .5rem; }

/* No plate. Three bars already read as a menu; a translucent capsule
   around them only adds a shape, and next to a real pill button it reads
   as a second, emptier button. */
.nav-toggle {
  display: none; place-items: center;
  flex: none;
  width: 44px; height: 44px;
  background: none;
  border: 0;
  cursor: pointer; padding: 0;
}
.nav-toggle span { display: block; width: 18px; height: 2px; background: #fff; margin: 4px auto; border-radius: 2px; transition: transform .3s var(--ease), opacity .2s var(--ease); }
.header--solid .nav-toggle span { background: var(--ink); }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ---------- 7b. The group panel under the nav ---------- */
.nav__has-mega > .nav__link {
  display: inline-flex; align-items: center; gap: .3rem;
}
.nav__has-mega > .nav__link i { transition: transform .3s var(--ease); }
.nav__has-mega > .nav__link[aria-expanded="true"] i { transform: rotate(180deg); }
.nav__link[data-within="true"] { color: var(--lime); }
.header--solid .nav__link[data-within="true"] { color: var(--green); }

.mega {
  position: absolute;
  left: 0; right: 0;
  top: 100%;
  background: var(--white);
  border-top: 1px solid var(--line);
  box-shadow: var(--sh-3);
  opacity: 0; visibility: hidden;
  transform: translateY(-8px);
  transition: opacity .25s var(--ease), transform .3s var(--ease), visibility .3s;
}
.mega[hidden] { display: block; }          /* animated, not removed */
.mega.is-open { opacity: 1; visibility: visible; transform: none; }
.mega__inner { padding: clamp(1.4rem, 2.4vw, 2.1rem) var(--gutter) clamp(1.6rem, 2.6vw, 2.3rem); }

.mega__parent {
  display: flex; align-items: center; gap: .9rem;
  padding: .85rem 1.1rem;
  margin-bottom: 1rem;
  border-radius: var(--corner-lg);
  background: var(--g-900);
  color: #fff;
  transition: background-color .3s var(--ease);
}
.mega__parent:hover { background: var(--g-800); }
.mega__mark { display: grid; place-items: center; color: var(--lime); }
.mega__parent strong { display: block; font-size: 1rem; line-height: 1.2; }
.mega__parent small { font-size: .82rem; color: var(--on-dark-soft); }
.mega__go {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: .8rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--lime);
}

.mega__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: .75rem; }
.mega__card {
  display: block;
  padding: 1.1rem 1.15rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: var(--corner-lg);
  background: var(--cream);
  color: var(--ink);
  transition: background-color .3s var(--ease), border-color .3s var(--ease), transform .3s var(--ease);
}
.mega__card:hover { background: var(--white); border-color: var(--g-light); transform: translateY(-3px); }
.mega__logo { display: flex; align-items: center; min-height: 38px; margin-bottom: .6rem; }
.mega__card small { display: block; font-size: .8rem; color: var(--body-2); }
.mega__chips { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .7rem; }
.mega__chips i {
  font-style: normal;
  font-size: .68rem; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase;
  padding: .22rem .5rem;
  border-radius: var(--r-pill);
  background: var(--white);
  border: 1px solid var(--line);
  color: var(--ink-3);
}
.mega__card:hover .mega__chips i { background: var(--cream); }
.mega__units { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .7rem; }
.mega__units a {
  font-size: .76rem; font-weight: 700;
  color: var(--g-mid);
  border-bottom: 1px solid currentColor;
}
.mega__units a:hover { color: var(--ink); }

/* Mobile drawer */
.drawer {
  /* Above the header (100) and the utility bar (110): an open menu owns the
     screen, and the control that closes it must not sit under the one that
     opened it. */
  position: fixed; inset: 0; z-index: 120;
  background-color: var(--g-900);
  background-image: radial-gradient(80% 50% at 80% 0%, rgba(12, 105, 52, .32) 0%, rgba(12, 105, 52, 0) 62%);
  padding: 0 var(--gutter) 2rem;
  display: flex; flex-direction: column; gap: 1.5rem;
  opacity: 0; visibility: hidden; transform: translateY(-10px);
  transition: opacity .3s var(--ease), transform .35s var(--ease), visibility .35s;
  overflow-y: auto;
}
.drawer.is-open { opacity: 1; visibility: visible; transform: none; }

/* The drawer covers the button that opened it, so it carries its own close
   control, sized for a thumb and placed where a close control belongs. */
.drawer__top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  min-height: var(--header-h);
  margin-bottom: 1.5rem;
}
.drawer__brand { display: inline-flex; align-items: center; }
.drawer__brand img { height: 40px; width: auto; display: block; }
.drawer__close {
  flex: none;
  display: grid; place-items: center;
  width: 46px; height: 46px;
  padding: 0;
  background: rgba(255, 255, 255, .1);
  border: 1px solid rgba(255, 255, 255, .26);
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: background-color .25s var(--ease), border-color .25s var(--ease), transform .25s var(--ease);
}
.drawer__close svg { width: 20px; height: 20px; stroke: #fff; stroke-width: 2; stroke-linecap: round; fill: none; }
.drawer__close:hover { background: rgba(255, 255, 255, .18); border-color: rgba(255, 255, 255, .4); }
.drawer__close:active { transform: scale(.94); }

/* And the hamburger becomes an X wherever it is still visible. */
.nav-toggle span { transform-origin: center; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; transform: scaleX(.4); }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
body.is-locked .fab-rail { opacity: 0; visibility: hidden; }
.drawer__list a {
  display: flex; justify-content: space-between; align-items: center;
  padding: 1.05rem 0;
  border-bottom: 1px solid var(--line-2);
  color: #fff; font-size: 1.35rem; font-weight: 700;
}
.drawer__list a span { color: var(--lime); font-size: .9rem; font-weight: 600; }
.drawer__foot { margin-top: auto; display: grid; gap: .75rem; color: var(--on-dark-soft); font-size: .95rem; }
.drawer__foot a { color: #fff; font-weight: 600; }
.drawer__foot .pbtn { margin-top: .5rem; }

/* ---------- 8. Hero ---------- */
.hero {
  position: relative;
  background: var(--ink);
  overflow: hidden;
  isolation: isolate;
  /* One screen, no scrolling to reach the rest of the hero. The top bar and
     header sit above it, so subtract their height rather than guessing. */
  height: calc(100svh - var(--topbar-h));
  min-height: 520px;
  max-height: 1040px;
  padding-top: calc(var(--header-h) + clamp(.75rem, 2.5vh, 2rem));
  padding-bottom: clamp(1.25rem, 3.5vh, 2.75rem);
  display: flex;
  align-items: center;
}
/* ---- Hero carousel ----
   Slides are stacked and crossfaded. Each one carries its own object-position
   so the subject stays clear of the headline, whatever the crop. */
.hero__media {
  position: absolute;
  inset: 0;
  z-index: -4;
  overflow: hidden;
  background: var(--g-900);
}
.hero__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1.4s var(--ease);
  will-change: opacity;
}
.hero__slide.is-active { opacity: 1; }
.hero__slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--pos, 50% 40%);
  /* A light hand. The unify layer below does the colour work, so the image only
     needs its contrast held and its brightness brought down for the type. */
  /* Per slide exposure. Stock frames never match each other, so each one gets a
     handle and the set is balanced by measurement rather than by eye. */
  filter: saturate(.9) contrast(1.04) brightness(calc(.94 * var(--expo, 1)));
}
/* A slow drift on the visible slide only, so the hero is never quite static. */
.hero__slide.is-active img { animation: hero-drift 9s var(--ease) forwards; }
@keyframes hero-drift {
  from { transform: scale(1.015); }
  to   { transform: scale(1.075); }
}

/* 1. Unify. Four photographs shot by different people are four different colour
   temperatures. Blending a single deep green over the hue, while leaving the
   luminance alone, makes them read as one set instead of a slideshow. */
.hero__unify {
  position: absolute; inset: 0; z-index: -3;
  pointer-events: none;
  background: var(--g-850);
  opacity: .12;
  mix-blend-mode: color;
}

/* 2. Vignette. Pulls the corners down so the eye lands in the middle. */
.hero__vignette {
  position: absolute; inset: 0; z-index: -3;
  pointer-events: none;
  background: radial-gradient(118% 92% at 52% 46%, transparent 58%, rgb(var(--shade-rgb) / .26) 100%);
  mix-blend-mode: multiply;
}

/* 2b. Brand bloom. One of the three companies has its own colours, and
   while its slide is up a wash in that blue fades over the whole frame and
   lifts again after it. Opacity rather than a swapped gradient, because a
   gradient cannot transition and the change would land as a jump cut. */
.hero__tint {
  position: absolute; inset: 0; z-index: -2;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.1s var(--ease);
  background:
    radial-gradient(74% 86% at 12% 8%, rgba(29, 79, 168, .50) 0%, rgba(29, 79, 168, 0) 62%),
    radial-gradient(60% 70% at 92% 96%, rgba(95, 149, 242, .26) 0%, rgba(95, 149, 242, 0) 66%);
}
.hero[data-brand="circuitron"] .hero__tint { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .hero__tint { transition: none; } }

/* 3. Grid. Texture, not decoration. */
.hero__grid {
  position: absolute; inset: 0; z-index: -2;
  pointer-events: none;
  background-image: var(--pat-grid-lt);
  background-size: var(--cell) var(--cell);
  opacity: .34;
  -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,.5) 0%, #000 38%, #000 100%);
          mask-image: linear-gradient(90deg, rgba(0,0,0,.5) 0%, #000 38%, #000 100%);
}
.hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  /* Two gentle ramps rather than one steep one. The left carries the copy and
     has cleared by three quarters of the frame; the bottom carries the tab
     strip and hands off to the page. Through the middle the photograph is
     almost untouched, which is the point. */
  background:
    linear-gradient(100deg,
      rgb(var(--shade-rgb) / .82) 0%,
      rgb(var(--shade-rgb) / .62) 26%,
      rgb(var(--shade-rgb) / .30) 46%,
      rgb(var(--shade-rgb) / .08) 62%,
      rgb(var(--shade-rgb) / 0) 78%),
    linear-gradient(180deg,
      rgb(var(--shade-rgb) / .44) 0%,
      rgb(var(--shade-rgb) / .06) 20%,
      rgb(var(--shade-rgb) / .04) 52%,
      rgba(5, 29, 20, .46) 86%,
      rgb(var(--shade-rgb) / .78) 100%);
}

.hero__content { position: relative; max-width: 720px; }
/* A soft wide shadow darkens the few pixels around each glyph instead of the
   whole photograph. It is what lets the scrim above be as light as it is. */
.hero .h-hero { color: #fff; margin-bottom: clamp(.7rem, 1.8vh, 1.2rem);
  text-shadow: 0 1px 2px rgb(var(--shade-rgb) / .6), 0 2px 28px rgb(var(--shade-rgb) / .62); }
.hero__lead {
  color: #fff;
  font-size: clamp(.95rem, min(1.2vw, 1.9vh), 1.08rem);
  /* Small type over a lit face is the hardest thing in the frame. A tight
     halo plus a wide soft pass carries it without touching the photograph. */
  text-shadow:
    0 0 2px rgb(var(--shade-rgb) / .92),
    0 1px 3px rgb(var(--shade-rgb) / .85),
    0 2px 18px rgb(var(--shade-rgb) / .8);
  max-width: 50ch;
  margin-bottom: clamp(1.1rem, 3vh, 2rem);
}

/* Three panels, one per company. They share a grid cell so the hero is as
   tall as the tallest of them and nothing jumps when the slide changes. */
.hero__panels { display: grid; }
.hero__panel {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;          /* also takes the hidden panels out of tab order */
  transform: translateY(14px);
  /* Out first, in second. Crossfading two headlines over each other ghosts
     them together and neither is readable for a quarter of a second. */
  transition: none;
}
.hero--ready .hero__panel {
  transition: opacity .26s var(--ease), transform .45s var(--ease), visibility .45s;
}
/* The incoming panel starts before the outgoing one has finished, so the two
   never ghost together and the slot is never empty: the lowest combined
   opacity through a switch is about .38, at t = .16s. */
.hero__panel.is-active {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: none;
}
.hero--ready .hero__panel.is-active {
  transition: opacity .34s var(--ease) .16s, transform .5s var(--ease) .16s,
              visibility .5s .16s;
}

/* The company's own mark, so the panel says who is speaking before the
   headline does. */
.hero__id {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: .7rem 1.1rem;
  margin-bottom: clamp(.8rem, 2.2vh, 1.5rem);
}
.hero__lockup {
  filter: drop-shadow(0 2px 14px rgb(var(--shade-rgb) / .6));
  height: clamp(30px, 4.6vh, 42px);
  width: auto;
  display: block;
}

.hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.1rem; }
.hero__call { display: flex; align-items: center; gap: .8rem; margin: 0; }
.hero__call dt { font-size: .72rem; letter-spacing: .14em; text-transform: uppercase; color: rgba(255,255,255,.72); text-shadow: 0 1px 10px rgb(var(--shade-rgb) / .7); }
.hero__call dd { margin: .15rem 0 0; color: #fff; font-weight: 800; font-size: 1.02rem; letter-spacing: -.01em; text-shadow: 0 1px 12px rgb(var(--shade-rgb) / .7); }

/* The picker names the companies rather than numbering pictures, because
   saying who the three are is what the hero is now for. */
.hero__tabs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  margin-top: clamp(1.2rem, 3.4vh, 2.6rem);
  max-width: 720px;
  background: rgba(255, 255, 255, .12);
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: var(--corner-lg);
  overflow: hidden;
}
.hero__tab {
  position: relative;
  text-shadow: 0 1px 10px rgb(var(--shade-rgb) / .65);
  display: flex; align-items: flex-start; gap: .6rem;
  padding: clamp(.75rem, 1.9vh, 1.15rem) clamp(.7rem, 1.4vw, 1.05rem);
  background: rgba(9, 53, 34, .62);
  backdrop-filter: blur(8px);
  border: 0;
  text-align: left;
  cursor: pointer;
  color: #fff;
  transition: background-color .35s var(--ease);
}
.hero__tab:hover { background: rgba(12, 105, 52, .62); }
.hero__tab.is-active { background: var(--g-mid); }

/* The rail doubles as the progress bar: it says which company is showing and
   how long is left before it moves on. */
.hero__tab-rail {
  position: absolute; inset: 0 0 auto 0;
  height: 3px;
  background: rgba(255, 255, 255, .14);
  overflow: hidden;
}
.hero__tab-rail i {
  display: block; height: 100%; width: 100%;
  background: var(--lime);
  transform: scaleX(0);
  transform-origin: left;
}
.hero__tab.is-active .hero__tab-rail i { animation: hero-progress var(--hero-dwell, 7s) linear forwards; }
.hero--paused .hero__tab.is-active .hero__tab-rail i { animation-play-state: paused; }
@keyframes hero-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes hero-progress-y { from { transform: scaleY(0); } to { transform: scaleY(1); } }

.hero__tab-n { font-size: .7rem; font-weight: 800; color: rgba(255,255,255,.66); line-height: 1.5; }
.hero__tab.is-active .hero__tab-n { color: var(--accent-3); }
.hero__tab-text strong {
  display: block;
  font-size: clamp(.82rem, 1.05vw, .95rem);
  line-height: 1.2;
  letter-spacing: -.01em;
}
.hero__tab-text small {
  display: block; margin-top: .15rem;
  font-size: .68rem; letter-spacing: .06em; text-transform: uppercase;
  color: rgba(255,255,255,.7);
}
.hero__tab.is-active .hero__tab-text small { color: rgba(255,255,255,.86); }
.hero__tab:focus-visible { outline: 2px solid var(--lime); outline-offset: -3px; }

/* A quieter second action, so the pair reads as primary and alternative. */
.pbtn--ghost {
  background: rgba(255, 255, 255, .1);
  border: 1px solid rgba(255, 255, 255, .26);
  color: #fff;
  backdrop-filter: blur(8px);
}
/* The chevron carries no plate of its own. A frosted square inside a
   frosted pill is two glass surfaces arguing, and the square corners fight
   the capsule they sit in. */
.pbtn--ghost .pbtn__chev { color: #fff; }
.pbtn--ghost:hover { background: rgba(255, 255, 255, .18); border-color: rgba(255, 255, 255, .4); }

/* Interior page hero */
.phero {
  position: relative;
  background: var(--ink);
  color: #fff;
  overflow: hidden;
  isolation: isolate;
  padding-top: calc(var(--header-h) + clamp(3rem, 7vw, 5.5rem));
  padding-bottom: clamp(3rem, 6vw, 5rem);
}
.phero__media { position: absolute; inset: 0; width: 100%; z-index: -2; }
.phero__media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 28%; }

/* Two pictures, crossfading. Stacked rather than sequenced, so the one
   underneath is already painted when the one on top fades: a hero that goes
   briefly empty between two photographs reads as a fault.

   The drift is applied to the slide, not to the image, because the framing
   engine sets object-position on the image and a transform there would move
   the subject out from under its own crop. */
.phero__slide {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity 1.5s var(--ease);
}
.phero__slide.is-active { opacity: 1; }
.phero__slide.is-active img { animation: phero-drift 16s linear both; }
@keyframes phero-drift {
  from { transform: scale(1.0); }
  to   { transform: scale(1.045); }
}
@media (prefers-reduced-motion: reduce) {
  /* No fade and no drift: the first picture stays, which is what the hero
     looked like before and is a complete hero on its own. */
  .phero__slide { transition: none; }
  .phero__slide.is-active img { animation: none; }
  .phero__media[data-phero] .phero__slide:not(.is-active) { display: none; }
}
.phero__scrim {
  position: absolute; inset: 0; z-index: -1;
  /* Same shape as the main hero: the left carries the copy and has cleared by
     three quarters, the bottom only enough to hand off to the page. */
  background:
    linear-gradient(100deg,
      rgb(var(--shade-rgb) / .84) 0%,
      rgb(var(--shade-rgb) / .64) 28%,
      rgb(var(--shade-rgb) / .32) 48%,
      rgb(var(--shade-rgb) / .10) 64%,
      rgb(var(--shade-rgb) / 0) 80%),
    linear-gradient(180deg,
      rgb(var(--shade-rgb) / .46) 0%,
      rgb(var(--shade-rgb) / .08) 22%,
      rgb(var(--shade-rgb) / .06) 54%,
      rgba(5, 29, 20, .48) 86%,
      rgb(var(--shade-rgb) / .78) 100%);
}
/* ---------- The interior hero's picture switch ----------
   Bottom corner, on the side the copy does not use. Two segments rather
   than two dots: a dot says "there is more", a numbered segment says how
   much more and which one you are on, in the same space.

   Positioned against the container's own gutter so it lines up with the
   copy's right edge on a wide screen and with the page margin on a phone. */
.pswitch {
  position: absolute;
  right: max(var(--gutter), calc(50% - var(--container) / 2 + var(--gutter)));
  bottom: clamp(1.1rem, 2.4vw, 1.9rem);
  z-index: 3;
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  border-radius: var(--r-pill);
  background: rgb(var(--shade-rgb) / .42);
  border: 1px solid rgba(255, 255, 255, .18);
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
}
.pswitch__seg {
  display: grid;
  place-items: center;
  min-width: 34px;
  height: 26px;
  padding: 0 .4rem;
  border: 0;
  border-radius: var(--r-pill);
  background: none;
  color: rgba(255, 255, 255, .62);
  font: inherit;
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .04em;
  cursor: pointer;
  transition: background-color .3s var(--ease), color .3s var(--ease);
}
.pswitch__seg:hover { color: #fff; background: rgba(255, 255, 255, .12); }
.pswitch__seg.is-active {
  background: var(--accent);
  color: var(--ink);
}
.pswitch__seg:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}
@media (max-width: 560px) {
  /* Smaller, and the hero makes room under the copy for it rather than
     letting it land on the last line of the lead. */
  .pswitch { bottom: .9rem; padding: 2px; }
  .pswitch__seg { min-width: 28px; height: 22px; font-size: .66rem; }
  .phero:has(.pswitch) .container { padding-bottom: 2.4rem; }
}

/* The type carries its own legibility, as it does in the main hero. */
.phero .h-1, .phero h1 {
  text-shadow: 0 1px 2px rgb(var(--shade-rgb) / .6), 0 2px 28px rgb(var(--shade-rgb) / .62);
}
.phero .lead, .phero__lead {
  text-shadow: 0 0 2px rgb(var(--shade-rgb) / .9), 0 1px 3px rgb(var(--shade-rgb) / .82),
               0 2px 18px rgb(var(--shade-rgb) / .78);
}
.phero .overline { text-shadow: 0 1px 10px rgb(var(--shade-rgb) / .7); }
.phero--plain {
  background-color: var(--g-900);
  background-image:
    var(--pat-grid-lt),
    radial-gradient(60% 90% at 86% 24%, rgb(var(--accent-rgb) / .16) 0%, rgb(var(--accent-rgb) / 0) 64%),
    var(--ramp-soft);
  background-size: var(--cell) var(--cell), cover, cover;
}
.phero--plain::after {
  content: ""; position: absolute; right: -3%; bottom: -46%;
  width: min(480px, 44vw); aspect-ratio: 1; z-index: -1;
  background: url("../img/brand/mark-white.png") no-repeat center / contain;
  opacity: .07;
}
.phero h1, .phero h2 { color: #fff; }
.phero h1 { max-width: 17ch; margin-bottom: .9rem; }
.phero p { color: rgba(255,255,255,.75); max-width: 54ch; }

.crumb { display: flex; align-items: center; gap: .5rem; margin-bottom: 1.25rem; font-size: .84rem; color: rgba(255,255,255,.6); }
.crumb a:hover { color: var(--lime); }
.crumb .sep { font-style: normal; opacity: .45; }

/* ---------- 9. Notched card (the signature component) ---------- */
.ncard {
  --c: var(--white);
  --fg: var(--ink);
  display: flex;
  flex-direction: column;
  transition: transform .4s var(--ease);
}
.ncard:hover { transform: translateY(-6px); }

.ncard__main {
  position: relative;
  flex: 1;
  background: var(--c);
  border-radius: 0 0 0 var(--r-card);
  padding: clamp(1.8rem, 2.6vw, 2.4rem);
  padding-bottom: clamp(1.9rem, 2.8vw, 2.5rem);
  color: var(--fg);
}
/* A rule that draws itself along the flat top edge on hover. */
.ncard__main::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--accent-rule, var(--lime));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .5s var(--ease);
  z-index: 1;
}
.ncard:hover .ncard__main::before { transform: scaleX(1); }
.ncard--lime { --accent-rule: var(--g-dark); }
.ncard--green { --accent-rule: var(--lime); }

.ncard__icon { display: block; margin-bottom: clamp(2.5rem, 5vw, 4rem); color: var(--fg); }
.ncard__icon i { display: block; }
.ncard__main h3 { color: var(--fg); margin-bottom: .6rem; max-width: 15ch; }
.ncard__main p { color: var(--fg); opacity: .74; font-size: .95rem; margin: 0; }
.ncard .card__list li { color: var(--fg); opacity: .78; }
.ncard .card__list { --bullet: currentColor; }

.ncard__foot { display: flex; align-items: stretch; gap: var(--gap-tab); min-height: calc(46px + var(--tab-drop)); }

.ncard__cta {
  display: inline-flex; align-items: center; gap: .5rem;
  margin-top: var(--tab-drop);
  padding: 0 1.25rem;
  background: var(--c);
  border-radius: var(--r-pill);
  color: var(--fg);
  font-size: .86rem; font-weight: 700;
  white-space: nowrap;
  transition: gap .3s var(--ease);
}
.ncard:hover .ncard__cta { gap: .8rem; }
.ncard__cta i { flex: none; }

/* The filler completes the card silhouette to the right of the tab */
.ncard__fill {
  position: relative;
  flex: 1;
  background: var(--c);
  border-radius: 0 0 var(--r-card) var(--r-md);
}
/* …and this is the concave joint where the bite meets the card body */
.ncard__fill::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--notch)); top: 0;
  width: var(--notch); height: var(--notch);
  background: var(--c);
  -webkit-mask: radial-gradient(circle var(--notch) at 0 100%, transparent 98%, #000 100%);
          mask: radial-gradient(circle var(--notch) at 0 100%, transparent 98%, #000 100%);
}

/* Colour variants */
.ncard--lime { --c: var(--lime); --fg: var(--ink); }
.ncard--dark { --c: var(--g-850); --fg: #fff; }
.ncard--green { --c: var(--green); --fg: #fff; }
.ncard--white .ncard__main { box-shadow: var(--sh-1); }

/* The coloured cards carry a fine grid and nothing else.
   There used to be a large tinted circle in the bottom corner here. A circle
   bigger than its container has a hard edge somewhere, and this one's ran
   diagonally through the body copy and stopped dead at the seam between the
   card and its foot: two straight tonal steps that read as a rendering fault
   rather than as depth. Texture that reaches every corner evenly cannot do
   that, so the grid stays and the circle goes. */
.ncard--lime .ncard__main, .ncard--dark .ncard__main, .ncard--green .ncard__main { position: relative; overflow: hidden; }

/* ---------- 10. Plain cards ---------- */
.card {
  position: relative;
  display: flex; flex-direction: column;
  padding: clamp(1.5rem, 2.3vw, 2rem);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--corner-xl);
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), background-color .4s var(--ease), border-color .4s var(--ease);
}
.card h3 { transition: color .4s var(--ease); }
.card p { color: var(--body-2); font-size: .95rem; transition: color .4s var(--ease); }
.card__icon {
  width: 52px; height: 52px;
  display: grid; place-items: center;
  margin-bottom: 1.3rem;
  background: var(--lime-4);
  border-radius: var(--corner-md);
  color: var(--green);
  transition: background-color .4s var(--ease), color .4s var(--ease), transform .4s var(--ease);
}
.card__icon i { display: block; }

.card--hoverdark { position: relative; overflow: hidden; }
.card--hoverdark::before {
  content: "";
  position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--lime);
  transform: scaleX(0); transform-origin: left;
  transition: transform .5s var(--ease);
  z-index: 1;
}
.card--hoverdark:hover::before { transform: scaleX(1); }
.card--hoverdark:hover { background: var(--ink); border-color: var(--ink); transform: translateY(-6px); box-shadow: var(--sh-3); }
.card--hoverdark:hover h3 { color: #fff; }
.card--hoverdark:hover p { color: rgba(255,255,255,.66); }
.card--hoverdark:hover .card__icon { background: var(--lime); color: var(--ink); transform: rotate(-6deg); }
.card--hoverdark:hover .card__list li { color: rgba(255,255,255,.66); }
.card--hoverdark:hover .card__list .li-ico { color: var(--lime); }
.card--hoverdark:hover .plink { background: var(--lime); border-color: var(--lime); color: var(--ink); }

.card__list { margin-top: 1.1rem; display: grid; gap: .5rem; }
.card__list li {
  font-size: .92rem; line-height: 1.5; color: var(--body);
  transition: color .4s var(--ease);
}
.card .plink { margin-top: auto; align-self: flex-start; padding-top: .6rem; }
.card .plink { margin-top: 1.5rem; }

.card--flat { border: 0; background: var(--cream); }
/* A surface on a dark ground lifts by being a lighter green, not by having
   white washed over it. White washes go grey and kill the hue. */
.card--dark { background: var(--g-800); border-color: rgba(255, 255, 255, .09); }
.card--dark h3 { color: #fff; }
.card--dark p, .card--dark .card__list li { color: var(--on-dark-soft); }
.card--dark .card__icon { background: rgba(255,255,255,.08); color: var(--lime); }
.card--dark .card__list { --bullet: var(--lime); }

/* Award laurels. The source art is only 120x118, so it is given a fixed box and
   object-fit:contain: it can never be squashed by a parent, whatever the layout. */
.award-mark {
  /* align-self, or the column flex parent stretches the box to full card width
     and object-fit quietly letterboxes the artwork inside it. */
  align-self: flex-start;
  width: auto;
  height: clamp(64px, 7vw, 82px);
  aspect-ratio: 120 / 118;
  object-fit: contain;
  margin-bottom: 1.1rem;
  opacity: .95;
  border-radius: 0;
}

/* The two bands the seal straddles give it room, or it lands on the copy
   above and the heading below instead of on the gap between them. */
.section:has(+ .seam) { padding-bottom: calc(var(--section-y) + 3.25rem); }
.seam + .section { padding-top: calc(var(--section-y) + 3.25rem); }

/* The build credit. Its own weight on the name, so it reads as a signature
   rather than as another legal link in the row. */
.footer__by strong { font-weight: 800; color: #fff; transition: color .25s var(--ease); }
.footer__by:hover strong { color: var(--lime); }

/* ---------- 10b. The seal on a seam ----------
   Three laurels on a plate centred on the join between two bands: half of
   it over the light section above, half over the dark one below. The
   element is given a height and then half of that height is taken back off
   each side as negative margin, so whatever it measures it lands centred on
   the line rather than near it.

   White, because the plate has to work against both grounds at once, and
   lifted on z-index because the band below is painted after it. */
.seam {
  --seam-h: clamp(78px, 8.4vw, 98px);
  position: relative;
  z-index: 5;
  display: flex;
  justify-content: center;
  height: var(--seam-h);
  margin-block: calc(var(--seam-h) / -2);
  padding-inline: var(--gutter);
}
.seam__plate {
  display: inline-flex;
  align-items: center;
  gap: clamp(.9rem, 1.8vw, 1.6rem);
  height: 100%;
  padding: 0 clamp(1.1rem, 2.2vw, 1.9rem);
  background: var(--white);
  border-radius: var(--r-pill);
  box-shadow: 0 14px 40px rgba(6, 41, 27, .18), 0 2px 6px rgba(6, 41, 27, .08);
  transition: transform .4s var(--ease), box-shadow .4s var(--ease);
}
.seam:hover .seam__plate {
  transform: translateY(-3px);
  box-shadow: 0 20px 52px rgba(6, 41, 27, .24), 0 2px 6px rgba(6, 41, 27, .08);
}
.seam__marks { display: inline-flex; align-items: center; gap: clamp(.55rem, 1.3vw, 1.1rem); }
.seam__marks img {
  height: clamp(44px, 4.6vw, 56px);
  width: auto;
  aspect-ratio: 120 / 118;
  object-fit: contain;
}
.seam__note {
  display: grid;
  gap: .1rem;
  padding-left: clamp(.7rem, 1.4vw, 1.2rem);
  border-left: 1px solid var(--line);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--body-2);
  line-height: 1.25;
}
.seam__note strong {
  font-size: .9rem;
  font-weight: 800;
  letter-spacing: -.01em;
  text-transform: none;
  color: var(--ink);
}
.seam__go { display: inline-flex; color: var(--green); transition: transform .3s var(--ease); }
.seam:hover .seam__go { transform: translateX(4px); }

@media (max-width: 720px) {
  /* The caption goes first: the laurels carry the words already, and three
     of them plus a sentence will not sit on one line on a phone. */
  .seam { --seam-h: 68px; }
  .seam__note, .seam__go { display: none; }
  .seam__plate { padding: 0 1rem; gap: .6rem; }
  .seam__marks img { height: 40px; }
}

/* ---------- A link that covers its card ----------
   The card keeps its own markup and its own cross links; one anchor inside
   it grows a transparent layer over the whole thing, so the click target is
   the card while the accessible name stays the heading and the tab order
   gains nothing.

   Everything else inside has to be lifted above that layer, or the card
   would swallow its own cross links and its own picture. */
.stretch { position: relative; }
.stretch::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}
.ncard, .dcard, .unit, .signcard { position: relative; }

/* The heading reads as a link only on hover: a capability card whose title
   is permanently link coloured competes with the real cross links in its
   own body. */
.dcard h3 .stretch, .unit h3 .stretch, .signcard strong .stretch {
  color: inherit;
  text-decoration: none;
  transition: color .3s var(--ease);
}
.dcard:hover h3 .stretch, .signcard:hover strong .stretch { color: var(--green); }
.unit:hover h3 .stretch { color: var(--lime); }

/* Anything else interactive in the card sits above the sheet. */
.dcard a:not(.stretch), .unit a:not(.stretch),
.ncard a:not(.stretch), .signcard a:not(.stretch) { position: relative; z-index: 2; }

/* ---------- 11. Bento (about) ---------- */
.bento { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(.75rem, 1.2vw, 1rem); }
.bento img { border-radius: var(--corner-lg); width: 100%; height: 100%; object-fit: cover; }
.bento__hero { grid-column: 1 / -1; aspect-ratio: 16 / 9; }
.bento__tile { aspect-ratio: 1 / 1; }
.bento__stat {
  display: grid; place-content: center; gap: .5rem;
  aspect-ratio: 1 / 1;
  padding: 1.25rem;
  background-color: var(--lime);
  border-radius: var(--corner-lg);
  text-align: center;
  color: var(--ink);
}
.bento__stat svg { margin-inline: auto; }
.bento__stat strong { display: block; font-size: clamp(1.9rem, 3.4vw, 2.6rem); font-weight: 800; line-height: 1; letter-spacing: -.035em; }
.bento__stat span { font-size: .88rem; font-weight: 600; line-height: 1.35; opacity: .78; }

/* Author / credential row */
.byline { display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap; margin-top: 2rem; }
.byline__person { display: flex; align-items: center; gap: .75rem; }
.byline__avatar {
  width: 46px; height: 46px; flex: none;
  display: grid; place-items: center;
  background: var(--lime-4);
  border: 2px solid var(--white);
  border-radius: 50%;
  box-shadow: var(--sh-1);
  color: var(--green);
}
.byline__person strong { display: block; color: var(--ink); font-size: .96rem; line-height: 1.3; }
.byline__person span { font-size: .84rem; color: var(--body-2); }

/* Mini stat cards */
.ministat { background: var(--cream); border-radius: var(--corner-lg); padding: clamp(1.25rem, 2vw, 1.75rem); }
.section--cream .ministat { background: var(--white); }
.ministat__stars { display: flex; gap: 2px; color: var(--lime-2); margin-bottom: .9rem; }
.ministat__num { font-size: clamp(2rem, 3.4vw, 2.7rem); font-weight: 800; color: var(--ink); line-height: 1; letter-spacing: -.035em; }
.ministat__num small { font-size: .42em; font-weight: 700; color: var(--body-2); letter-spacing: 0; }
.ministat__label { margin-top: 1.4rem; font-weight: 700; color: var(--ink); font-size: .98rem; }
.ministat h3 { font-size: 1.08rem; margin-bottom: 1rem; }

.tags { display: flex; flex-wrap: wrap; gap: .4rem; }
.tags span {
  padding: .32rem .7rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--white);
  font-size: .68rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-2);
}
.section--cream .tags span { background: var(--cream); }

/* ---------- 12. Steps ---------- */
.steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(1rem, 1.6vw, 1.4rem); }
.step {
  padding: clamp(1.4rem, 2.2vw, 1.9rem);
  background-color: var(--g-800);
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: var(--corner-lg);
  transition: background-color .4s var(--ease), transform .4s var(--ease);
}
.step:hover { background-color: var(--g-750); transform: translateY(-5px); }
.step__n {
  display: inline-grid; place-items: center;
  width: 46px; height: 46px;
  margin-bottom: 1.4rem;
  background: var(--lime);
  border-radius: 50%;
  color: var(--ink); font-weight: 800; font-size: .95rem;
}
.step h3 { font-size: 1.15rem; margin-bottom: .45rem; }
.step p { color: var(--on-dark-soft); font-size: .93rem; margin: 0; }

/* ---------- 13. Sector rows ---------- */
.rows { border-top: 1px solid var(--line); }
.section--dark .rows { border-color: var(--line-2); }
.row {
  display: grid;
  grid-template-columns: 64px 1fr auto;
  align-items: center;
  gap: clamp(1rem, 2.5vw, 2.5rem);
  padding: clamp(1.3rem, 2.2vw, 1.85rem) 0;
  border-bottom: 1px solid var(--line);
  transition: padding-inline .4s var(--ease), background-color .4s var(--ease);
}
.section--dark .row { border-color: var(--line-2); }
.row:hover { background: var(--cream); padding-inline: clamp(.5rem, 1.5vw, 1.4rem); }
.section--dark .row:hover { background: var(--g-800); }
.row__n { font-size: .8rem; font-weight: 700; letter-spacing: .06em; color: var(--g-mid); }
.section--dark .row__n { color: var(--g-light); }
.row__body h3 { font-size: clamp(1.2rem, 2vw, 1.6rem); margin-bottom: .2rem; }
.row__body p { margin: 0; font-size: .95rem; color: var(--body-2); max-width: 66ch; }
.section--dark .row__body p { color: var(--on-dark-soft); }
.row__go {
  width: 44px; height: 44px; flex: none;
  display: grid; place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--green);
  transition: background-color .35s var(--ease), color .35s var(--ease), border-color .35s var(--ease), transform .35s var(--ease);
}
.section--dark .row__go { border-color: var(--line-2); color: var(--lime); }
.row:hover .row__go { background: var(--lime); border-color: var(--lime); color: var(--ink); transform: translateX(4px); }

/* ---------- 14. Clients marquee ---------- */
.clients { padding-block: clamp(2rem, 3.5vw, 3rem); }
.clients__label { text-align: center; font-size: .8rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--body-2); margin-bottom: 1.6rem; }
.marquee { overflow: hidden; -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent); mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent); }
.marquee__track { display: flex; width: max-content; animation: marquee 34s linear infinite; }
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__group { display: flex; align-items: center; gap: clamp(2.5rem, 6vw, 5rem); padding-right: clamp(2.5rem, 6vw, 5rem); }
/* Full strength. A client logo at 55 percent grey reads as a placeholder,
   and these are real clients who agreed to be named. */
.marquee img { height: clamp(30px, 3.8vw, 42px); width: auto; object-fit: contain; filter: grayscale(1) contrast(1.05); opacity: .9; transition: opacity .3s var(--ease), filter .3s var(--ease); }
.marquee img:hover { filter: none; opacity: 1; }
@keyframes marquee { to { transform: translateX(-50%); } }

/* ---------- Text that arrives a word at a time ----------
   The word spans are written by the script, and the resting state is set by
   the script too: if it never runs, or runs late, the paragraph is just a
   paragraph. Nothing here hides anything on its own.

   Transparent rather than hidden, so the sentence is read whole by a screen
   reader, stays selectable, and stays findable with the browser's own find,
   the entire time it is arriving. */
.js [data-stream].is-streaming .wd {
  opacity: 0;
  filter: blur(4px);
  transform: translateY(.14em);
}
.js [data-stream].is-streaming.is-on .wd {
  opacity: 1;
  filter: blur(0);
  transform: none;
}
.js [data-stream] .wd {
  display: inline-block;
  opacity: 1;
  filter: blur(0);
  transform: none;
  transition: opacity .34s var(--ease), filter .34s var(--ease),
              transform .34s var(--ease);
  transition-delay: var(--d, 0ms);
}
/* The cursor, moved along in front of whichever word is arriving. */
.js .caret {
  display: inline-block;
  width: .075em;
  height: .95em;
  margin-right: .1em;
  vertical-align: -.1em;
  background: currentColor;
  opacity: .5;
  animation: caret .9s steps(1) infinite;
}
@keyframes caret { 50% { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  /* Nothing is wrapped in this case, but belt and braces. */
  .js [data-stream].is-streaming .wd { opacity: 1; filter: none; transform: none; }
  .js .caret { display: none; }
}

/* ---------- Cross links in running text ----------
   A linked phrase takes the brand colour outright. The previous treatment
   inherited the body colour and marked itself with a grey dotted rule, which
   is the typographic equivalent of a whisper: on a page this green, a link
   should read as the one warm thing in the paragraph.

   Each ground gives a link three things - a resting colour, a hover colour
   and a wash to light up behind it - so the same rule can serve the cream
   pages, the dark bands, the accent cards and the blue theme.

   Hover does not mean "brighter" everywhere. On the dark bands the link
   brightens, because there is headroom above the accent. On the light ones
   brightening is the wrong direction: the resting colour is already deep,
   and a lighter green against cream would hand back the contrast the link
   needs. There the ink firms up and a pale mint highlighter comes on behind
   it, so the link gains contrast on hover rather than losing it. Measured:
   6.3:1 at rest on cream, 8.2:1 hovered.

   The underline stays at rest, thin and tinted rather than dotted and grey.
   It has to: these links sit 1.10:1 against the surrounding body colour, far
   under the 3:1 that would let colour identify them on its own, so colour
   alone would leave them invisible to anyone who cannot separate the hues.

   Written as a.clink rather than .clink: a container that colours its own
   paragraphs, as the office block does, matches at (0,1,1) and would
   otherwise take the link's colour straight back off it. */
a.clink {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-decoration-color: color-mix(in srgb, var(--link) 42%, transparent);
  text-underline-offset: 3px;
  text-decoration-skip-ink: auto;
  border-radius: 4px;
  padding: 0 .16em;
  margin: 0 -.16em;
  font-weight: 650;
  transition: color .2s var(--ease), text-decoration-color .2s var(--ease),
              background-color .2s var(--ease);
}
a.clink:hover,
a.clink:focus-visible {
  color: var(--link-hi);
  text-decoration-color: currentColor;
  text-decoration-thickness: 2px;
  background: var(--link-wash);
}

/* The dark bands: the other end of the same ramp. Set on the ground rather
   than on the link, so a link anywhere inside one is right without asking. */
.section--dark,
.section--photo,
.phero,
.hero,
.card--dark,
.ncard--dark,
.unit {
  --link:      var(--accent);        /* 8.9:1 on the lightest dark ground */
  --link-hi:   var(--accent-3);      /* 7.1:1 even over its own wash */
  --link-wash: rgb(var(--accent-rgb) / .15);
}

/* A card whose ground IS the accent. The logo green reaches only 3.86:1 on
   it, so the link goes the other way: deeper than the copy, not lighter,
   and the wash is white rather than mint. */
.ncard--lime,
.ncard--green {
  --link:      var(--g-950);         /* 10.7:1 on the accent */
  --link-hi:   var(--g-950);
  --link-wash: rgb(255 255 255 / .22);
}
.ncard--lime a.clink,
.ncard--green a.clink {
  text-decoration-color: color-mix(in srgb, var(--g-950) 55%, transparent);
}

/* Over a photograph the type already carries a shadow; the link keeps it, or
   the one coloured phrase in the sentence is the one that stops being legible. */
.hero a.clink, .phero a.clink, .section--photo a.clink { text-shadow: inherit; }

@media (prefers-reduced-motion: reduce) { a.clink { transition: none; } }

/* ---------- Photographic section grounds ----------
   Every other band carries a picture. Same treatment as the heroes: full
   bleed, two gentle ramps, and the type carries its own shadow rather than
   the photograph being darkened until the words win. */
.section--photo {
  position: relative;
  isolation: isolate;
  color: #fff;
  background-color: var(--g-950);
}
.secbg {
  position: absolute; inset: 0; z-index: -2;
  overflow: hidden;
}
.secbg img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: var(--pos, 50% 45%);
  filter: saturate(.9) contrast(1.04);
}
.secbg::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(100deg,
      rgb(var(--shade-rgb) / .90) 0%,
      rgb(var(--shade-rgb) / .78) 26%,
      rgb(var(--shade-rgb) / .60) 46%,
      rgb(var(--shade-rgb) / .46) 64%,
      rgb(var(--shade-rgb) / .40) 100%),
    linear-gradient(180deg,
      rgb(var(--shade-rgb) / .46) 0%,
      rgb(var(--shade-rgb) / .14) 26%,
      rgb(var(--shade-rgb) / .16) 64%,
      rgb(var(--shade-rgb) / .62) 100%);
}
.section--photo .h-2,
.section--photo .h-3,
.section--photo .shead__title {
  text-shadow: 0 1px 2px rgb(var(--shade-rgb) / .66), 0 2px 26px rgb(var(--shade-rgb) / .6);
}
.section--photo .lead,
.section--photo .shead__aside,
.section--photo p {
  text-shadow: 0 0 2px rgb(var(--shade-rgb) / .86), 0 1px 3px rgb(var(--shade-rgb) / .8),
               0 2px 16px rgb(var(--shade-rgb) / .74);
}
/* A phone sees the narrow middle of a wide frame, so the ramp runs down the
   picture instead of across it. */
@media (max-width: 860px) {
  .secbg::after {
    background: linear-gradient(180deg,
      rgb(var(--shade-rgb) / .72) 0%,
      rgb(var(--shade-rgb) / .56) 30%,
      rgb(var(--shade-rgb) / .62) 64%,
      rgb(var(--shade-rgb) / .86) 100%);
  }
}

/* ---------- Ambient theme bleed ----------
   The card is tinted by its own photograph. A blurred, saturation boosted
   copy sits behind the body and the real picture dissolves into it, so the
   colour appears to bleed down out of the image. Nothing is configured per
   card: the tint is whatever that photograph happens to be. */
.dcard--photo { position: relative; isolation: isolate; }

.dcard__bleed {
  position: absolute;
  inset: 0;
  z-index: -1;                 /* above the card's own ground, below its content */
  width: 100%; height: 100%;
  object-fit: cover;
  /* Blur pulls content inward, so the copy is oversized to keep its edges
     outside the card. */
  transform: scale(1.25);
  opacity: .25;
  filter: blur(38px) saturate(1.6);
  pointer-events: none;
  /* Black is visible, transparent is hidden: the wash exists only over the
     body, which is what makes it read as bleeding down from the picture. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 34%, #000 70%);
          mask-image: linear-gradient(to bottom, transparent 34%, #000 70%);
}

/* The real photograph dissolves at its lower edge instead of ending on a
   line, so there is no seam between picture and body. */
.dcard--photo .dcard__media {
  background: none;
  margin-bottom: 0;
}
.dcard--photo .dcard__media img {
  -webkit-mask-image: linear-gradient(to bottom, #000 76%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 76%, transparent 100%);
}

/* Prose sits on a tinted ground here rather than on white, so it carries
   more weight than the body colour used elsewhere. */
.dcard--photo p,
.dcard--photo .dcard__list li { color: #455349; }

/* The body climbs into the fade, so the type sits over the dissolve rather
   than beneath it. */
.dcard--photo .dcard__ico {
  position: relative;
  margin-top: calc(-1 * clamp(1.1rem, 1.8vw, 1.5rem));
}
.dcard--photo > :not(.dcard__bleed):not(.dcard__media) { position: relative; }

/* Safari on iOS has repeatedly mis-composited a large blur inside a clipped,
   rounded container. The wash is decoration, so it is dropped rather than
   risked where it cannot be relied on. */
@supports (-webkit-touch-callout: none) {
  .dcard__bleed { filter: blur(26px) saturate(1.5); opacity: .22; }
}

/* ---------- Circuitron's page ----------
   Their mark is #002C77 beside a green that is almost Sentinel's, which is
   what makes the company read as part of the group. The page shifts to blue
   without leaving: these tokens are redefined on <main>, so the header, the
   drawer and the footer stay in the group's green and only the page's own
   content changes. */
.theme-circuitron {
  --shade-rgb:  5 18 41;
  --accent-rgb: 95 149 242;

  /* The accent: hue 218 at the lightness the dark ground needs. 6.5:1 on
     that ground, 5.3:1 for ink set on top of it. */
  --accent:   #5F95F2;
  --accent-2: #4C88F0;
  --accent-3: #A8C6F8;
  --accent-4: #E2ECFD;

  /* The dark grounds lean blue by the same amount the greens leaned green. */
  --g-950: #051229;
  --g-900: #07183A;
  --g-850: #0A1F47;
  --g-800: #0C2555;
  --g-750: #123068;
  --g-700: #16397A;
  --g-650: #1B4490;
  --g-mid: #1D4FA8;
  --g-light: #6C98E5;

  --ink:   #0A1F47;
  --ink-2: #0C2555;
  --ink-3: #16397A;
  --body:    #4A5568;
  --body-2:  #5C6880;

  /* Links, the same three steps in this theme's hue: 7.0:1 at rest,
     8.5:1 hovered over the wash. */
  --link:      #1D4FA8;
  --link-hi:   #163F86;
  --link-wash: var(--accent-4);
  --line:  rgba(10, 31, 71, .14);
  --cream: #F2F5FB;

  --green:   var(--g-mid);
  --green-2: #2A62C4;
  --green-3: var(--g-light);

  /* A token whose value is written as var() of another token computes where
     it is DECLARED, not where it is used: --lime: var(--accent) on :root
     resolved to green once, and that green then inherited straight through
     this theme. Every alias has to be redeclared here or the page comes out
     blue in the places that name --accent and green in the places that name
     its alias - which is exactly what the capability lists were doing. */
  --lime:    var(--accent);
  --lime-2:  var(--accent-2);
  --lime-3:  var(--accent-3);
  --lime-4:  var(--accent-4);

  --g-dark:  var(--g-850);
  --ramp:      linear-gradient(118deg, var(--g-950) 0%, var(--g-800) 22%, var(--g-mid) 52%, var(--g-light) 78%, var(--lime) 100%);
  --ramp-soft: linear-gradient(118deg, var(--g-950) 0%, var(--g-800) 26%, var(--g-mid) 60%, var(--g-light) 94%, var(--lime) 124%);
}

/* ---------- 15. Accordion ---------- */
.accordion { display: grid; gap: .75rem; }
.acc__item { background: var(--white); border: 1px solid var(--line); border-radius: var(--corner-lg); overflow: hidden; transition: border-color .3s var(--ease), box-shadow .3s var(--ease); }
.acc__item:has(.acc__btn[aria-expanded="true"]) { border-color: var(--lime-2); box-shadow: var(--sh-2); }
.acc__btn {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 1.25rem;
  padding: 1.25rem 1.5rem;
  background: none; border: 0; cursor: pointer; text-align: left;
  font-size: clamp(1rem, 1.6vw, 1.1rem); font-weight: 700; color: var(--ink);
}
.acc__icon { position: relative; flex: none; width: 34px; height: 34px; border-radius: 50%; background: var(--cream); transition: background-color .3s var(--ease); }
.acc__btn[aria-expanded="true"] .acc__icon { background: var(--lime); }
.acc__icon::before, .acc__icon::after {
  content: ""; position: absolute; left: 50%; top: 50%; background: var(--ink);
  transform: translate(-50%, -50%); transition: transform .35s var(--ease), opacity .3s var(--ease);
}
.acc__icon::before { width: 12px; height: 2px; border-radius: 2px; }
.acc__icon::after { width: 2px; height: 12px; border-radius: 2px; }
.acc__btn[aria-expanded="true"] .acc__icon::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }
.acc__panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .4s var(--ease); }
.acc__panel[data-open="true"] { grid-template-rows: 1fr; }
.acc__panel > div { overflow: hidden; }
.acc__panel p { padding: 0 1.5rem 1.4rem; color: var(--body-2); max-width: 70ch; }

/* ---------- 16. Forms ---------- */
.formcard { background: var(--white); border: 1px solid var(--line); border-radius: var(--corner-xl); padding: clamp(1.5rem, 3vw, 2.5rem); box-shadow: var(--sh-2); }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.field { display: flex; flex-direction: column; gap: .4rem; }
.field--full { grid-column: 1 / -1; }
.field label { font-size: .78rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2); }
.field input, .field select, .field textarea {
  width: 100%; padding: .85rem 1.1rem;
  font: inherit; font-size: .97rem; color: var(--ink);
  background: var(--cream); border: 1px solid transparent; border-radius: var(--corner-md);
  transition: background-color .25s var(--ease), border-color .25s var(--ease), box-shadow .25s var(--ease);
}
.field textarea { resize: vertical; min-height: 130px; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; background: var(--white); border-color: var(--lime-2);
  box-shadow: 0 0 0 4px rgb(var(--accent-rgb) / .3);
}
.field input::placeholder, .field textarea::placeholder { color: #9AA79F; }
.form-note { margin-top: 1rem; font-size: .85rem; color: var(--body-2); }
.form-note a { color: var(--green); font-weight: 700; }
.form-status { margin-top: 1rem; font-size: .93rem; font-weight: 600; color: var(--green); display: none; }
.form-status.is-visible { display: block; }

.contact-grid { display: grid; grid-template-columns: .9fr 1.1fr; gap: clamp(2rem, 4vw, 3.5rem); align-items: start; }
.cinfo { display: grid; grid-template-columns: 48px 1fr; gap: 1rem; padding: 1.2rem 0; border-bottom: 1px solid var(--line); }
.cinfo:first-of-type { border-top: 1px solid var(--line); }
.cinfo__icon { width: 48px; height: 48px; display: grid; place-items: center; background: var(--lime-4); border-radius: var(--corner-md); color: var(--g-mid); }
.cinfo__icon i { display: block; }
.cinfo h3 { font-size: .76rem; letter-spacing: .12em; text-transform: uppercase; color: var(--body-2); margin-bottom: .3rem; }
.cinfo a, .cinfo p { display: block; margin: 0; font-size: 1rem; font-weight: 600; color: var(--ink); }
.cinfo a:hover { color: var(--green); }
/* A named row rather than a bare logo: on the page where somebody is looking
   for a way to reach us, "Sentinel on LinkedIn" says more than a glyph. */
.cinfo__social { display: flex; align-items: center; gap: .55rem; }
.cinfo__social + .cinfo__social { margin-top: .35rem; }
.cinfo__social i { flex: none; color: var(--green); transition: color .25s var(--ease); }
.cinfo__social:hover i { color: var(--green-2); }

.map-wrap { position: relative; background: var(--ink); min-height: clamp(320px, 40vw, 440px); }
.map-wrap__fallback { position: absolute; inset: 0; display: grid; place-content: center; gap: .5rem; text-align: center; padding: var(--gutter); color: var(--on-dark-soft); }
.map-wrap__fallback strong { color: #fff; font-size: 1.1rem; }
.map-wrap__fallback a { color: var(--lime); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
.map-embed { position: relative; border: 0; width: 100%; height: clamp(320px, 40vw, 440px); filter: grayscale(.2) contrast(1.05); }

/* Offices */
.office { background: var(--white); border: 1px solid var(--line); border-radius: var(--corner-lg); padding: clamp(1.4rem, 2.2vw, 1.85rem); }
.office h3 { font-size: 1.1rem; margin-bottom: .7rem; }
.office p, .office a { display: block; margin: 0 0 .35rem; font-size: .96rem; color: var(--body); }
.office a:hover { color: var(--green); }

/* ---------- 17. CTA band ---------- */
/* The closing band carries a picture inside the same rounded card: the shape
   stays, the material changes. */
.cta--photo { background-image: none; }
.cta--photo .secbg { border-radius: inherit; }
.cta--photo .secbg::after {
  background:
    linear-gradient(100deg,
      rgb(var(--shade-rgb) / .90) 0%,
      rgb(var(--shade-rgb) / .74) 32%,
      rgb(var(--shade-rgb) / .44) 56%,
      rgb(var(--shade-rgb) / .22) 74%,
      rgb(var(--shade-rgb) / .12) 88%),
    linear-gradient(180deg, rgb(var(--shade-rgb) / .34) 0%, rgb(var(--shade-rgb) / .58) 100%);
}
.cta--photo .h-2 { text-shadow: 0 1px 2px rgb(var(--shade-rgb) / .7), 0 2px 24px rgb(var(--shade-rgb) / .6); }
.cta--photo .lead, .cta--photo p { text-shadow: 0 0 2px rgb(var(--shade-rgb) / .88), 0 1px 3px rgb(var(--shade-rgb) / .8); }
@media (max-width: 860px) {
  .cta--photo .secbg::after {
    background: linear-gradient(180deg, rgb(var(--shade-rgb) / .74) 0%, rgb(var(--shade-rgb) / .62) 42%, rgb(var(--shade-rgb) / .86) 100%);
  }
}

.cta {
  position: relative;
  background-color: var(--g-850);
  background-image:
    var(--pat-grid-lt),
    radial-gradient(36% 86% at 93% 6%, rgb(var(--accent-rgb) / .13) 0%, rgb(var(--accent-rgb) / 0) 72%),
    linear-gradient(118deg, var(--g-900) 0%, var(--g-850) 58%, var(--g-800) 100%);
  background-size: var(--cell) var(--cell), cover, cover;
  color: var(--on-dark-soft);
  border-radius: var(--corner-xl);
  padding: clamp(2.25rem, 4.5vw, 3.75rem);
  overflow: hidden;
  isolation: isolate;
}
.cta::after {
  content: ""; position: absolute; right: -6%; top: -60%;
  width: min(420px, 45%); aspect-ratio: 1; z-index: -1;
  background: url("../img/brand/mark-white.png") no-repeat center / contain;
  opacity: .06;
}
.cta__inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 2rem; }
.cta h2 { color: #fff; max-width: 17ch; margin-bottom: .55rem; }
.cta p { margin: 0; max-width: 44ch; }
.cta__actions { display: flex; flex-wrap: wrap; gap: .85rem; }

/* ---------- 18. Footer ---------- */
/* Deepest step on the page, so the layout has a floor to sit on. The gradient
   lets it meet whatever section precedes it instead of butting against it. */
.footer {
  /* The sweep leaves the bottom left corner, under the lockup, so the page
     ends on the same idea it opens with. */
  --pat-at: 8% 118%;
  --pat-o: .9;
  background-color: var(--g-950);
  background-image: linear-gradient(180deg, var(--g-900) 0%, var(--g-950) 42%);
  color: var(--on-dark-soft);
  padding-top: clamp(3.5rem, 6vw, 5rem);
}
.footer__top { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1.25fr; gap: clamp(2rem, 4vw, 3.25rem); padding-bottom: clamp(2.5rem, 4.5vw, 3.5rem); }
/* width:auto or the HTML width attribute stretches these. */
.footer__brand img { height: 40px; width: auto; margin-bottom: 1.25rem; }
.footer__brand p { font-size: .95rem; max-width: 34ch; }
.footer__tagline { font-size: 1.7rem; color: var(--lime); margin: .2rem 0 .8rem; max-width: none; white-space: nowrap; }
.footer h4 { font-size: .78rem; font-weight: 700; letter-spacing: .13em; text-transform: uppercase; color: #fff; margin-bottom: 1.1rem; }
.footer__links li + li { margin-top: .5rem; }
.footer__links a { font-size: .95rem; transition: color .25s var(--ease); }
.footer__links li { transition: transform .25s var(--ease); }
.footer__links li:hover { transform: translateX(4px); }
.footer__links li:hover a,
.footer__links li:hover .li-ico { color: var(--lime); }
/* Quieter than the label until the row is hovered: in a column of fifteen,
   fifteen bright glyphs would out-shout the words they belong to. */
.footer__links .li-ico { color: rgba(255, 255, 255, .42); transition: color .25s var(--ease); }
.footer__contact li { display: flex; gap: .7rem; font-size: .95rem; margin-bottom: .8rem; }
.footer__contact i { flex: none; margin-top: 3px; color: var(--lime); }
.footer__contact a { display: block; }
.footer__contact a:hover { color: var(--lime); }
.socials { display: flex; gap: .55rem; margin-top: 1.4rem; }
.socials a {
  width: 40px; height: 40px; display: grid; place-items: center;
  border: 1px solid var(--line-2); border-radius: 50%;
  color: var(--on-dark-soft);
  transition: background-color .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease), transform .3s var(--ease);
}
.socials a i { display: block; }
.socials a:hover { background: var(--lime); border-color: var(--lime); color: var(--g-dark); transform: translateY(-3px); }
.footer__bottom { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; padding-block: 1.5rem; border-top: 1px solid var(--line-2); font-size: .86rem; }
.footer__bottom nav { display: flex; gap: 1.4rem; }
.footer__bottom a:hover { color: var(--lime); }

/* ---------- 19. Prose ---------- */
.prose { max-width: 72ch; }
.prose h2 { font-size: clamp(1.3rem, 2.2vw, 1.7rem); margin-top: 2.4rem; }
.prose h2:first-child { margin-top: 0; }
/* The legal page's lists. No glyph: these are sentences, not line items,
   and a lorry against a sentence about data retention would be comedy.
   They take the brand's own mark rather than the browser's disc, which was
   the last undrawn bullet on the site. */
.prose ul { list-style: none; padding: 0; margin: 0 0 1.1em; display: grid; gap: .45rem; }
.prose ul li { position: relative; padding-left: 1.3rem; margin-bottom: 0; }
.prose ul li::before {
  content: "";
  position: absolute; left: 0; top: .66em;
  width: 8px; height: 2px;
  background: var(--green);
}
.prose li { margin-bottom: .35rem; }
.prose a { color: var(--green); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }

/* ---------- 19b. Surfaces that are links ---------- */
/* Everything that reads as a panel now goes somewhere, so every one of them
   needs to say so on hover and take a focus ring. */
a.step, a.ministat, a.bento__stat, a.bento__hero, a.bento__tile,
a.byline__person, a.card {
  cursor: pointer;
  text-decoration: none;
}
a.step, a.ministat, a.bento__stat {
  transition: transform .35s var(--ease), background-color .35s var(--ease), box-shadow .35s var(--ease);
}
a.ministat:hover { transform: translateY(-4px); box-shadow: var(--sh-2); }
a.bento__stat:hover { transform: translateY(-4px); }
a.byline__person:hover strong { color: var(--g-mid); }

/* Bento photographs became links, so the anchor has to carry the tile geometry. */
.bento__hero, .bento__tile {
  display: block;
  overflow: hidden;
  border-radius: var(--corner-lg);
}
.bento__hero img, .bento__tile img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: 0;
  transition: transform .6s var(--ease);
}
.bento__hero:hover img, .bento__tile:hover img { transform: scale(1.04); }

/* Sector tags are links now */
.tags a {
  padding: .32rem .7rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--white);
  font-size: .68rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-2);
  transition: background-color .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
.tags a:hover { background: var(--g-800); border-color: var(--g-800); color: var(--lime); }
.section--cream .tags a { background: var(--cream); }

/* Client logos became links */
.marquee__group a { display: block; flex: none; }

/* Dark cards that are links get the lime treatment rather than the dark one */
.card--hoverlime { position: relative; overflow: hidden; }
.card--hoverlime::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--lime); transform: scaleX(0); transform-origin: left;
  transition: transform .5s var(--ease); z-index: 1;
}
.card--hoverlime:hover::before { transform: scaleX(1); }
.card--hoverlime:hover { border-color: rgb(var(--accent-rgb) / .45); background: var(--g-750); transform: translateY(-5px); }
.card--dark .plink { background: rgba(255,255,255,.06); border-color: var(--line-2); color: #fff; }
.card--hoverlime:hover .plink { background: var(--lime); border-color: var(--lime); color: var(--g-dark); }

/* Step cards are links now */
.step { display: block; color: inherit; }
.step:hover h3 { color: var(--lime); }

/* A company's own lockup. Sized by height, never stretched, and on dark
   grounds the white variant rather than a filter. */
.clogo { width: auto; max-width: 100%; display: block; object-fit: contain; }

/* ---------- 19c. The group, as a comparison ---------- */
/* Rows line up across three columns so the eye reads across. There are no
   vertical rules: horizontal hairlines carry the alignment on their own, and
   the client asked for the column rules to go. */
.org {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: clamp(1.4rem, 3vw, 3rem);
  border-top: 1px solid var(--line);
}
.org__row { display: contents; }
/* No rule under a cell. The chart is read by alignment - four rows that
   line up across three columns - and the spacing already says where one
   row ends. A hairline under every cell on a ruled ground was two grids
   arguing with each other. */
.org__row > * { padding: .95rem 0; margin: 0; }

/* The colour field is what distinguishes the three. Two of the marks are
   nearly identical and the third belongs to another palette, so the field
   does the work and the mark only confirms it. */
.org__row--head > * { padding: 0 0 1.25rem; border-bottom: 0; }
.org__col { display: block; }
.org__field {
  display: grid; place-items: center;
  height: 96px;
  border-radius: var(--corner-lg);
  transition: transform .35s var(--ease);
}
.org__col:hover .org__field { transform: translateY(-3px); }
.org__field img { height: 42px; width: auto; display: block; }
.org--a .org__field { background: var(--g-850); }
.org--b .org__field { background: var(--g-mid); }
/* --a deepest green, --b the logo green, --c Circuitron's own blue: the
   plate is read as "three companies", so the third one carrying a different
   hue is the point rather than an inconsistency. */
.org--c .org__field { background: var(--g-mid); }

.org__role {
  font-size: .72rem; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--g-mid);
}
.org__line { font-size: 1.02rem; line-height: 1.4; color: var(--ink); max-width: 30ch; }
.org__serves, .org__trades { font-size: .92rem; color: var(--body); }
.org__none { color: var(--line); }
.org__row--label > * {
  padding: 1rem 0 .25rem;
  border-bottom: 0;
  font-size: .68rem; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--body-2);
}
.org__row--label + .org__row > * { padding-top: 0; }
.org__row--go > * { border-bottom: 0; padding-bottom: 0; }
.org__go {
  display: inline-flex; align-items: center; gap: .45rem;
  font-size: .9rem; font-weight: 800;
  color: var(--ink);
  transition: color .25s var(--ease), gap .25s var(--ease);
}
.org__go:hover { color: var(--g-mid); gap: .7rem; }

/* The group itself, as a line in the section header rather than a node
   floating in the middle of the canvas. */
.orgparent {
  display: inline-flex; align-items: center; gap: .55rem;
  margin-top: 1rem;
  padding: .45rem .95rem .45rem .6rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--white);
  color: var(--body);
  font-size: .86rem;
  transition: border-color .25s var(--ease);
}
.orgparent:hover { border-color: var(--g-light); }
.orgparent b { color: var(--ink); font-weight: 800; }
.section--dark .orgparent {
  background: rgba(255,255,255,.07); border-color: rgba(255,255,255,.16);
  color: var(--on-dark-soft);
}
.section--dark .orgparent b { color: #fff; }

/* The phone form: three rows, a colour bar each, nothing else. At 30px the
   two Sentinel lockups are indistinguishable, so there are no logos here. */
.orglist { display: none; }
.orgrow {
  display: flex; align-items: center; gap: 1rem;
  padding: 1.15rem 0 1.15rem 1.1rem;
  border-bottom: 1px solid var(--line);
  border-left: 4px solid var(--g-850);
  color: var(--ink);
}
.orgrow:first-child { border-top: 1px solid var(--line); }
.orgrow.org--a { border-left-color: var(--g-850); }
.orgrow.org--b { border-left-color: var(--g-mid); }
.orgrow.org--c { border-left-color: var(--lime); }
.orgrow__text small {
  display: block;
  font-size: .68rem; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--g-mid);
  margin-bottom: .15rem;
}
.orgrow__text strong { display: block; font-size: 1.05rem; line-height: 1.2; letter-spacing: -.015em; }
.orgrow__go { margin-left: auto; color: var(--g-mid); }
.section--dark .orgrow { color: #fff; border-bottom-color: rgba(255,255,255,.14); }
.section--dark .orgrow:first-child { border-top-color: rgba(255,255,255,.14); }
.section--dark .orgrow__text small { color: var(--lime); }
.section--dark .orgrow__go { color: var(--lime); }

/* ---------- 19d. Capabilities inside a company ---------- */
.dgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: clamp(1rem, 1.6vw, 1.4rem);
}
.dcard {
  display: flex; flex-direction: column;
  padding: clamp(1.3rem, 2.1vw, 1.8rem);
  border: 1px solid var(--line);
  border-radius: var(--corner-xl);
  background: var(--white);
  scroll-margin-top: calc(var(--header-h) + 24px);
  overflow: hidden;
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
/* A capability that has an honest photograph leads with it. The card keeps
   its padding, so the image is pulled back out to the edges. */
.dcard--photo { padding-top: 0; }
.dcard__media {
  display: block;
  margin: 0 calc(-1 * clamp(1.3rem, 2.1vw, 1.8rem)) clamp(1.2rem, 2vw, 1.6rem);
  overflow: hidden;
  background: var(--g-900);
}
.dcard__media img {
  width: 100%; height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  display: block;
  transition: transform .6s var(--ease);
}
.dcard--photo:hover .dcard__media img { transform: scale(1.04); }
.dcard--photo .dcard__ico { margin-top: 0; }

.unit__media {
  display: block;
  margin: calc(-1 * clamp(1.4rem, 2.3vw, 2rem)) calc(-1 * clamp(1.4rem, 2.3vw, 2rem)) clamp(1.3rem, 2.2vw, 1.8rem);
  overflow: hidden;
}
.unit { overflow: hidden; }
.unit__media img {
  width: 100%; height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
  transition: transform .6s var(--ease);
}
.unit:hover .unit__media img { transform: scale(1.03); }
.dcard:hover { transform: translateY(-4px); box-shadow: var(--sh-2); }
.dcard__ico {
  display: grid; place-items: center;
  width: 58px; height: 58px;
  margin-bottom: 1.1rem;
  border-radius: var(--corner-lg);
  background: var(--lime-4);
  color: var(--g-mid);
}
.dcard h3 { margin: 0 0 .5rem; }
.dcard > p { margin: 0 0 1.1rem; font-size: .95rem; }
.dcard__list { display: grid; gap: .5rem; margin: 0 0 1.3rem; padding: 0; list-style: none; }
.dcard__list li {
  font-size: .9rem;
  line-height: 1.5;
  color: var(--body);
}

/* ---------- 19e. A business inside a business ---------- */
.unit {
  padding: clamp(1.4rem, 2.3vw, 2rem);
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: var(--corner-xl);
  background: var(--g-800);
  scroll-margin-top: calc(var(--header-h) + 24px);
}
.unit__head { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.1rem; }
.unit__ico {
  display: grid; place-items: center;
  width: 60px; height: 60px; flex: none;
  border-radius: var(--corner-lg);
  background: rgb(var(--accent-rgb) / .12);
  color: var(--lime);
}
.unit h3 { margin: 0; color: #fff; }
.unit__strap { margin: .1rem 0 0; font-size: 1.45rem; color: var(--lime); }
.unit > p { color: var(--on-dark-soft); margin: 0 0 1.2rem; }
.unit__list { display: grid; gap: .5rem; margin: 0; padding: 0; list-style: none; }
.unit__list li {
  display: flex; align-items: center; gap: .55rem;
  font-size: .9rem; color: #fff;
  padding: .55rem .8rem;
  border-radius: var(--corner-md);
  background: rgba(255, 255, 255, .05);
}
.unit__list li { --bullet: var(--lime); }
.unit__list .li-ico { align-self: center; }

/* ---------- 19f. The rest of the group ---------- */
.sibs { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(.8rem, 1.4vw, 1.2rem); }
.sib {
  display: flex; align-items: center; gap: .9rem;
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: var(--corner-lg);
  background: var(--white);
  color: var(--ink);
  transition: transform .3s var(--ease), box-shadow .3s var(--ease);
}
.sib:hover { transform: translateY(-3px); box-shadow: var(--sh-2); }
.sib { gap: 1.1rem; }
.sib__logo { display: flex; align-items: center; flex: none; min-height: 34px; }
.sib__body small { font-size: .82rem; font-weight: 600; color: var(--body-2); }
.sib__go { margin-left: auto; color: var(--g-mid); transition: transform .3s var(--ease); }
.sib:hover .sib__go { transform: translateX(4px); }
.sib--all { background: var(--g-900); color: #fff; border-color: var(--g-900); }
.sib--all .sib__ico { color: var(--lime); flex: none; }
.sib--all .sib__go { color: var(--lime); }
.sib--all .sib__body strong { display: block; font-size: .98rem; line-height: 1.2; }
.sib--all .sib__body small { color: var(--on-dark-soft); }

/* ---------- 19g. A company in full, on the group page ---------- */
.gdetail { display: grid; grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr); gap: clamp(2rem, 4vw, 3.5rem); align-items: start; }
.gdetail__logo { display: block; margin-bottom: 1.4rem; }
.gdetail__legal {
  font-size: .74rem; font-weight: 800;
  letter-spacing: .09em; text-transform: uppercase;
  color: var(--g-mid);
  margin: 0 0 .9rem;
}
.section--dark .gdetail__legal { color: var(--lime); }
.gdetail__strap { font-size: 1.85rem; margin: .35rem 0 1.4rem; color: var(--g-mid); }
.section--dark .gdetail__strap { color: var(--lime); }
.gdetail__meta { display: grid; gap: .9rem; margin: 0; padding-top: 1.3rem; border-top: 1px solid var(--line); }
.section--dark .gdetail__meta { border-color: rgba(255,255,255,.14); }
.gdetail__meta dt {
  font-size: .72rem; font-weight: 800;
  letter-spacing: .09em; text-transform: uppercase;
  color: var(--body-2);
  margin-bottom: .2rem;
}
.section--dark .gdetail__meta dt { color: var(--on-dark-soft); }
.gdetail__meta dd { margin: 0; font-size: .94rem; font-weight: 600; }
.section--dark .gdetail__meta dd { color: #fff; }

.gdetail__rows { display: grid; gap: .5rem; }
.drow {
  display: grid;
  grid-template-columns: auto auto 1fr auto;
  align-items: center;
  gap: .9rem;
  padding: 1rem 1.15rem;
  border: 1px solid var(--line);
  border-radius: var(--corner-lg);
  background: var(--white);
  color: var(--ink);
  transition: background-color .3s var(--ease), transform .3s var(--ease), border-color .3s var(--ease);
}
.drow:hover { transform: translateX(4px); border-color: var(--g-light); }
.section--dark .drow { background: var(--g-800); border-color: rgba(255,255,255,.1); color: #fff; }
.section--dark .drow:hover { background: var(--g-750); }
.drow__n { font-size: .8rem; font-weight: 800; color: var(--g-mid); }
.section--dark .drow__n { color: var(--lime); }
.drow__ico { color: var(--g-mid); }
.section--dark .drow__ico { color: var(--lime); }
.drow__body h4 { margin: 0; font-size: 1rem; line-height: 1.25; }
.drow__body p { margin: .15rem 0 0; font-size: .84rem; color: var(--body-2); }
.section--dark .drow__body p { color: var(--on-dark-soft); }
.drow__go { color: var(--g-mid); transition: transform .3s var(--ease); }
.section--dark .drow__go { color: var(--lime); }
.drow:hover .drow__go { transform: translateX(3px); }

.gdetail__units { display: flex; flex-wrap: wrap; gap: .7rem; margin-top: 1.6rem; }
.gunit {
  display: flex; align-items: center; gap: .7rem;
  padding: .75rem 1.1rem;
  border: 1px dashed var(--line);
  border-radius: var(--r-pill);
  color: var(--ink);
  transition: background-color .3s var(--ease), border-color .3s var(--ease);
}
.gunit:hover { border-style: solid; border-color: var(--g-light); background: var(--white); }
.gunit strong { display: block; font-size: .92rem; line-height: 1.2; }
.gunit small { font-size: .78rem; color: var(--body-2); }
.gunit svg { color: var(--g-mid); }
.section--dark .gunit { color: #fff; border-color: rgba(255,255,255,.22); }
.section--dark .gunit svg { color: var(--lime); }
.section--dark .gunit small { color: var(--on-dark-soft); }

/* ---------- 19g2. Signage ---------- */
.signgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: clamp(1rem, 1.6vw, 1.4rem);
  align-items: start;
}
.signcard {
  margin: 0;
  padding: clamp(1.1rem, 1.8vw, 1.5rem);
  border: 1px solid var(--line);
  border-radius: var(--corner-xl);
  background: var(--white);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.signcard:hover { transform: translateY(-4px); box-shadow: var(--sh-2); }
/* The plate is a neutral stage: a sign has to be judged against a wall, not
   against the page it is being sold on. */
.signcard__plate {
  display: grid;
  place-items: center;
  min-height: 190px;
  margin-bottom: 1.1rem;
  padding: 1.1rem;
  border-radius: var(--corner-lg);
  background:
    linear-gradient(180deg, rgba(6, 41, 27, .05), rgba(6, 41, 27, .09)),
    var(--cream);
}
.signcard__plate img { height: auto; display: block; filter: drop-shadow(0 6px 14px rgba(6, 41, 27, .18)); }
.signcard figcaption strong { display: block; font-size: 1rem; line-height: 1.2; }
.signcard__meta {
  display: block;
  margin: .25rem 0 .55rem;
  font-size: .68rem; font-weight: 800;
  letter-spacing: .09em; text-transform: uppercase;
  color: var(--g-mid);
}
.signcard--statutory .signcard__meta { color: #8A6D00; }
.signcard figcaption small { display: block; font-size: .86rem; color: var(--body); line-height: 1.45; }

.walk { display: grid; gap: .6rem; }
.walkstep {
  display: grid;
  grid-template-columns: auto 1fr 96px;
  align-items: center;
  gap: 1.2rem;
  padding: 1.1rem 1.3rem;
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: var(--corner-lg);
  background: var(--g-800);
}
.walkstep__n { font-size: .82rem; font-weight: 800; color: var(--lime); }
.walkstep__body h3 { margin: 0; font-size: 1.02rem; color: #fff; }
.walkstep__body p { margin: .2rem 0 0; font-size: .9rem; color: var(--on-dark-soft); }
.walkstep__sign {
  display: grid; place-items: center;
  padding: .5rem;
  border-radius: var(--corner-md);
  background: rgba(255, 255, 255, .06);
  transition: background-color .3s var(--ease), transform .3s var(--ease);
}
.walkstep__sign:hover { background: rgba(255, 255, 255, .12); transform: translateY(-2px); }
.walkstep__sign img { width: 100%; max-width: 68px; height: auto; display: block; }

.spec { display: grid; gap: .5rem; }
.spec__row {
  display: grid;
  grid-template-columns: minmax(0, .28fr) minmax(0, .72fr);
  gap: clamp(1rem, 2.5vw, 2.5rem);
  padding: 1.1rem 1.3rem;
  border: 1px solid var(--line);
  border-radius: var(--corner-lg);
  background: var(--cream);
}
.spec__row dt {
  font-size: .74rem; font-weight: 800;
  letter-spacing: .09em; text-transform: uppercase;
  color: var(--g-mid);
}
.spec__row dd { margin: 0; font-size: .95rem; }

/* ---------- 19h. Leadership ---------- */
.leader {
  padding: clamp(1.4rem, 2.3vw, 2rem);
  border: 1px solid var(--line);
  border-radius: var(--corner-xl);
  background: var(--white);
}
.leader__head { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.1rem; }
.leader__ico {
  display: grid; place-items: center;
  width: 60px; height: 60px; flex: none;
  border-radius: var(--corner-lg);
  background: var(--lime-4);
  color: var(--g-mid);
}
.leader h3 { margin: 0; }
.leader__role {
  margin: .1rem 0 0;
  font-size: .76rem; font-weight: 800;
  letter-spacing: .09em; text-transform: uppercase;
  color: var(--g-mid);
}
.leader > p { margin: 0 0 1.2rem; font-size: .95rem; }
.leader__quals { display: grid; gap: .4rem; margin: 0; padding: 1.1rem 0 0; list-style: none; border-top: 1px solid var(--line); }
.leader__quals li { font-size: .86rem; line-height: 1.45; color: var(--body-2); }

/* ---------- 19h2. Photographs off our own sites ----------
   Phone pictures, portrait, shown at the shape the camera recorded rather
   than stretched into the wide frames the stock photography uses. The frame
   holds 3:4 whatever the column does, so the subject engine always has the
   same box to work against and nothing is ever cropped.

   The caption sits under the picture, not over it. Over a photograph it
   would need a scrim, and a scrim across somebody's face to carry eight
   words is a bad trade. */
.wall { display: grid; gap: clamp(.9rem, 1.8vw, 1.5rem); }
/* Two portraits across a 1280px container would be two metre tall people.
   The pair is held to about the width three would take, which keeps the
   frames the same size as everywhere else they appear on the site. */
.wall--n2 { grid-template-columns: repeat(2, 1fr); max-width: 900px; }
.wall--n3 { grid-template-columns: repeat(3, 1fr); }
.wall__fig { margin: 0; }
.wall__frame {
  position: relative;
  overflow: hidden;
  aspect-ratio: 3 / 4;
  border-radius: var(--corner-xl);
  background: var(--g-800);
  box-shadow: var(--sh-1);
}
.wall__frame img {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  /* The same balance the photographic bands get, for the same reason:
     midday sun on red soil and jacaranda is far more saturated than the
     rest of the set, and the page should read as one set of pictures. */
  filter: saturate(.92) contrast(1.03);
  transition: transform .7s var(--ease);
}
.wall__fig:hover .wall__frame img { transform: scale(1.035); }
.wall__cap {
  display: flex;
  align-items: flex-start;
  gap: .55rem;
  margin-top: .9rem;
  font-size: .88rem;
  line-height: 1.45;
  color: var(--body-2);
}
.wall__ico { flex: none; margin-top: .08rem; color: var(--green); }
.wall__ico i { display: block; }
.section--dark .wall__cap { color: var(--on-dark-soft); }
.section--dark .wall__ico { color: var(--lime); }

/* ---------- 19i. Company page facts ---------- */
.cfacts { display: grid; gap: .6rem; }
.cfacts__logo {
  display: flex; align-items: center; gap: .85rem;
  padding: 1.15rem 1.25rem;
  margin-bottom: .3rem;
  border: 1px solid var(--line);
  border-radius: var(--corner-lg);
  background: var(--white);
}
.cfacts__logo { min-height: 72px; }
.cfact {
  padding: 1.05rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--corner-lg);
  background: var(--cream);
}
.cfact dt {
  font-size: .72rem; font-weight: 800;
  letter-spacing: .09em; text-transform: uppercase;
  color: var(--body-2);
  margin-bottom: .25rem;
}
.cfact dd { margin: 0; font-size: .98rem; font-weight: 700; color: var(--ink); }
.cfact a { color: var(--g-mid); border-bottom: 1px solid currentColor; }
.cfact a:hover { color: var(--ink); }
.cmeta {
  margin-top: 1.1rem;
  font-size: .8rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--body-2);
}

.split--narrow { grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); align-items: start; }
.shead--wide .shead__title { max-width: 22ch; }

/* ---------- 20. Back to top ---------- */
.fab-rail {
  position: fixed;
  right: clamp(1rem, 2.5vw, 2rem);
  bottom: clamp(1rem, 2.5vw, 2rem);
  z-index: 95;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .7rem;
}

.to-top {
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 0; border-radius: 50%; background: var(--white); color: var(--g-dark);
  border: 1px solid var(--line);
  cursor: pointer; box-shadow: var(--sh-2);
  opacity: 0; visibility: hidden; transform: translateY(10px);
  transition: opacity .3s var(--ease), transform .3s var(--ease), visibility .3s,
              background-color .3s var(--ease), color .3s var(--ease);
}
.to-top.is-visible { opacity: 1; visibility: visible; transform: none; }
.to-top:hover { background: var(--g-850); color: var(--lime); border-color: var(--g-850); }

/* ---- WhatsApp widget ---- */
.wa { position: relative; display: flex; flex-direction: column; align-items: flex-end; gap: .65rem; }

.wa__toggle {
  position: relative;
  width: 58px; height: 58px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: #25D366;
  color: #fff;
  cursor: pointer;
  box-shadow: 0 10px 28px rgba(6, 41, 27, .28);
  transition: transform .3s var(--ease), box-shadow .3s var(--ease), background-color .3s var(--ease);
}
.wa__toggle:hover { transform: scale(1.06); box-shadow: 0 14px 34px rgba(6, 41, 27, .34); }
.wa__toggle i { font-size: 31px; transition: transform .35s var(--ease), opacity .2s var(--ease); }
.wa__toggle .wa__close { position: absolute; font-size: 24px; opacity: 0; transform: rotate(-45deg); }
.wa__toggle[aria-expanded="true"] .wa__open { opacity: 0; transform: rotate(45deg); }
.wa__toggle[aria-expanded="true"] .wa__close { opacity: 1; transform: rotate(0); }

/* A quiet pulse, so the button is noticed once without nagging. */
.wa__toggle::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 50%;
  border: 2px solid #25D366;
  animation: wa-pulse 2.6s var(--ease) infinite;
}
.wa__toggle[aria-expanded="true"]::after { animation: none; opacity: 0; }
@keyframes wa-pulse {
  0%   { transform: scale(1);    opacity: .55; }
  70%  { transform: scale(1.45); opacity: 0; }
  100% { transform: scale(1.45); opacity: 0; }
}

.wa__panel {
  width: min(304px, calc(100vw - 2.5rem));
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--corner-xl);
  box-shadow: 0 20px 48px rgba(6, 41, 27, .22);
  overflow: hidden;
  transform-origin: bottom right;
  opacity: 0; visibility: hidden;
  transform: translateY(10px) scale(.96);
  transition: opacity .25s var(--ease), transform .3s var(--ease), visibility .3s;
}
.wa.is-open .wa__panel { opacity: 1; visibility: visible; transform: none; }

.wa__head {
  display: flex; align-items: center; gap: .65rem;
  padding: .9rem 1rem;
  background: linear-gradient(118deg, var(--g-900), var(--g-750));
  color: #fff;
}
.wa__head i { color: #25D366; font-size: 22px; }
.wa__head strong { display: block; font-size: .92rem; line-height: 1.2; }
.wa__head span { font-size: .76rem; color: var(--on-dark-soft); }

.wa__body { padding: .75rem; display: grid; gap: .5rem; }
.wa__opt {
  display: grid;
  grid-template-columns: 38px 1fr 16px;
  align-items: center;
  gap: .7rem;
  padding: .7rem .75rem;
  border-radius: var(--corner-md);
  background: var(--cream);
  color: var(--ink);
  transition: background-color .25s var(--ease), transform .25s var(--ease);
}
.wa__opt:hover { background: var(--lime-4); transform: translateX(2px); }
.wa__opt i:first-child {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: var(--corner-md);
  background: var(--white);
  color: var(--g-mid);
  font-size: 19px;
}
.wa__opt strong { display: block; font-size: .88rem; line-height: 1.25; }
.wa__opt small { display: block; margin-top: .12rem; font-size: .74rem; color: var(--body-2); line-height: 1.32; }
.wa__opt > i:last-child { color: var(--g-mid); font-size: 15px; }
.wa__foot { padding: 0 .75rem .8rem; font-size: .7rem; color: var(--body-2); text-align: center; }

@media (prefers-reduced-motion: reduce) { .wa__toggle::after { animation: none; } }

/* ---------- 21. Reveal ----------
   One family, nine gestures. Everything here animates transform and opacity
   only, so it stays on the compositor, and everything is cancelled wholesale
   under prefers-reduced-motion further down. */
.js [data-reveal] {
  opacity: 0; transform: translateY(24px);
  transition: opacity .7s var(--ease), transform .7s var(--ease);
  transition-delay: var(--d, 0ms);
  will-change: transform, opacity;
}
.js [data-reveal].is-in {
  opacity: 1; transform: none;
  will-change: auto;
}

/* zip -- alternating sides, tight and slightly sprung. The overshoot is what
   makes it read as arriving rather than as fading. */
.js [data-anim="zip"] > [data-reveal] {
  transform: translateX(-44px) skewX(-5deg);
  transition-duration: .54s;
  transition-timing-function: cubic-bezier(.22, 1.3, .36, 1);
}
.js [data-anim="zip"] > [data-reveal]:nth-child(even) {
  transform: translateX(44px) skewX(5deg);
}

/* deal -- a hand being dealt: flat, then down onto the table. */
.js [data-anim="deal"] > [data-reveal] {
  transform: perspective(900px) rotateX(13deg) translateY(30px) scale(.97);
  transform-origin: 50% 100%;
  transition-duration: .66s;
}

/* wipe -- uncovered left to right. The clip travels, the type does not. */
.js [data-reveal][data-anim="wipe"] {
  opacity: 1;
  transform: none;
  clip-path: inset(0 100% 0 0);
  transition: clip-path .82s cubic-bezier(.16, .84, .3, 1);
  transition-delay: var(--d, 0ms);
}
.js [data-reveal][data-anim="wipe"].is-in { clip-path: inset(0 0 0 0); }

/* slide -- rows in sequence, as a list is read. */
.js [data-anim="slide"] > [data-reveal] {
  transform: translateX(-32px);
  transition-duration: .58s;
}

/* scale -- a photograph coming to rest. */
.js [data-reveal][data-anim="scale"] { transform: scale(1.055); }
.js [data-anim="scale"] > [data-reveal] { transform: scale(1.055); }

/* split -- two columns parting from the line they share. */
.js [data-anim="split"] > [data-reveal]:nth-child(odd)  { transform: translateX(-38px); }
.js [data-anim="split"] > [data-reveal]:nth-child(even) { transform: translateX(38px); }
.js [data-anim="split"] > [data-reveal] { transition-duration: .7s; }

/* draw -- the overline's rule draws itself, then the label arrives. */
.js [data-reveal][data-anim="draw"] { opacity: 1; transform: none; }
.js [data-reveal][data-anim="draw"]::before {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .56s var(--ease) var(--d, 0ms);
}
.js [data-reveal][data-anim="draw"].is-in::before { transform: scaleX(1); }
.js [data-reveal][data-anim="draw"] > span,
.js [data-reveal][data-anim="draw"] { color: inherit; }

/* count -- the figures hold at zero until they are read, then run up. */
.js [data-anim="count"] > [data-reveal] { transform: translateY(18px); }
.figures dt[data-count] { font-variant-numeric: tabular-nums; }

/* The arrived state, for every gesture above. Each variant selector scores
   0-3-0, exactly what the plain arrived rule scores, and the variants come
   later, so without this a zipped step and a scaled photograph would hold
   their opening position permanently. */
.js [data-reveal].is-in,
.js [data-anim] > [data-reveal].is-in,
.js [data-reveal][data-anim].is-in {
  opacity: 1 !important;
  transform: none !important;
}
.js [data-reveal][data-anim="wipe"].is-in { clip-path: inset(0 0 0 0) !important; }

/* No motion preference: every gesture above is cancelled, not just the ones
   that move, or a clipped heading stays clipped and a drawn rule stays at
   zero width. */
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal],
  .js [data-anim] > [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    transition: none !important;
  }
  .js [data-reveal][data-anim="draw"]::before { transform: scaleX(1) !important; transition: none !important; }
  .hero__slide.is-active img { animation: none; transform: none; }
  .hero__slide { transition: none; }
  .hero__panel { transition: none; }
  .hero__tab.is-active .hero__tab-rail i { animation: none; transform: scaleX(1); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .js [data-reveal] { opacity: 1; transform: none; }
}

/* ---------- 22. Responsive ---------- */
@media (max-width: 1080px) {
  .footer__top { grid-template-columns: 1fr 1fr; }
  .steps { grid-template-columns: repeat(2, 1fr); }
  .gdetail { grid-template-columns: 1fr; gap: 2rem; }
  .split--narrow { grid-template-columns: 1fr; }
}

/* Below this the hero content genuinely cannot fit one screen; let it grow. */
@media (max-height: 560px) and (min-width: 981px) {
  .hero { height: auto; min-height: 0; padding-block: calc(var(--header-h) + 2rem) 3rem; }
}

/* The laptop band, between the drawer appearing at 980 and the width where
   the full row fits. The six labels, the mark, the two header gaps and the
   button come to about 1120px of content, so the row needs roughly 1240px of
   window before it can be set at full size. Below that it wants more room
   than it has, and
   a nav that wraps to two lines is worse than one set a shade smaller: the
   links tighten and the button falls back to its short wording, the same one
   the phone header already uses. */
@media (min-width: 981px) and (max-width: 1240px) {
  .nav__list { flex-wrap: nowrap; gap: .22rem; }
  /* nowrap on the link too: without it the list holds one line by breaking a
     two word label down the middle, which is the same ugliness one level in. */
  .nav__link { font-size: .87rem; padding: .5rem .34rem; white-space: nowrap; }
  .header__cta { margin-left: .35rem; }
  .header__cta .lbl-full { display: none; }
  .header__cta .lbl-brief { display: inline; }
  .header__cta .pbtn__label { padding: .62rem .9rem; font-size: .9rem; }
  .header__cta .pbtn__chev { display: none; }
}

@media (max-width: 980px) {
  .nav, .mega { display: none; }
  .nav-toggle { display: grid; margin-left: .35rem; }

  /* The one action in the header stays on a phone, compact, to the left of
     the menu. Hiding it left a reader with a menu and nothing to press. */
  .header__cta { display: block; margin-left: auto; }
  .header__cta .pbtn { padding: 4px .55rem 4px 4px; font-size: .84rem; }
  .header__cta .pbtn__label { padding: .62rem .85rem; font-size: .84rem; white-space: nowrap; }
  .header__cta .pbtn__chev { display: none; }
  /* The short wording below the desktop header. One of the two is always
     display:none, which hides it from a screen reader as well, so what is
     announced is what is on screen. */
  .header__cta .lbl-full { display: none; }
  .header__cta .lbl-brief { display: inline; }
  /* The chart turns into a spine: one vertical rule down the left with each
     company hanging off it. A three column chart at 390px is unreadable. */
  .org { align-items: stretch; }
  .org__parent { align-self: flex-start; }
  .org__trunk { margin-left: 22px; height: 24px; }
  .org__row {
    grid-template-columns: 1fr;
    grid-template-rows: none;
    row-gap: 1.4rem;
    padding-top: 0;
    padding-left: 22px;
  }
  .org__row::before {
    left: 0; right: auto; top: 0; bottom: 42px;
    width: 2px; height: auto;
  }
  .org__card, .org__subs { grid-row: auto !important; grid-column: auto !important; }
  .org__card::before {
    top: 34px; left: -22px;
    width: 22px; height: 2px;
    transform: none;
  }
  .org__subs { padding-left: 22px; }
  .org__subs::before { top: 0; left: 0; height: 100%; width: 2px; transform: none; }
  .sibs { grid-template-columns: 1fr; }
  .mega__grid { grid-template-columns: 1fr; }
  .org { display: none; }
  .orglist { display: block; }
  .topbar__list li:nth-child(2) { display: none; }
  .g-3, .g-4 { grid-template-columns: repeat(2, 1fr); }
  .split, .contact-grid { grid-template-columns: 1fr; }
  .shead { grid-template-columns: 1fr; align-items: start; }
  .shead__aside { padding-bottom: 0; }
  .shead__cta { justify-content: flex-start; }
  /* The hero owns the screen here too. Content is a column: the copy sits at the
     top, the actions follow, and the figures strip is pinned to the bottom. */
  /* Two zones. The photograph keeps the top of the screen and nothing is
     drawn over it; the copy sits on a solid ground below. A hero that fills
     the viewport only works when the picture can carry type, and a portrait
     crop of a wide frame usually cannot. */
  .hero {
    height: auto;
    min-height: 0;
    max-height: none;
    padding: 0;
    display: block;
    overflow: visible;
  }
  .hero__media {
    position: relative;
    inset: auto;
    height: 320px;
    z-index: 0;
    border-radius: 0;
    /* The picture gives out over its last fifth so it dissolves into the
       block below rather than ending on a line. */
    -webkit-mask-image: linear-gradient(to bottom, #000 62%, rgba(0,0,0,.55) 84%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 62%, rgba(0,0,0,.55) 84%, transparent 100%);
    background: var(--g-950);
  }
  .hero__slide img {
    filter: saturate(.94) contrast(1.03) brightness(calc(1.04 * var(--expo, 1)));
  }
  /* Only enough darkness at the join to carry the header and meet the block
     below it. The rest of the frame is left alone. */
  .hero__unify, .hero__vignette, .hero__grid { display: none; }
  .hero__scrim {
    /* Top aligned with the media. Anchored to the bottom it covered the copy
       block instead, which quietly greyed the headline to 67% white. */
    inset: 0 0 auto 0;
    height: 320px;
    /* Carries the header at the top, then lets the picture breathe, then
       closes into the block's own colour at the foot. */
    background: linear-gradient(180deg,
      rgb(var(--shade-rgb) / .72) 0%,
      rgb(var(--shade-rgb) / .18) 26%,
      rgb(var(--shade-rgb) / 0) 44%,
      rgb(var(--shade-rgb) / .30) 70%,
      rgb(var(--shade-rgb) / .78) 90%,
      var(--g-950) 100%);
  }
  .hero > .container {
    display: block;
    width: 100%;
    background: var(--g-950);
    padding-top: clamp(1.4rem, 4vw, 2rem);
    padding-bottom: clamp(1.6rem, 5vw, 2.4rem);
  }
  .hero__content { max-width: none; }
  /* The copy sits on a solid block here, so the shadows that carry it over a
     photograph on the desktop are just a halo. */
  .hero .h-hero, .hero__lead, .hero__call dd, .hero__call dt, .hero__tab {
    text-shadow: none;
  }
  .hero__lockup { filter: none; }

  .hero__panels { min-height: 0; }
  .hero__id { margin-bottom: .9rem; }
  .hero__lockup { height: 32px; }

  /* One pill. The other two actions are secondary, so they read as links. */
  .hero__actions {
    display: grid;
    gap: .9rem;
    margin-top: 1.3rem;
  }
  .hero__actions .pbtn--ghost {
    background: none;
    border: 0;
    backdrop-filter: none;
    padding: 0;
    justify-self: start;
  }
  .hero__actions .pbtn--ghost .pbtn__label { padding: 0; color: var(--lime); font-size: .95rem; }
  .hero__actions .pbtn--ghost .pbtn__chev { display: none; }
  .hero__call { gap: .6rem; }
  .hero__call .rbtn { width: 38px; height: 38px; }

  .hero__tabs { margin-top: 1.5rem; }

  .phero__media { width: 100%; opacity: 1; }
  .phero__scrim {
    background: linear-gradient(180deg,
      rgb(var(--shade-rgb) / .64) 0%,
      rgb(var(--shade-rgb) / .42) 34%,
      rgb(var(--shade-rgb) / .56) 70%,
      rgb(var(--shade-rgb) / .84) 100%);
  }
  .bento__hero { aspect-ratio: 2 / 1; }
}

@media (max-width: 640px) {
  /* A 26px dot grid behind 16px body copy is noise on a phone. */
  .section--cream { background-image: none; }
  .dgrid, .signgrid { grid-template-columns: 1fr; }
  /* A portrait two up on a phone is about 165px wide, which is a thumbnail
     of a face rather than a photograph of one. Two pictures stack; three
     lead with the first at full width and pair the other two, which keeps
     the section from becoming a column of three tall frames. */
  .wall--n2 { grid-template-columns: 1fr; max-width: none; }
  .wall--n3 { grid-template-columns: repeat(2, 1fr); }
  .wall--n3 .wall__fig:first-child { grid-column: 1 / -1; }
  .wall__cap { font-size: .84rem; }
  .walkstep { grid-template-columns: auto 1fr; }
  .walkstep__sign { grid-column: 2; justify-self: start; margin-top: .6rem; }
  .spec__row { grid-template-columns: 1fr; gap: .4rem; }
  .drow { grid-template-columns: auto 1fr auto; }
  .drow__ico { display: none; }
  .gdetail__units { flex-direction: column; align-items: stretch; }
  .gunit { border-radius: var(--corner-md); }
  .leader__head, .unit__head { gap: .8rem; }
  .leader__ico, .unit__ico { width: 50px; height: 50px; }
  .dcard__ico { width: 50px; height: 50px; }
  :root {
    --header-h: 64px;
    --topbar-h: 34px;
    --r-card: 20px;
    --r-lg: 16px;
    --r-md: 9px;
    --notch: 14px;
    --gap-tab: 20px;
    --gutter: 1.15rem;
    --section-y: 3.5rem;
    --cell: 26px;
  }

  /* The bar itself shortens to 64px here, so the mark cannot follow the
     desktop size all the way down; it keeps the same share of the bar. */
  .brand img, .header--solid .brand img { height: 46px; }

  /* One column for prose, two for anything that reads as a tile. Collapsing
     everything to one column makes the page taller and flatter than it needs. */
  .g-3, .g-4, .form-grid, .steps { grid-template-columns: 1fr; }
  .g-2 { grid-template-columns: 1fr; }
  .footer__top { grid-template-columns: 1fr 1fr; }
  .footer__brand { grid-column: 1 / -1; }

  /* Utility bar: the phone number only. */
  .topbar { font-size: .78rem; }
  .topbar__inner { min-height: 34px; justify-content: space-between; }
  .topbar__list li:not(:last-child) { display: none; }
  .topbar__social .script { display: none; }
  .topbar__social { gap: .7rem; margin-left: 0; }
  /* The mail and phone glyphs go: the number they duplicate is the one thing
     still showing in the list beside them, and the room they free is what
     the two social logos need at 320px. */
  .topbar__hide-sm { display: none; }

  /* ---- Hero ---- */
  .hero h1 { margin-bottom: clamp(.55rem, 1.6vh, .95rem); }
  .hero__lead {
    max-width: 34ch;
    font-size: clamp(.92rem, 3.9vw, 1rem);
    line-height: 1.55;
    margin-bottom: clamp(1rem, 2.8vh, 1.7rem);
  }

  /* Two full width actions, stacked and equal. */
  .hero__tabs { max-width: none; }
  .hero__tab {
    flex-direction: column; align-items: flex-start; gap: .2rem;
    padding: .62rem .6rem .66rem;
  }
  .hero__tab-n { font-size: .62rem; line-height: 1; }
  .hero__tab-text strong { font-size: .78rem; letter-spacing: -.015em; }
  .hero__tab-text small { display: none; }
  .hero__id { gap: .5rem .8rem; margin-bottom: .7rem; }
  .hero__lockup { height: 30px; }
  /* Two rows, not three: the primary action across the top, then the
     secondary link and the number sharing the line under it. Stacked, the
     three of them pushed the carousel tabs off the first screen. */
  .hero__actions {
    display: grid;
    grid-template-columns: auto minmax(0, auto);
    justify-content: start;
    align-items: center;
    gap: .95rem .85rem;
  }
  /* The primary action keeps the pill and the full width. */
  .hero__actions .pbtn:not(.pbtn--ghost) {
    grid-column: 1 / -1;
    width: 100%;
    justify-content: center;
    padding: 5px 1rem 5px 5px;
  }
  .hero__actions .pbtn:not(.pbtn--ghost) .pbtn__label {
    flex: 1; text-align: center; padding: .85rem 1rem;
  }
  /* The second one is secondary by definition, so it reads as a link. */
  .hero__actions .pbtn--ghost {
    width: auto;
    padding: 0;
    background: none;
    border: 0;
    backdrop-filter: none;
    box-shadow: none;
  }
  .hero__actions .pbtn--ghost .pbtn__label {
    padding: 0;
    color: var(--lime);
    font-size: .92rem;
    white-space: nowrap;
    border-bottom: 1px solid rgb(var(--accent-rgb) / .4);
  }
  .hero__actions .pbtn--ghost .pbtn__chev { display: none; }

  .hero__call {
    display: flex; align-items: center; gap: .35rem;
    padding: 0 0 0 .85rem; border: 0; background: none; backdrop-filter: none;
    position: relative;
  }
  /* A hairline keeps the two from reading as one control. */
  .hero__call::before {
    content: ""; position: absolute; left: 0; top: 50%;
    width: 1px; height: 1.1em; transform: translateY(-50%);
    background: rgba(255, 255, 255, .26);
  }
  .hero__call .rbtn { width: 22px; height: 22px; background: none; color: var(--lime); }
  .hero__call .rbtn:hover { transform: none; background: none; }
  /* The icon says "phone", so the label is for screen readers only. */
  .hero__call dt { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .hero__call dd { margin: 0; font-size: .92rem; white-space: nowrap; }


  /* Headings need tighter tracking at small sizes or they look loose. */
  .h-1, .h-2 { letter-spacing: -.028em; }
  .shead { margin-bottom: 2rem; gap: .9rem; }
  .shead__title { max-width: 20ch; }
  .shead__aside { font-size: .94rem; }

  /* Bento keeps its two up row; only the wide photo spans. */
  .bento { grid-template-columns: 1fr 1fr; }
  .bento__hero { aspect-ratio: 3 / 2; }
  .bento__tile, .bento__stat { aspect-ratio: 1 / 1; }
  .bento__stat strong { font-size: 1.8rem; }
  .bento__stat span { font-size: .76rem; }

  /* Notched cards: less air, so the tab still reads as part of the card. */
  .ncard__main { padding: 1.4rem 1.35rem 1.6rem; }
  .ncard__icon { margin-bottom: 1.5rem; }
  .i-2xl { font-size: 36px; }
  .ncard__foot { min-height: calc(42px + var(--tab-drop)); }
  .ncard__cta { font-size: .82rem; padding: 0 1.1rem; }

  .card { padding: 1.35rem 1.3rem; }
  .card__icon { width: 46px; height: 46px; margin-bottom: 1rem; }

  /* Sector rows */
  .row { grid-template-columns: 1fr auto; gap: 1rem; padding-block: 1.1rem; }
  /* The numerals are the only numeric texture on the page; without them
     five rows of body copy is not a list. */
  .row__n { display: block; font-size: .72rem; }
  .row__go { width: 38px; height: 38px; }
  .row:hover { padding-inline: 0; }

  /* Steps read better as a numbered list than as four stacked boxes. */
  .step { display: grid; grid-template-columns: 44px 1fr; column-gap: 1rem; padding: 1.1rem 1.2rem; }
  .step__n { grid-row: span 2; align-self: start; width: 38px; height: 38px; margin-bottom: 0; font-size: .85rem; }
  .step h3 { margin-bottom: .2rem; }

  /* Buttons reach the comfortable tap target without becoming slabs. */
  .pbtn { font-size: .9rem; padding: 5px 1rem 5px 5px; }
  .pbtn__label { padding: .78rem 1.15rem; }
  .plink { padding: .55rem 1rem; }

  /* Forms */
  .formcard { padding: 1.35rem 1.2rem; border-radius: var(--corner-lg); }
  .field input, .field select, .field textarea { padding: .8rem 1rem; font-size: 16px; }
  .field textarea { min-height: 110px; }

  .cinfo { grid-template-columns: 40px 1fr; gap: .85rem; padding: 1rem 0; }
  .cinfo__icon { width: 40px; height: 40px; }

  /* CTA band */
  .cta { border-radius: var(--corner-lg); padding: 1.75rem 1.35rem; }
  .cta__inner { gap: 1.4rem; }
  .cta__actions { width: 100%; flex-direction: column; }
  .cta__actions .pbtn { justify-content: center; }

  .accordion { gap: .6rem; }
  .acc__btn { padding: 1rem 1.15rem; gap: .9rem; }
  .acc__panel p { padding: 0 1.15rem 1.1rem; }

  .marquee__group { gap: 2.25rem; padding-right: 2.25rem; }
  .clients__label { font-size: .74rem; }

  .footer { padding-top: 3rem; }
  .footer__bottom { justify-content: center; text-align: center; }
  .footer__tagline { font-size: 1.45rem; }

  .office { padding: 1.25rem 1.2rem; }
  .ministat { padding: 1.25rem 1.2rem; }
  .tags span { font-size: .64rem; padding: .28rem .6rem; }

  .drawer__list a { font-size: 1.2rem; padding: .9rem 0; }
  .to-top { width: 40px; height: 40px; }
  .wa__toggle { width: 52px; height: 52px; }
  .wa__toggle i { font-size: 27px; }
  .fab-rail { gap: .55rem; }
}

/* Short phones (SE class). Shed the strip rather than squeeze everything. */
@media (max-width: 640px) and (max-height: 700px) {
  .hero { min-height: 0; }
  .hero__lead { display: none; }}

/* Very narrow phones: drop the bento to one column so nothing gets cramped. */
@media (max-width: 380px) {
  /* Three things on one line at 320px: the lockup gives up a few pixels and
     the action gives up its padding, rather than the action being dropped. */
  .brand img, .header--solid .brand img { height: 34px; }
  .header__cta .pbtn { padding: 3px .45rem 3px 3px; }
  .header__cta .pbtn__label { padding: .55rem .7rem; font-size: .8rem; }
  .nav-toggle { width: 38px; margin-left: .15rem; }
  .bento { grid-template-columns: 1fr; }
  .bento__tile, .bento__stat { aspect-ratio: 16 / 9; }
  .footer__top { grid-template-columns: 1fr; }
}

@media print {
  .header, .topbar, .drawer, .to-top, .hero__media, .footer { display: none !important; }
}
