/* ==========================================================================
   Blue Shield Services - design system and shared components
   Owner: foundation agent (Phase 3 integrator may edit). Page agents put
   page-specific rules in assets/css/pages/<page>.css, linked after this file.
   Selector policy: flat, single-class selectors wherever possible so page
   stylesheets can override without fights. No !important anywhere.
   ========================================================================== */


/* ==========================================================================
   0. Metric-matched stand-in for the display face
   ========================================================================== */

/* Barlow Condensed arrives over the network with `display=swap`, so the first
   paint of every page uses whatever the display stack falls back to. Measured
   at 100px/700 with the hero headline as the string, Barlow Condensed sets it
   in 2628px and Arial Narrow in 3166px: 20% wider, which took the home h1 from
   five lines to seven and dropped the second call to action 59px below the fold
   at 360x800 for the whole swap window. This face is the same local Arial
   Narrow scaled to Barlow Condensed's advance widths (2566/3104 of the glyph
   run once the 0.01em tracking, which `size-adjust` does not scale, is taken
   out of both), with Barlow Condensed's own vertical metrics (1000/-200 on a
   1000 em, so a `normal` line box is 1.2) declared over Arial Narrow's. It sits
   in `--font-display` ahead of the generic fallbacks, so the swap re-renders
   the headline without re-wrapping it. Where no narrow face is installed the
   src fails and the stack simply moves on, as it did before. */
@font-face {
  font-family: "Barlow Condensed Fallback";
  src: local("Arial Narrow"), local("Liberation Sans Narrow"), local("Nimbus Sans Narrow");
  size-adjust: 83.7%;
  ascent-override: 119.5%;
  descent-override: 23.9%;
  line-gap-override: 0%;
}


/* ==========================================================================
   1. Tokens
   ========================================================================== */

:root {
  /* colour */
  --navy-900: #0B1A3D;
  --navy-700: #1B2C5E;
  --blue-500: #2B8BD1;
  --blue-700: #1A64A8;
  --sky-100: #EAF3FB;
  --paper: #FFFFFF;
  --paper-2: #F5F8FC;
  --ink: #0F172A;
  --ink-soft: #475569;
  --line: #D9E2EC;
  --hivis: #FFD60A;
  --danger: #B42318;
  --on-dark: rgba(255, 255, 255, 0.82);
  --on-dark-soft: rgba(255, 255, 255, 0.64);
  --on-dark-line: rgba(255, 255, 255, 0.16);

  /* the signature: navy left half, blue right half, hard stop */
  --split-rule: linear-gradient(90deg, var(--navy-700) 0 50%, var(--blue-500) 50% 100%);
  --rule-h: 3px;
  --rule-h-hover: 5px;
  --seam: 6px;

  /* type */
  --font-display: "Barlow Condensed", "Barlow Condensed Fallback", "Arial Narrow", Impact, sans-serif;
  --font-body: "IBM Plex Sans", "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Consolas, monospace;
  --font-logo: "Montserrat", "Segoe UI", system-ui, sans-serif;

  --text-h1: clamp(2.75rem, 6vw, 5.5rem);
  --text-h2: clamp(2rem, 3.6vw, 3.25rem);
  --text-h3: 1.375rem;
  --text-lead: 1.25rem;
  --text-body: 1.0625rem;
  --text-small: 0.9375rem;
  --text-mono: 0.8125rem;
  --track-display: 0.01em;
  --track-mono: 0.08em;

  /* spacing (4px base) */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.25rem;
  --s-6: 1.5rem;
  --s-8: 2rem;
  --s-10: 2.5rem;
  --s-12: 3rem;
  --s-16: 4rem;
  --s-20: 5rem;
  --section-pad: clamp(4rem, 9vw, 7.5rem);
  --container: 1200px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);

  /* shape and chrome */
  --radius: 4px;
  --header-h: 88px;
  --header-h-scrolled: 72px;
  --z-header: 50;
  --z-nav: 45;
  --z-anchor: 30;

  /* motion */
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --dur: 240ms;
  --dur-slow: 400ms;
}


/* ==========================================================================
   2. Reset and base
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-h-scrolled) + 1rem);
}

/* the header is fixed, so the document starts below it (the home hero pads itself) */
body {
  margin: 0;
  min-height: 100vh;
  padding-top: var(--header-h);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-body);
  font-weight: 400;
  line-height: 1.6;
  /* A word longer than its line box breaks rather than pushing the page
     sideways. Nothing in the copy is that long at the default text size, but at
     150% browser text size and above several things are, and a phone then
     scrolls horizontally. `break-word` is the general policy; the three places
     that need the stronger `anywhere` are named below. */
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* `anywhere` where `break-word` is not enough. The two differ in exactly one
   way that matters: both break a word that would otherwise overflow, but only
   `anywhere` lets that word stop counting towards its box's min-content width,
   and it is that floor — not the line breaking — that widens a grid track past
   the viewport and scrolls the page sideways. An email address is a single
   36-character word: at 150% text size it is wider than a 390px phone, and it
   was flooring the footer's one-column track and the About letter's column.
   It is deliberately NOT declared on `body`: the credential strip's licence
   number is a word too, and `Z21-869-00S` broken across two lines is not a
   credential any more, so the strip keeps `break-word` and wraps at the space
   before it instead. */
a[href^="mailto:"],
a[href^="tel:"] {
  overflow-wrap: anywhere;
}

h1, h2, h3, h4, p, ul, ol, figure, blockquote, dl, dd {
  margin: 0;
}

img, svg, video {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

a {
  color: var(--blue-700);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

button, input, select, textarea {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
}

address {
  font-style: normal;
}

/* Focus ring: a hi-vis line carried inside a navy ring (WCAG 1.4.11).
   #FFD60A alone is only 1.41:1 on --paper and 1.33:1 on --paper-2, so the
   hi-vis can never be the indicator's outer edge on a light ground. The
   box-shadow paints --navy-900 from the border box out to 7px and the outline
   is drawn over it at 3-5px, so the ring reads navy / hi-vis / navy: the outer
   edge is navy (17.08:1 on --paper, 16.04:1 on --paper-2, 15.22:1 on
   --sky-100) and on the navy grounds, where that ring disappears into the
   ground, the hi-vis line itself carries the contrast (12.10:1 on --navy-900,
   9.48:1 on --navy-700). Every ground the ring lands on clears 3:1. */
:focus-visible {
  outline: 2px solid var(--hivis);
  outline-offset: 3px;
  box-shadow: 0 0 0 7px var(--navy-900);
}

::selection {
  background: var(--sky-100);
  color: var(--navy-900);
}

.nav-open {
  overflow: hidden;
}


/* ==========================================================================
   3. Typography
   ========================================================================== */

h1, h2, .h1, .h2 {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: var(--track-display);
  color: var(--navy-700);
  text-wrap: balance;
}

h1, .h1 {
  font-size: var(--text-h1);
  font-weight: 700;
  line-height: 0.95;
}

h2, .h2 {
  font-size: var(--text-h2);
  font-weight: 600;
  line-height: 1.02;
}

/* .h3 and .h4 also work on an h1 or h2 whose visual size differs from its level:
   they undo the display rule's capitals, tracking and balance */
h3, .h3 {
  font-family: var(--font-body);
  font-size: var(--text-h3);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: normal;
  text-transform: none;
  text-wrap: initial;
  color: var(--navy-700);
}

h4, .h4 {
  font-family: var(--font-body);
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: normal;
  text-transform: none;
  text-wrap: initial;
  color: var(--navy-700);
}

.display-num {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--text-h2);
  line-height: 1;
  color: var(--navy-700);
}

.eyebrow {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  font-weight: 500;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--blue-700);
  margin-bottom: var(--s-4);
}

.eyebrow--on-dark {
  color: var(--sky-100);
}

.lead {
  font-size: var(--text-lead);
  line-height: 1.5;
  color: var(--ink-soft);
}

.small {
  font-size: var(--text-small);
}

.muted {
  color: var(--ink-soft);
}

.mono {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  font-weight: 500;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
}

.measure {
  max-width: 62ch;
}

.measure--narrow {
  max-width: 44ch;
}

.on-dark {
  color: var(--on-dark);
}

.text-link {
  font-weight: 600;
  color: var(--blue-700);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}

.text-link:hover {
  color: var(--navy-700);
}


/* ==========================================================================
   4. Layout
   ========================================================================== */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--narrow {
  max-width: 820px;
}

.section {
  padding-block: var(--section-pad);
  background: var(--paper);
}

.section--tint {
  background: var(--paper-2);
}

.section--dark {
  background: var(--navy-900);
  color: var(--on-dark);
}

.section--flush-top {
  padding-top: 0;
}

.section__head {
  max-width: 62ch;
  margin-bottom: clamp(2rem, 5vw, 3.5rem);
}

.section__head--row {
  max-width: none;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-8);
  flex-wrap: wrap;
}

.section__head--split {
  max-width: none;
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: var(--s-8) clamp(2rem, 6vw, 5rem);
  align-items: end;
}

.section__head-note {
  flex: 0 1 auto;
}

.grid {
  display: grid;
  gap: var(--s-6);
}

.grid--2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.grid--3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.grid--4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.grid--gap-lg {
  gap: var(--s-8) clamp(2rem, 6vw, 5rem);
}

.split {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: var(--s-10) clamp(2rem, 6vw, 5rem);
  align-items: start;
}

.split--even {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.split__sticky {
  position: sticky;
  top: calc(var(--header-h-scrolled) + var(--s-8));
}

.stack > * + * {
  margin-top: var(--s-4);
}

.stack--xs > * + * {
  margin-top: var(--s-2);
}

.stack--sm > * + * {
  margin-top: var(--s-3);
}

.stack--lg > * + * {
  margin-top: var(--s-8);
}

.stack--xl > * + * {
  margin-top: var(--s-12);
}

.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  align-items: center;
}

.list-plain {
  list-style: none;
  padding: 0;
  margin: 0;
}

.divided > * + * {
  border-top: 1px solid var(--line);
}


/* ==========================================================================
   5. Components
   ========================================================================== */

/* --- Skip link, header, brand --------------------------------------------- */

.skip-link {
  position: absolute;
  top: var(--s-3);
  left: var(--s-3);
  z-index: 100;
  padding: var(--s-3) var(--s-4);
  background: var(--navy-900);
  color: #fff;
  font-weight: 600;
  border-radius: var(--radius);
  text-decoration: none;
  transform: translateY(-200%);
}

.skip-link:focus {
  transform: none;
}

/* the skip link's target carries tabindex="-1" so that following it really
   moves focus (and the scroll) into the page rather than only setting the
   hash. That focus is programmatic and the landmark is the whole page, so it
   takes no ring: the ring belongs to whatever the next Tab reaches. */
main[tabindex="-1"]:focus,
main[tabindex="-1"]:focus-visible {
  outline: none;
  box-shadow: none;
}

/* fixed (not sticky) on every page: the 88px to 72px shrink after 40px of scroll
   then changes only the header's own box, never the position of the page below it */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--z-header);
  height: var(--header-h);
  background: var(--paper);
  color: var(--ink);
  border-bottom: 1px solid transparent;
}

.site-header.is-scrolled {
  height: var(--header-h-scrolled);
  border-bottom-color: var(--line);
}

/* transparent over the home hero, solid after 40px of scroll; the hero pads for the header */
.home {
  padding-top: 0;
}

.home .site-header {
  background: transparent;
  color: #fff;
}

.home .site-header.is-scrolled {
  background: var(--paper);
  color: var(--ink);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--s-8);
  height: 100%;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  color: inherit;
  text-decoration: none;
  flex: none;
}

.brand__mark {
  /* 38 x 39.2 is the traced artwork's own ratio (viewBox 200 x 206.41); a
     mismatched box would letterbox the mark inside it */
  width: 38px;
  height: 39.2px;
  flex: none;
}

.brand__mark-left {
  fill: var(--navy-700);
}

.brand__mark-right {
  fill: var(--blue-500);
}

.home .site-header .brand__mark-left {
  fill: #fff;
}

.home .site-header.is-scrolled .brand__mark-left {
  fill: var(--navy-700);
}

.brand--on-dark .brand__mark-left {
  fill: #fff;
}

.brand__text {
  display: flex;
  flex-direction: column;
  line-height: 1;
}

.brand__name {
  font-family: var(--font-logo);
  font-weight: 800;
  font-size: 1.0625rem;
  letter-spacing: 0.02em;
  color: inherit;
}

.brand__sub {
  font-family: var(--font-logo);
  font-weight: 700;
  font-size: 0.5625rem;
  letter-spacing: 0.18em;
  color: var(--blue-500);
  margin-top: 0.3rem;
}

.brand--on-dark {
  color: #fff;
}

/* --- Navigation ---------------------------------------------------------- */

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-left: auto;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  color: inherit;
}

.nav-toggle__bars {
  position: relative;
  display: block;
  width: 22px;
  height: 2px;
  background: currentColor;
}

.nav-toggle__bars::before,
.nav-toggle__bars::after {
  content: "";
  position: absolute;
  left: 0;
  width: 22px;
  height: 2px;
  background: currentColor;
}

.nav-toggle__bars::before {
  top: -7px;
}

.nav-toggle__bars::after {
  top: 7px;
}

.nav-toggle.is-open .nav-toggle__bars {
  background: transparent;
}

.nav-toggle.is-open .nav-toggle__bars::before {
  top: 0;
  transform: rotate(45deg);
}

.nav-toggle.is-open .nav-toggle__bars::after {
  top: 0;
  transform: rotate(-45deg);
}

.nav {
  display: flex;
  align-items: center;
  gap: var(--s-8);
  margin-left: auto;
}

.nav__list {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav__item {
  position: relative;
}

.nav__link,
.nav__trigger {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 44px;
  padding: 0.5rem 0.75rem;
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  font-size: var(--text-small);
  font-weight: 500;
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}

/* hi-vis marker: hover and current page (accent use 3 of 3) */
.nav__link::after,
.nav__trigger::after {
  content: "";
  position: absolute;
  left: 0.75rem;
  right: 0.75rem;
  bottom: 0.45rem;
  height: 2px;
  background: var(--hivis);
  transform: scaleX(0);
  transform-origin: left;
}

.nav__link:hover::after,
.nav__trigger:hover::after,
.nav__link.is-active::after,
.nav__trigger.is-active::after,
.nav__item.is-open .nav__trigger::after {
  transform: scaleX(1);
}

.nav__chevron {
  width: 12px;
  height: 12px;
  flex: none;
}

.nav__item.is-open .nav__chevron {
  transform: rotate(180deg);
}

.nav__menu {
  position: absolute;
  top: calc(100% - 0.25rem);
  left: 0;
  z-index: 5;
  min-width: 300px;
  margin: 0;
  padding: 0.5rem 0 0.75rem;
  list-style: none;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  opacity: 0;
  visibility: hidden;
  transform: translateY(6px);
}

.nav__menu::before {
  content: "";
  position: absolute;
  top: -1px;
  left: -1px;
  right: -1px;
  height: var(--rule-h);
  background: var(--split-rule);
  border-radius: var(--radius) var(--radius) 0 0;
}

.nav__item.is-open .nav__menu {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.nav__menu-link {
  display: block;
  padding: 0.625rem 1.25rem;
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
}

.nav__menu-link:hover,
.nav__menu-link:focus-visible {
  background: var(--sky-100);
  color: var(--blue-700);
}

.nav__menu-all {
  margin-top: 0.5rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--line);
}

.nav__menu-all .nav__menu-link {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--blue-700);
}

.nav__actions {
  display: flex;
  align-items: center;
  gap: var(--s-5);
}

.nav__phone {
  font-weight: 600;
  font-size: var(--text-small);
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.nav__phone:hover {
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

/* --- Buttons ------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 48px;
  padding: 0.75rem 1.5rem;
  border: 2px solid transparent;
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: var(--text-small);
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  /* No `white-space: nowrap` here. It is a nowrap that cannot wrap: at 200%
     browser text size "Call 1300 310 462" is 355px wide, so on a 390px phone
     the button box grew past its own column and took the page with it. Losing
     it does not let button rows re-arrange, because a flex line breaks on the
     items' max-content sizes, which nowrap does not change — it only decides
     what happens once a button is narrower than its label, and a label on two
     centred lines is better than a page that scrolls sideways. */
  max-width: 100%;
  text-align: center;
  cursor: pointer;
}

.btn--primary {
  background: var(--blue-700);
  border-color: var(--blue-700);
  color: #fff;
}

.btn--primary:hover {
  background: var(--navy-700);
  border-color: var(--navy-700);
  color: #fff;
}

.btn--secondary {
  background: transparent;
  border-color: var(--navy-700);
  color: var(--navy-700);
}

.btn--secondary:hover {
  background: var(--navy-700);
  color: #fff;
}

.btn--ghost {
  min-height: 44px;
  padding-inline: 0;
  background: transparent;
  border-color: transparent;
  color: var(--blue-700);
}

.btn--ghost:hover {
  color: var(--navy-700);
  text-decoration: underline;
  text-underline-offset: 0.3em;
}

.btn--on-dark {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.55);
  color: #fff;
}

.btn--on-dark:hover {
  background: #fff;
  border-color: #fff;
  color: var(--navy-900);
}

.btn--sm {
  min-height: 44px;
  padding: 0.6rem 1.125rem;
  font-size: 0.875rem;
}

.btn--block {
  width: 100%;
}

.btn__arrow {
  width: 16px;
  height: 16px;
  flex: none;
}

.btn:hover .btn__arrow {
  transform: translateX(3px);
}

/* --- Separated list ------------------------------------------------------
   Items on one wrapping line with a middot between them, and no middot that can
   strand at a line break. The separator is not a glyph in the text: it is drawn
   in the flex column gap by a ::before on every item after the first, and the
   box is clipped at its own edge, so the dot that would open or close a wrapped
   line falls outside the box and is simply not painted.

   The home hero eyebrow and the services "Best for" row are listed alongside
   `.seplist` below: they get the mechanism through the classes their markup
   already has. The `ul` and descendant qualifiers on the "Best for" selectors
   are there to carry these rules past the page stylesheet that still styles the
   same list as an inline run. Both can drop to plain `.seplist` in the markup.
   ------------------------------------------------------------------------- */

.seplist,
.home-hero__eyebrow,
.service__for > ul.service__sectors {
  --seplist-gap: 1.5em;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--seplist-gap);
  row-gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow: clip;
}

.seplist > *,
.home-hero__eyebrow > .home-hero__eyebrow-part,
.service__for ul.service__sectors > li {
  position: relative;
}

.seplist > * + *::before,
.home-hero__eyebrow > .home-hero__eyebrow-part + .home-hero__eyebrow-part::before,
.service__for ul.service__sectors > li + li::before {
  content: "\00B7";
  position: absolute;
  left: calc(var(--seplist-gap) / -2);
  /* the box keeps the item's own metrics, so the dot sits on the item's
     baseline; the scale is what gives it weight (the mono middot reads as a
     dash at label sizes, so it borrows the body face) */
  font-family: var(--font-body);
  font-size: inherit;
  line-height: inherit;
  color: inherit;
  transform: translateX(-50%) scale(1.15);
}

/* the literal separators those two patterns still carry in their own markup */
.home-hero__eyebrow-sep {
  display: none;
}

.service__for ul.service__sectors > li::after {
  content: none;
}

/* the flex wrap still breaks between sectors first; a sector too long to fit the
   row on its own wraps inside itself rather than being clipped at the list edge */
.service__for ul.service__sectors > li {
  white-space: normal;
}

/* the label and the list sit on one baseline, the list wrapping inside itself */
.service__for {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
}

.service__for > ul.service__sectors {
  flex: 1 1 14rem;
  min-width: 0;
}

/* --- Split rule (standalone element) ------------------------------------- */

.split-rule {
  display: block;
  width: 100%;
  height: var(--rule-h);
  background: var(--split-rule);
}

.split-rule--seam {
  height: var(--seam);
  background: var(--blue-500);
}

/* --- Cards --------------------------------------------------------------- */

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1;
  height: var(--rule-h);
  background: var(--split-rule);
}

.card:hover {
  transform: translateY(-2px);
  border-color: #C5D2DF;
}

.card:hover::before {
  height: var(--rule-h-hover);
}

.card__media {
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--navy-900);
}

.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  flex: 1;
  padding: var(--s-6);
}

.card__title {
  font-size: var(--text-h3);
}

.card__text {
  color: var(--ink-soft);
  font-size: var(--text-small);
}

.card__link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  margin-top: auto;
  padding-top: var(--s-3);
  font-weight: 600;
  font-size: var(--text-small);
  color: var(--blue-700);
  text-decoration: none;
}

/* stretched link: the whole service card is the target */
.card--service .card__link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
}

.card--service:hover .card__link {
  color: var(--navy-700);
}

/* The stretched link makes the whole card the target, so the ring belongs on
   the card. `:has(… :focus-visible)` and not `:focus-within`: focus-within is
   true for a pointer click as well, which painted the ring around the card on
   an ordinary mouse click. The link's own :focus-visible ring is the one the
   browser draws here, and it is the card that gets it. */
.card--service:has(.card__link:focus-visible) {
  outline: 2px solid var(--hivis);
  outline-offset: 3px;
  box-shadow: 0 0 0 7px var(--navy-900);
}

/* only where the card ring above is actually painted, so the card is ringed
   once rather than twice; a browser without :has() keeps the link's own ring */
.card--service:has(.card__link:focus-visible) .card__link:focus-visible {
  outline: none;
  box-shadow: none;
}

.card--service:hover .card__media img {
  transform: scale(1.03);
}

.card--flat {
  border: 0;
  background: transparent;
  border-radius: 0;
  overflow: visible;
}

.card--pad {
  padding: var(--s-8);
}

/* --- Credential strip ---------------------------------------------------- */

.credential-strip {
  background: var(--navy-700);
  color: #fff;
  border-top: 2px solid var(--hivis);
}

/* A grid, not a wrapping flex row with space-between: the five items are the
   primary trust device and they sit directly under the hero, so a wrapped row
   has to land on the same tracks as the row above it rather than being spread
   edge to edge on its own. The column count is set per band (see section 8) so
   five items never leave a single item stranded on a row of its own; the tracks
   are `auto` here, because the item widths are very uneven (the licence number
   needs 256px, "AISP member" 123px) and equal tracks would starve the longest
   item while padding the shortest. `minmax(0, auto)` lets a track shrink below
   its content and wrap the text instead of overflowing the page. */
.credential-strip__list {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, auto));
  justify-content: space-between;
  align-items: center;
  gap: var(--s-3) var(--s-8);
  margin: 0;
  padding: var(--s-4) 0;
  list-style: none;
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  font-weight: 500;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
}

.credential-strip__item {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 28px;
}

.credential-strip__check {
  width: 16px;
  height: 16px;
  flex: none;
  color: var(--blue-500);
}

/* --- Page hero (inner pages) --------------------------------------------- */

.page-hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 40vh;
  padding-block: clamp(2.5rem, 5vw, 4rem);
  background: var(--navy-900);
  color: #fff;
}

.page-hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--seam);
  background: var(--blue-500);
}

.page-hero__inner {
  max-width: 62ch;
}

/* smaller than the home h1: the inner hero is a title bar, not the thesis */
.page-hero__title {
  max-width: 20ch;
  font-size: clamp(2.5rem, 4.5vw, 4rem);
  color: #fff;
}

.page-hero__lead {
  margin-top: var(--s-5);
  color: var(--on-dark);
  font-size: var(--text-lead);
  line-height: 1.5;
}

.page-hero--compact {
  min-height: 0;
}

/* A hero that runs straight into the credential strip drops its own seam bar:
   the strip's hi-vis hairline is the only edge there, so the site never shows
   two accent lines touching. `page-hero--seamless` says the same explicitly. */
.page-hero:has(+ .credential-strip)::after,
.page-hero--seamless::after {
  display: none;
}

/* --- Home hero ----------------------------------------------------------- */

/* The third term is what keeps the hero from becoming a void as the window
   narrows. `min(100vh, 880px)` alone held the hero at 880px all the way from
   1440 down to 861, while the panel's content stayed around 430px and the
   photograph — a 1800x1350 landscape — was squeezed into an ever narrower
   slot: 0.91:1 at 1440, 0.75 at 1200, 0.64 at 1025, 0.51 at 861. A different,
   steadily more extreme crop at every width, with roughly 190px of dead navy
   above the eyebrow and below the buttons at the bottom of that range.
   `--header-h + 62vw` makes the photograph's slot keep one ratio (about 0.8:1
   with the panel at 1fr, 0.756:1 where the panel takes 1.12fr below 64em)
   instead, which is the rule the stacked band already follows: one ratio, no
   cap, the same picture at every width. It is the smallest of the three from
   1277px down, so it governs exactly the range that had the void and nothing
   above it — at 1440 the 880px term still wins and the hero is unchanged.
   All three are floors, so a panel whose own content is taller still wins. */
.home-hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--seam) minmax(0, 1fr);
  min-height: min(100vh, 880px, calc(var(--header-h) + 62vw));
  background: var(--navy-900);
  color: #fff;
}

.home-hero__panel {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-top: calc(var(--header-h) + clamp(3rem, 6vw, 5rem));
  padding-bottom: clamp(3rem, 6vw, 5rem);
  padding-right: var(--gutter);
  padding-left: max(var(--gutter), calc((100vw - var(--container)) / 2 + var(--gutter)));
}

/* The home header is fixed and transparent over the hero, so a seam drawn over
   the full hero height would run up through the nav row and cut it in half.
   Start the seam at the header's lower edge instead: it still reads as one
   line from the header down to the credential strip's top border. */
.home-hero__seam {
  margin-top: var(--header-h);
  background: var(--blue-500);
}

.home-hero__eyebrow {
  margin-bottom: var(--s-6);
}

.home-hero__title {
  color: #fff;
  font-size: clamp(2.75rem, 4.2vw, 3.75rem);
  text-wrap: initial;
}

.home-hero__line {
  display: block;
}

.home-hero__lead {
  margin-top: var(--s-8);
  max-width: 42ch;
  color: var(--on-dark);
  font-size: var(--text-lead);
  line-height: 1.5;
}

.home-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  margin-top: var(--s-10);
}

/* The photo starts at the fixed header's lower edge, exactly like the seam, so
   the 88px header band is navy-900 right across its width. Without this the
   panel/photo boundary runs up through the nav row as a tonal edge and the
   right half of the header sits on the photograph. */
.home-hero__media {
  position: relative;
  margin-top: var(--header-h);
  overflow: hidden;
  background: var(--navy-900);
}

.home-hero__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 78% 50%;
  filter: grayscale(1) contrast(1.08);
}

/* navy duotone: multiply the greys into navy, then a light lift of blue */
.home-hero__media::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(90deg, rgba(11, 26, 61, 0.92), rgba(27, 44, 94, 0.7) 45%, rgba(27, 44, 94, 0.55));
  mix-blend-mode: multiply;
}

.home-hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: linear-gradient(90deg, rgba(43, 139, 209, 0.28), rgba(43, 139, 209, 0.1));
  mix-blend-mode: screen;
}

/* --- Included list (intro) ----------------------------------------------- */

.included {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}

.included__item {
  padding: var(--s-5) 0;
  border-bottom: 1px solid var(--line);
}

.included__title {
  font-size: 1.125rem;
  margin-bottom: var(--s-1);
}

.included__text {
  color: var(--ink-soft);
  font-size: var(--text-small);
}

/* --- Spec sheet (definition list: mono term, plain description, hairlines) --
   Used for officer standards (About), Deputy and Uniguard (Compliance) and the
   head office details (Contact). --spec-term sets the term column on the list. */

.spec {
  margin: 0;
  border-top: 1px solid var(--line);
}

.spec__row {
  display: grid;
  grid-template-columns: var(--spec-term, 12rem) minmax(0, 1fr);
  gap: var(--s-1) var(--s-6);
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--line);
}

.spec__term {
  padding-top: 0.2rem;
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  font-weight: 500;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  line-height: 1.6;
  color: var(--ink-soft);
}

.spec__desc {
  margin: 0;
  color: var(--ink);
}

/* one column: term above description */
.spec--stacked .spec__row {
  grid-template-columns: 1fr;
  gap: var(--s-1);
}

.spec--stacked .spec__term {
  padding-top: 0;
}

/* inside a bordered panel: the panel draws the outer edges */
.spec--flush {
  border-top: 0;
}

.spec--flush .spec__row:last-child {
  border-bottom: 0;
}

/* --- Pillars ------------------------------------------------------------- */

.pillars {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-10) var(--s-8);
  list-style: none;
  margin: 0;
  padding: 0;
}

.pillar {
  position: relative;
  padding-top: var(--s-5);
}

.pillar::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--rule-h);
  background: var(--split-rule);
}

.pillar__title {
  font-size: var(--text-h3);
  margin-bottom: var(--s-3);
}

.pillar__text {
  color: var(--ink-soft);
}

/* --- Steps (a real sequence: the only numbered device on the site) ------- */

.steps {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--s-6) var(--s-5);
  list-style: none;
  margin: 0;
  padding: 0;
}

.step {
  position: relative;
  padding-top: var(--s-5);
}

.step::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--rule-h);
  background: var(--split-rule);
}

.step__num {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  font-weight: 500;
  letter-spacing: var(--track-mono);
  color: var(--blue-700);
  margin-bottom: var(--s-3);
}

.step__title {
  font-size: 1.125rem;
  margin-bottom: var(--s-2);
}

.step__text {
  color: var(--ink-soft);
  font-size: var(--text-small);
}

.steps--stacked {
  grid-template-columns: 1fr;
}

.steps--stacked .step {
  display: grid;
  grid-template-columns: 4rem minmax(0, 1fr);
  gap: 0 var(--s-4);
}

.steps--stacked .step__num {
  margin: 0;
  padding-top: 0.2rem;
}

.steps--stacked .step__title,
.steps--stacked .step__text {
  grid-column: 2;
}

/* --- Chips --------------------------------------------------------------- */

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.chip {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0.5rem 1rem;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--navy-700);
}

.chip--tint {
  background: var(--sky-100);
  border-color: transparent;
}

/* --- Wordmarks and testimonial ------------------------------------------- */

/* The trusted-by row is a logo row, so it takes the full container width as its
   own band rather than half of a split: five uniform slots on one line under a
   hairline, sized so real client logo files can drop into the slots later
   without reflowing the section. A split that contains one collapses to a
   single column and the row sits above whatever follows it. */
.split:has(.wordmarks) {
  grid-template-columns: minmax(0, 1fr);
}

.split:has(.wordmarks) .testimonial {
  max-width: 42rem;
}

/* the `ul` qualifier is deliberate: it carries this row past a page stylesheet
   that still sets columns on the same list through its own single class.
   A wrapping flex row rather than a grid: the slots are still uniform
   (`--wordmark-cols` is the only thing a breakpoint changes, and every slot is
   exactly one column wide, so a client logo file drops into one without
   reflowing the row), but a row that does not fill — the fifth name under two
   at 768 — is centred instead of hanging off the left.
   Each name is centred in its own slot, so the row reads as evenly spaced
   across the hairline above it with no rag at the end. */
ul.wordmarks {
  --wordmark-cols: 5;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}

ul.wordmarks > li.wordmark {
  flex: 0 0 calc(100% / var(--wordmark-cols));
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 4.5rem;
  padding-inline: var(--s-2);
  text-align: center;
  font-family: var(--font-display);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--ink-soft);
}

.testimonial {
  padding: var(--s-8);
}

.testimonial__quote {
  font-size: var(--text-lead);
  font-weight: 500;
  line-height: 1.5;
  color: var(--navy-700);
}

.testimonial__quote::before {
  content: "\201C";
}

.testimonial__quote::after {
  content: "\201D";
}

.testimonial__cite {
  display: block;
  margin-top: var(--s-5);
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  font-style: normal;
  font-weight: 500;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* --- CTA band ------------------------------------------------------------ */

.cta-band {
  background: var(--navy-900);
  color: #fff;
  padding-block: clamp(3.5rem, 7vw, 6rem);
}

.cta-band__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-8);
  flex-wrap: wrap;
}

.cta-band__title {
  color: #fff;
  max-width: 18ch;
}

.cta-band__text {
  margin-top: var(--s-4);
  max-width: 44ch;
  color: var(--on-dark);
}

.cta-band__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
}

/* --- Anchor nav (services page) ------------------------------------------ */

.anchor-nav {
  position: sticky;
  top: var(--header-h-scrolled);
  z-index: var(--z-anchor);
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}

/* The trailing fade's width. It is registered so it can be interpolated, and it
   starts at 0 so that the fade is absent unless something switches it on. */
@property --anchor-fade {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

.anchor-nav__list {
  display: flex;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.anchor-nav__list::-webkit-scrollbar {
  display: none;
}

/* Trailing air at the end of the scroll, so the last label is never pressed
   against the edge it arrived at. It is a flex item rather than padding on the
   list, because the Services page re-declares the list's padding to bleed the
   row into the gutters on a phone, which is exactly where this is needed. */
.anchor-nav__list::after {
  content: "";
  flex: none;
  width: var(--s-6);
}

/* On a phone the seven labels are a horizontal scrollport with its scrollbar
   hidden, so the four past the right edge do not look scrollable: they look cut
   off. A mask fades the trailing edge while there is more to reach and retracts
   to nothing over the last of the scroll, and the spacer above keeps the final
   label clear of the edge once it arrives.
   The fade is driven by the list's own scroll position, which is also what
   keeps it off the desktop bar: a scroll timeline on a container that cannot
   scroll is inactive, so the animation has no effect and `--anchor-fade` keeps
   its 0px initial value, leaving the gradient's hard stop past the right edge.
   Nothing moves on its own here - the mask only follows the finger - so this
   sits outside the reduced-motion guard. */
@supports (animation-timeline: scroll(self inline)) {
  .anchor-nav__list {
    mask-image: linear-gradient(to right, #000 0, #000 calc(100% - var(--anchor-fade)), transparent calc(100% + 1px));
    animation-name: anchor-nav-fade;
    animation-timing-function: linear;
    animation-fill-mode: both;
    animation-timeline: scroll(self inline);
  }

  /* A focused link must never be dimmed by the fade: its ring is drawn inside
     the link (below), so a link focused under the trailing edge would lose part
     of its own indicator. With any link focused the mask comes off entirely. */
  .anchor-nav__list:has(.anchor-nav__link:focus-visible) {
    mask-image: none;
  }

  @keyframes anchor-nav-fade {
    0%,
    82% {
      --anchor-fade: 2.5rem;
    }

    100% {
      --anchor-fade: 0px;
    }
  }
}

.anchor-nav__link {
  display: inline-flex;
  align-items: center;
  min-height: 52px;
  padding: 0 var(--s-4);
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  font-weight: 500;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--ink-soft);
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
}

.anchor-nav__link:hover {
  color: var(--navy-700);
}

/* The list is a horizontal scrollport, and `overflow-x: auto` clips the other
   axis too, while the link fills the bar's full height: an outward ring would
   be cut off top and bottom and read as two vertical bars. Draw this one ring
   inside the link instead, same navy / hi-vis / navy order and same widths. */
.anchor-nav__link:focus-visible {
  outline-offset: -3px;
  box-shadow: inset 0 0 0 7px var(--navy-900);
}

.anchor-nav__link.is-active {
  color: var(--navy-700);
  border-bottom-color: var(--navy-700);
}

/* --- Form controls ------------------------------------------------------- */

.form {
  display: grid;
  gap: var(--s-5);
}

.form__row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-5);
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}

.field__label {
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--ink);
}

.field__hint {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--ink-soft);
}

.field__error {
  display: none;
  font-size: 0.875rem;
  color: var(--danger);
}

.field.is-invalid .field__error {
  display: block;
}

.input,
.select,
.textarea {
  width: 100%;
  min-height: 48px;
  padding: 0.75rem 0.875rem;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink);
  font-size: 1rem;
  line-height: 1.4;
}

.input:hover,
.select:hover,
.textarea:hover {
  border-color: #B7C6D6;
}

.input:focus-visible,
.select:focus-visible,
.textarea:focus-visible {
  border-color: var(--navy-700);
}

.field.is-invalid .input,
.field.is-invalid .select,
.field.is-invalid .textarea {
  border-color: var(--danger);
}

.textarea {
  min-height: 9rem;
  resize: vertical;
}

.select {
  appearance: none;
  padding-right: 2.75rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%230F172A' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.875rem center;
}

.checkbox {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  font-size: var(--text-small);
}

.checkbox__input {
  flex: none;
  width: 20px;
  height: 20px;
  margin: 0.2rem 0 0;
  accent-color: var(--blue-700);
}

.honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-status {
  display: none;
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: var(--text-small);
}

.form-status.is-visible {
  display: block;
}

.form-status--ok {
  background: var(--sky-100);
  border-color: var(--blue-700);
  color: var(--navy-900);
}

.form-status--error {
  border-color: var(--danger);
  color: var(--danger);
}

/* --- Footer -------------------------------------------------------------- */

/* the hairline marks where the CTA band ends and the footer starts (both navy-900) */
.site-footer {
  background: var(--navy-900);
  color: var(--on-dark);
  padding-block: clamp(3rem, 6vw, 5rem) var(--s-8);
  border-top: 1px solid var(--on-dark-line);
  font-size: var(--text-small);
}

.site-footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1.1fr) minmax(0, 1.3fr);
  gap: var(--s-10) var(--s-8);
}

/* `ch` is font-relative, so at 150% browser text size a 34ch measure is wider
   than the column it sits in and the footer pushes the page sideways. The
   measure still governs at the default text size; `100%` takes over past that. */
.site-footer__blurb {
  margin-top: var(--s-5);
  max-width: min(34ch, 100%);
}

.site-footer__title {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  font-weight: 500;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: #fff;
  margin-bottom: var(--s-4);
}

/* Most of the services links wrap to two lines. The space between items is kept
   near twice the leading inside one, so a wrapped link still reads as a single
   item instead of merging into a paragraph with its neighbours. */
.site-footer__links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--s-3);
}

/* every footer link is a full 44px row */
.site-footer__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-block: var(--s-3);
  line-height: 1.3;
  color: var(--on-dark);
  text-decoration: none;
}

.site-footer__link:hover {
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

.site-footer__contact {
  display: grid;
  gap: var(--s-1);
}

.site-footer__contact a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  justify-self: start;
  color: #fff;
  text-decoration: none;
}

.site-footer__contact a:hover {
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

.site-footer__id {
  font-family: var(--font-mono);
  font-size: var(--text-mono);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--on-dark-soft);
  display: grid;
  gap: 0.375rem;
  margin-top: var(--s-6);
}

.site-footer__legal {
  margin-top: var(--s-12);
  padding-top: var(--s-6);
  border-top: 1px solid var(--on-dark-line);
  display: grid;
  gap: var(--s-5);
}

.site-footer__ack {
  max-width: 78ch;
  color: var(--on-dark-soft);
}

.site-footer__copy {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s-2) var(--s-6);
  color: var(--on-dark-soft);
  font-size: 0.875rem;
}


/* ==========================================================================
   6. Utilities
   ========================================================================== */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.reveal {
  opacity: 1;
  transform: none;
}

.reveal--d1,
.reveal--d2,
.reveal--d3,
.reveal--d4,
.reveal--d5 {
  --reveal-delay: 0ms;
}

.hide-mobile {
  display: initial;
}

.show-mobile {
  display: none;
}

.text-center {
  text-align: center;
}


/* ==========================================================================
   7. Motion (everything here is off under prefers-reduced-motion: reduce)
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
  /* smooth only for anchor navigation (a focused link), never for programmatic scrolls */
  html:focus-within {
    scroll-behavior: smooth;
  }

  .site-header {
    transition: height var(--dur) var(--ease), background-color var(--dur) var(--ease),
      border-color var(--dur) var(--ease), color var(--dur) var(--ease);
  }

  .brand__mark-left {
    transition: fill var(--dur) var(--ease);
  }

  .nav__link::after,
  .nav__trigger::after {
    transition: transform var(--dur) var(--ease);
  }

  .nav__chevron {
    transition: transform var(--dur) var(--ease);
  }

  .nav__menu {
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease),
      visibility 0s linear var(--dur);
  }

  .nav__item.is-open .nav__menu {
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease), visibility 0s;
  }

  .site-header::after {
    transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
  }

  .site-header.is-nav-open::after {
    transition: opacity var(--dur) var(--ease), visibility 0s;
  }

  .nav-toggle__bars,
  .nav-toggle__bars::before,
  .nav-toggle__bars::after {
    transition: transform var(--dur) var(--ease), top var(--dur) var(--ease),
      background-color var(--dur) var(--ease);
  }

  .btn {
    transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease),
      border-color var(--dur) var(--ease);
  }

  .btn__arrow {
    transition: transform var(--dur) var(--ease);
  }

  .card {
    transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
  }

  .card::before {
    transition: height var(--dur) var(--ease);
  }

  .card__media img {
    transition: transform 600ms var(--ease);
  }

  .skip-link {
    transition: transform var(--dur) var(--ease);
  }

  .anchor-nav__link {
    transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
  }

  .input,
  .select,
  .textarea {
    transition: border-color var(--dur) var(--ease);
  }

  /* scroll reveals (only hidden when JS is running, so content never disappears) */
  .js .reveal {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 600ms var(--ease) var(--reveal-delay, 0ms),
      transform 600ms var(--ease) var(--reveal-delay, 0ms);
  }

  .js .reveal.is-visible {
    opacity: 1;
    transform: none;
  }

  .reveal--d1 { --reveal-delay: 80ms; }
  .reveal--d2 { --reveal-delay: 160ms; }
  .reveal--d3 { --reveal-delay: 240ms; }
  .reveal--d4 { --reveal-delay: 320ms; }
  .reveal--d5 { --reveal-delay: 400ms; }

  /* home load sequence, under 1.2s in total */
  .home-hero__panel {
    animation: hero-rise var(--dur-slow) var(--ease) both;
  }

  .home-hero__line {
    opacity: 0;
    animation: hero-line 520ms var(--ease) forwards;
  }

  .home-hero__line:nth-child(1) { animation-delay: 160ms; }
  .home-hero__line:nth-child(2) { animation-delay: 240ms; }
  .home-hero__line:nth-child(3) { animation-delay: 320ms; }
  .home-hero__line:nth-child(4) { animation-delay: 400ms; }

  .home-hero__eyebrow,
  .home-hero__lead,
  .home-hero__actions {
    opacity: 0;
    animation: hero-fade 480ms var(--ease) forwards;
  }

  .home-hero__eyebrow { animation-delay: 120ms; }
  .home-hero__lead { animation-delay: 520ms; }
  .home-hero__actions { animation-delay: 620ms; }

  .home-hero__media img {
    animation: hero-zoom 900ms var(--ease) both;
  }

  .credential-strip__item {
    opacity: 0;
    animation: hero-fade var(--dur-slow) var(--ease) forwards;
  }

  .credential-strip__item:nth-child(1) { animation-delay: 560ms; }
  .credential-strip__item:nth-child(2) { animation-delay: 630ms; }
  .credential-strip__item:nth-child(3) { animation-delay: 700ms; }
  .credential-strip__item:nth-child(4) { animation-delay: 770ms; }
  .credential-strip__item:nth-child(5) { animation-delay: 840ms; }

  @keyframes hero-rise {
    from { opacity: 0; transform: translateY(24px); }
    to { opacity: 1; transform: none; }
  }

  @keyframes hero-line {
    from { opacity: 0; transform: translateY(0.35em); }
    to { opacity: 1; transform: none; }
  }

  @keyframes hero-fade {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  @keyframes hero-zoom {
    from { transform: scale(1.04); }
    to { transform: scale(1); }
  }
}

/* ==========================================================================
   8. Responsive
   ========================================================================== */

/* WHICH BREAKPOINTS ARE FONT-RELATIVE, AND WHY.
   A breakpoint in `px` moves when the window gets narrower. A breakpoint in
   `em` moves when the window gets narrower OR when the reader enlarges text,
   because `em` in a media query is measured against the browser's own default
   font size — the setting a reader changes to make text bigger. (It is NOT
   affected by `html { font-size }` in a stylesheet: Media Queries Level 4
   evaluates font-relative units against the *initial* value, so no declaration
   in this file can move them. That is a property of the cascade, not of the
   choice of unit.)
   So the rule here is: a layout that breaks because the TEXT got bigger is
   written in `em`; a layout that breaks because the VIEWPORT got narrower, or
   whose number is a measured photographic geometry, stays in `px`.
   Every conversion below is numerically identical at the default text size
   (1em = 16px), so nothing moves at 100%: 75em = 1200px, 64em = 1024px,
   55.3125em = 885px, 48em = 768px, 30em = 480px.
   In `em`:  the nav collapse (a row of words that must fit beside the logo),
             the wordmark slot, the credential strip's track count, the
             column-count and type-scale steps at 48em and 30em. Every one of
             them is a question of whether text still fits its box.
   In `px`:  the home hero's own bands — the 860px stack point, the 380px title
             step, and the 799px/720px height bands. Those numbers are not text
             measurements: they are the photograph's crop and the fold budget,
             measured off a 1800x1350 file at six named phone viewports (see
             docs/components.md, "Home hero"). Re-banding them with the text
             size would change the crop of the photograph, which is the one
             thing that block exists to hold still.
   `assets/js/main.js` still hard-codes `(max-width: 1024px)` as MOBILE_QUERY;
   it should become `(max-width: 64em)` in the same pass (see components.md). */

/* There are five names, so the column count steps 5 -> 2 -> 1: every count in
   that ladder either fills its row or leaves a single centred name at the end.
   Three columns is the one count that cannot, because five names over three
   slots leaves a visible hole in the last row under a left-aligned opener, so
   the row holds five slots until it drops to two. Below the container width a
   slot is too narrow for the longest client name on one line, so the names wrap
   inside their slot instead; the slots themselves stay uniform, which is what a
   real logo file will need.
   `em`, because the thing that stops fitting is a name: the slot is a share of
   the container, the name is text, and at a larger text size the name outgrows
   the slot at a wider window than 1200px. */
@media (max-width: 75em) {
  ul.wordmarks > li.wordmark {
    white-space: normal;
  }
}

/* The credential strip's ladder is 5 -> 3 -> 2 -> 1, and every step past the
   first is a grid of equal tracks so that a wrapped row lands on the same
   tracks as the row above it, starting on the container's left edge.
   The five items measure 1071px including their gaps, so one line holds only
   while the container is at its full 1200px width; below that, four tracks
   would fit and strand the fifth item alone on a second row (the old
   space-between flex row did exactly that between 1100 and 600). Three equal
   tracks give 3 + 2 with no hole.
   885px is where three tracks stop holding "Master licence Z21-869-00S" on one
   line (3 x 16rem plus two 20px gaps inside the gutters), and a licence number
   broken across two lines is not a credential any more; below that the count
   follows the same floor on its own: two tracks down to about 583px, then one.
   Both numbers are `em` here because both were derived from a `rem` text
   measure: 885px is where three copies of the licence line stop fitting, so at
   a larger text size they stop fitting at a proportionally wider window. */
@media (min-width: 55.3125em) and (max-width: 75em) {
  .credential-strip__list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    justify-content: start;
    column-gap: var(--s-5);
  }
}

/* The 16rem floor is the licence line's width, so a track is never too narrow
   for it — but it is font-relative, and at 150% browser text size 16rem is
   384px, wider than the 330px of container a 390px phone has. `min(16rem, 100%)`
   keeps the floor where it was at the default text size and lets it stand down
   to the track's own width past that, which is the difference between a licence
   number on one line and the whole page scrolling sideways.
   `not all and (min-width: …)` rather than `max-width: 55.3125em`: it is the
   exact complement of the band above, so the two can never both match and can
   never both miss. A `max-width` one step below would leave a sliver of
   fractional widths matching neither, and a `max-width` at the same number
   would match alongside the band above and win on source order, taking 885px
   itself from three tracks to two. */
@media not all and (min-width: 55.3125em) {
  .credential-strip__list {
    grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
    justify-content: start;
    column-gap: var(--s-6);
  }
}

/* 64em, not 1024px, and this is the breakpoint the rule at the top of this
   section exists for. The desktop header is a row of words — five nav labels,
   a phone number and a button — laid beside the logo inside a fixed bar. It
   stops fitting when that text gets wider, and text gets wider for two reasons:
   a narrower window and a larger text size. A `px` breakpoint only sees the
   first. With 1024px here, a reader at 150% text size on a 1280px window kept
   the desktop nav, and the nav ran off the right edge: the header is
   `position: fixed`, so nothing was added to `document.scrollWidth` and no
   scrollbar appeared, and because the hamburger was still `display: none`
   there was no way back to the phone number or "Request a quote" — the site's
   two conversion controls, gone, on every page, with no scroll and no fallback
   (WCAG 2.1 AA 1.4.4 Resize Text). In `em` the bar hands over to the hamburger
   as the text grows, which is what the hamburger is for.
   The rest of this block is column counts and the hero's panel/photo ratio.
   They are `em` for the same reason: a three-card row or a five-step row stops
   working when the words in it need more room than the track has, and that is
   a text measurement, not a window measurement. */
@media (max-width: 64em) {
  .nav-toggle {
    display: inline-flex;
  }

  /* off-canvas panel */
  .nav {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: var(--z-nav);
    width: min(88vw, 400px);
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: var(--s-8);
    margin: 0;
    padding: calc(var(--header-h) + var(--s-6)) var(--gutter) var(--s-10);
    background: var(--navy-900);
    color: #fff;
    overflow-y: auto;
    visibility: hidden;
    transform: translateX(100%);
    border-left: var(--seam) solid var(--blue-500);
  }

  .nav.is-open {
    visibility: visible;
    transform: none;
  }

  /* Backdrop behind the panel: one navy ground over the page, so the strip of
     page still showing beside the panel reads as a dimmed page rather than a
     clipped one. It is drawn by the header so that it sits inside the header's
     stacking context, above the brand and below the panel, and a click on it
     lands on the header (main.js closes the panel on a click outside it). */
  .site-header::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: calc(var(--z-nav) - 1);
    background: var(--navy-900);
    opacity: 0;
    visibility: hidden;
  }

  .site-header.is-nav-open::after {
    opacity: 0.7;
    visibility: visible;
  }

  .nav__list {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  .nav__item {
    border-bottom: 1px solid var(--on-dark-line);
  }

  /* `white-space: normal` undoes the desktop row's nowrap. In the bar a nav
     label must not break, because the row is laid out along one line; in the
     panel every label is its own full-width row, so a label that outgrows the
     panel has somewhere to go. It does outgrow it: at 200% text size
     "Compliance & safety" sets 428px of 52px condensed capitals inside a 394px
     panel, and with nowrap the panel — which is `overflow-y: auto`, so its
     overflow-x computes to `auto` too — scrolled sideways. That is the file's
     own rule from the Buttons note: no nowrap on anything that can be longer
     than the column it sits in. */
  .nav__link,
  .nav__trigger {
    width: 100%;
    justify-content: space-between;
    min-height: 56px;
    padding: 0.75rem 0;
    font-family: var(--font-display);
    font-size: 1.625rem;
    font-weight: 600;
    letter-spacing: var(--track-display);
    text-transform: uppercase;
    white-space: normal;
  }

  .nav__link::after,
  .nav__trigger::after {
    left: 0;
    right: auto;
    width: 2rem;
    bottom: 0.5rem;
  }

  .nav__chevron {
    width: 18px;
    height: 18px;
  }

  .nav__menu {
    position: static;
    display: none;
    min-width: 0;
    margin: 0 0 var(--s-4);
    padding: 0;
    background: transparent;
    color: inherit;
    border: 0;
    border-radius: 0;
    opacity: 1;
    visibility: visible;
    transform: none;
  }

  .nav__menu::before {
    display: none;
  }

  .nav__item.is-open .nav__menu {
    display: block;
  }

  .nav__menu-link {
    padding: 0.625rem 0;
    color: var(--on-dark);
    font-size: 1rem;
  }

  .nav__menu-link:hover,
  .nav__menu-link:focus-visible {
    background: transparent;
    color: #fff;
  }

  .nav__menu-all {
    border-top-color: var(--on-dark-line);
  }

  .nav__menu-all .nav__menu-link {
    color: var(--sky-100);
  }

  .nav__actions {
    flex-direction: column;
    align-items: stretch;
    gap: var(--s-4);
  }

  .nav__phone {
    font-family: var(--font-display);
    font-size: 1.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-display);
  }

  .home .site-header.is-nav-open {
    color: #fff;
  }

  .site-header.is-nav-open {
    color: #fff;
  }

  .site-header.is-nav-open .brand__mark-left {
    fill: #fff;
  }

  /* the brand and the close button both stay above the backdrop and the panel,
     so an open menu still reads as logo left, close right, over a dimmed page
     instead of a logo half-covered by the panel edge */
  .site-header.is-nav-open .brand,
  .site-header.is-nav-open .nav-toggle {
    position: relative;
    z-index: calc(var(--z-nav) + 1);
  }

  /* The hero keeps its two panels the whole way down to 860 (it only stacks
     below that, in its own block further down). A tablet is still wide enough
     for the split, and the split is what keeps the thesis and both calls to
     action inside the first screen: stacked, the photograph alone pushes the
     h1 past the fold. The panel takes the larger share here, because below the
     container width it is the text column that runs short, not the photograph,
     and the title steps down with the viewport so its four lines keep their
     breaks. */
  /* The panel takes the larger share; the hero's height is handled once in the
     base rule (see the `62vw` term there), which is what took this band from
     880px of hero around 420px of content — 190px of dead navy above the
     eyebrow and 190px below the buttons — to a panel that fits what is in it
     and a photograph cropped to 0.756:1 at every width from 900 to 1024. */
  .home-hero {
    grid-template-columns: minmax(0, 1.12fr) var(--seam) minmax(0, 1fr);
  }

  /* The floor is 2.5rem because 2.5rem is what the headline sets to on a phone
     (the stacked band's own `clamp(2.5rem, 9vw, 4rem)` bottoms out there), and
     a tablet-width two-panel hero showing a SMALLER thesis than a 390px phone
     was the clearest symptom that this band had been left behind: 4vw put it
     at 34.4px at 861 and 36px at 900 against the phone's 40px. The measure is
     not what was binding — "Licensed protection", the longest of the four
     written lines, sets 331px at 40px against 383px of panel at 861 — so the
     floor costs nothing. 4.2vw matches the base rule's own slope, so 1024
     (43.0px) runs straight into 1025 (44.0px) with no step. */
  .home-hero__title {
    font-size: clamp(2.5rem, 4.2vw, 3.75rem);
  }

  .home-hero__lead {
    margin-top: var(--s-6);
  }

  .home-hero__actions {
    margin-top: var(--s-8);
  }

  .steps {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--s-6) var(--s-4);
  }

  .step__title {
    font-size: 1rem;
  }

  .grid--4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .grid--3 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* `minmax(0, 1fr)`, matching the two-column form above: a bare `1fr` floors
     the stacked column at its content's min-content width, and at 200% browser
     text size a tracked mono heading inside a policy card is wider than a 390px
     phone, which grew the column and scrolled the page sideways. */
  .split {
    grid-template-columns: minmax(0, 1fr);
  }

  .split__sticky {
    position: static;
  }

  .site-footer__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Below 860 the two panels no longer both hold their content, so the hero
   stacks: photo first, the seam turns horizontal, then the text panel. The
   photograph is a band rather than half the screen, because every pixel of
   photo here is a pixel of thesis pushed down: the band has to leave the
   eyebrow, the h1, the lead and both calls to action inside the first screen.
   This one stays in `px`, and so do the 380px title step and the two height
   bands below it, deliberately: 860 is where the photograph changes from half
   the screen to a fixed-ratio band, and everything downstream of it — the
   21/9, 5/2 and 3/1 ratios, the `object-position` numbers, the six-viewport
   fold table in docs/components.md — is geometry measured off the photograph
   in device pixels. Moving that band with the text size would re-crop the
   photograph, which is the one thing these rules exist to hold still. */
@media (max-width: 860px) {
  /* `minmax(0, 1fr)`, not `1fr`: the one stacked column must be allowed to be
     the width of the viewport. A bare `1fr` floors it at the panel's
     min-content width, and at 200% browser text size the headline's own words
     are wider than a 390px phone, which pushed the hero — and the page — past
     the viewport. */
  .home-hero {
    position: relative;
    display: block;
    min-height: 0;
  }

  /* Stacked, the photograph is the hero's GROUND, not a band above it. A band
     is pure overhead: it pushes the thesis down the screen and buys nothing a
     background does not, which is why the band spent so long being re-cropped
     and re-capped to claw back a few pixels. As a ground it costs no vertical
     space at all, the officer is seen at full height instead of through a
     letterbox, and the whole hero reads as one image with the words on it. */
  .home-hero__media {
    position: absolute;
    inset: 0;
    z-index: 0;
    order: 0;
    margin-top: 0;
    width: auto;
    min-height: 0;
    aspect-ratio: auto;
  }

  /* The container is now taller than it is wide, and the photograph is
     landscape, so `cover` crops the sides rather than the top and bottom. 62%
     across keeps the officer and the SECURITY print in frame while the lit
     truss stays at the edge; 34% down places his head in the upper third,
     behind the eyebrow and clear of the headline. */
  .home-hero__media img {
    object-position: 62% 34%;
  }

  /* The desktop duotone runs left to right, which is right for two panels side
     by side and wrong under a full-bleed text block. Vertical instead, and
     deeper: every word of the hero now sits on the photograph, so the scrim is
     what makes them readable rather than a mood. Measured white-on-scrim
     contrast stays above 12:1 over the brightest part of the frame. */
  .home-hero__media::before {
    background: linear-gradient(
      180deg,
      rgba(11, 26, 61, 0.74) 0%,
      rgba(11, 26, 61, 0.88) 42%,
      rgba(11, 26, 61, 0.95) 100%
    );
    mix-blend-mode: normal;
  }

  .home-hero__media::after {
    background: linear-gradient(180deg, rgba(43, 139, 209, 0.16), rgba(43, 139, 209, 0.03));
  }

  /* the seam becomes the hero's bottom edge, meeting the credential strip's
     hi-vis hairline exactly as the vertical seam does on desktop */
  .home-hero__seam {
    position: absolute;
    inset: auto 0 0;
    height: var(--seam);
    z-index: 2;
    order: 0;
    margin-top: 0;
  }

  /* the panel now clears the fixed header itself, because nothing sits above it */
  .home-hero__panel {
    position: relative;
    z-index: 1;
    order: 0;
    padding: calc(var(--header-h) + clamp(2rem, 7vw, 3rem)) var(--gutter)
      clamp(2.75rem, 9vw, 3.5rem);
  }

  /* 6.34em is 14ch measured in Barlow Condensed (its "0" is 0.4531em), written
     as em because `ch` is the one unit here that the webfont swap moves. The
     metric-matched fallback in section 0 holds the letters to Barlow's advance
     widths, but no single `size-adjust` can hold the digits as well: Barlow
     Condensed's "0" is as wide as Arial Narrow's while its capitals are 16%
     narrower, so a 14ch measure shrank to 12ch-worth of room on fallback
     metrics and the four written lines wrapped into seven — 68px of extra
     headline, which is what pushed the second call to action below the fold at
     360x800 for the whole display=swap window. In em the measure is the same
     228px either way, and the lines break in the same four places. */
  .home-hero__title {
    font-size: clamp(2.5rem, 9vw, 4rem);
    max-width: 6.34em;
    /* body sets overflow-wrap: break-word so no page can scroll sideways. On the
       thesis that is the wrong trade: at very large text it splits words across
       lines and the headline reads as fragments. The headline is short enough
       that a long word can simply overhang its measure instead. */
    overflow-wrap: normal;
  }

  /* stacked, the gaps close up: the eyebrow, thesis, lead and both buttons
     have to read as one block inside the first screen */
  .home-hero__lead {
    margin-top: var(--s-6);
  }

  .home-hero__actions {
    margin-top: var(--s-8);
  }

  .home-hero__line {
    display: inline;
  }
}

/* Narrow phones: the thesis steps down a little so the lead and both buttons
   still clear the fold. 36px condensed caps still carry the headline. */
@media (max-width: 380px) {
  .home-hero__title {
    font-size: clamp(2.25rem, 9vw, 3.5rem);
  }

  .home-hero__lead {
    margin-top: var(--s-5);
  }

  .home-hero__actions {
    gap: var(--s-3);
  }
}

/* Shorter than a current phone (a 360x800 or 390x844 screen keeps the 21/9 band
   above). Height is the constraint here rather than width, so the band steps
   down to a shallower fixed ratio instead of to a height that varies per
   device: 5:2 is the deepest band that still leaves both calls to action in the
   first screen at these heights, and it is the same crop on every one of them.
   No height cap here either, for the reason given above: a cap would make this
   band's crop depend on the width as well, which is exactly the bug. This band
   trades the back-print for the whole head — its 53% window opens at 7% — and
   that is a deliberate difference from the band above, not a side effect. */
/* Nothing to do here any more: the photograph is the hero's ground, so it costs
   no height and a short screen does not need it shortened. Kept as a marker so
   the next person does not reintroduce a band. */

/* Short phones (an iPhone SE is only 667px tall). Height, not width, is the
   constraint here, so the photo, the thesis and the lead all give ground to
   keep "Request a quote" on the first screen. One fixed ratio again, and again
   no cap: 3:1 cuts a 44% window that holds the head and shoulders, and the
   print sits below the frame at every width in the band. */
@media (max-width: 860px) and (max-height: 720px) {
  .home-hero__title {
    font-size: clamp(2rem, 7.5vw, 2.5rem);
  }

  .home-hero__lead {
    margin-top: var(--s-5);
    font-size: 1rem;
  }

  .home-hero__actions {
    margin-top: var(--s-6);
  }
}

/* 48em: the phone type scale and the last of the column counts. Every rule in
   here is a "the words no longer have room" rule — two columns to one, a
   narrower definition-term column, a smaller step title — so it follows the
   text size as well as the window. */
@media (max-width: 48em) {
  :root {
    --header-h: 72px;
    --text-body: 1rem;
    --text-lead: 1.125rem;
    --text-h3: 1.25rem;
  }

  .site-header__inner {
    gap: var(--s-4);
  }

  /* the strip's column count is handled by the 884 band above; on a phone it
     only needs a little more air above and below */
  .credential-strip__list {
    padding-block: var(--s-5);
  }

  .section__head--split,
  .split--even {
    grid-template-columns: 1fr;
  }

  .grid--2 {
    grid-template-columns: 1fr;
  }

  .pillars {
    grid-template-columns: 1fr;
    gap: var(--s-8);
  }

  /* Three slots, not two: with five names two slots leave the fifth alone on a
     centred row in the middle of the band, which reads as a stray line of text
     rather than as the last logo in a set. Three gives 3 + 2, and from here
     down the names align to the left edge of their slot so both rows start on
     the same line as the heading above them. A real logo file will drop into a
     slot the same way; only the alignment inside it changes. */
  ul.wordmarks {
    --wordmark-cols: 3;
    justify-content: flex-start;
  }

  ul.wordmarks > li.wordmark {
    justify-content: flex-start;
    text-align: left;
  }

  .steps {
    grid-template-columns: 1fr;
  }

  .step {
    display: grid;
    grid-template-columns: 3.5rem minmax(0, 1fr);
    gap: 0 var(--s-4);
    padding-top: var(--s-4);
  }

  .step__num {
    margin: 0;
    padding-top: 0.25rem;
  }

  .step__title,
  .step__text {
    grid-column: 2;
  }

  .step__title {
    font-size: 1.125rem;
  }

  .cta-band__inner {
    flex-direction: column;
    align-items: flex-start;
  }

  .spec__row {
    grid-template-columns: min(var(--spec-term, 12rem), 9rem) minmax(0, 1fr);
    gap: var(--s-1) var(--s-5);
  }

  .form__row {
    grid-template-columns: 1fr;
  }

  .page-hero {
    min-height: 0;
    padding-top: var(--s-12);
  }

  .hide-mobile {
    display: none;
  }

  .show-mobile {
    display: initial;
  }
}

/* 30em: the last step, where everything that is still two-up goes one-up and
   the buttons go full width. `em` again — the footer comment below is the
   evidence for it, since the column that grew past the viewport there grew
   because of the text size, not because of the window. */
@media (max-width: 30em) {
  /* full width on a phone: a 48px strip of page beside the panel only ever
     shows the logo sliced through the middle of its letters */
  .nav {
    width: 100%;
  }

  .brand__mark {
    width: 32px;
    height: 37px;
  }

  .brand__name {
    font-size: 0.9375rem;
  }

  .home-hero__actions .btn {
    flex: 1 1 100%;
  }

  .grid--3,
  .grid--4 {
    grid-template-columns: 1fr;
  }

  .card__body {
    padding: var(--s-5);
  }

  .spec__row {
    grid-template-columns: 1fr;
    gap: var(--s-1);
  }

  .spec__term {
    padding-top: 0;
  }

  .testimonial {
    padding: var(--s-6);
  }

  ul.wordmarks {
    --wordmark-cols: 1;
  }

  ul.wordmarks > li.wordmark {
    min-height: 3rem;
  }

  .cta-band__actions {
    width: 100%;
  }

  .cta-band__actions .btn {
    flex: 1 1 100%;
  }

  /* one column on a phone: the services links are long enough that sharing a
     two-column grid leaves no room to tell one wrapped item from the next.
     `minmax(0, 1fr)`, like the four- and two-column steps above it: a bare
     `1fr` floors the track at its content's min-content width, and at 150%
     browser text size the support address in the contact column is wider than
     a 390px phone, so the track — and the page with it — grew past the
     viewport. */
  .site-footer__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-8);
  }

  .step {
    grid-template-columns: 3rem minmax(0, 1fr);
  }
}
