/* ==========================================================================
   Allied Computers theme
   Tokens and components ported from the Allied Computers design system
   (project/tokens.json and project/components/bundle.css). The design
   system is the source of truth: change values there first, then here.
   ========================================================================== */

/* ---------- Tokens: colour (single "light" theme) ---------- */
:root {
  --navy:          #0B1B3F;
  --midnight:      #06122B;
  --signal:        #1463FF;
  --signal-hover:  #0F4FD6;
  --signal-soft:   #8FB3FF;
  --sky:           #E8F0FF;
  --cloud:         #F5F7FB;
  --surface:       #FFFFFF;
  --line:          #DDE3EE;
  --ink:           var(--navy);
  --ink-body:      #475569;
  --ink-muted:     #64748B;
  --on-dark:       #FFFFFF;
  --on-dark-muted: #B8C4DC;

  /* ---------- Tokens: type ---------- */
  --font-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* ---------- Tokens: spacing ---------- */
  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
  --space-6: 24px; --space-8: 32px; --space-12: 48px; --space-20: 80px;

  /* ---------- Tokens: radius ---------- */
  --radius-sm: 6px; --radius-md: 12px; --radius-full: 999px;

  /* ---------- Tokens: shadow, opacity, layout ---------- */
  --shadow-card:   0 1px 2px rgba(11,27,63,.06), 0 8px 24px rgba(11,27,63,.08);
  --overlay-photo: 0.72;
  --container-max: 1200px;

  /* Sticky header: 80px bar plus its 1px rule. The fold subtracts this,
     so change it here and the first screen stays exactly one viewport. */
  --header-h: 81px;
}

/* IBM Plex Sans, self-hosted (SIL Open Font License 1.1), Latin subset,
   weights 400/500/600/700 — about 94KB total. No Google Fonts call in
   production, per the design system README. font-display:swap so text
   paints immediately in the fallback and reflows when the face arrives. */
@font-face{font-family:"IBM Plex Sans";src:url("/assets/fonts/ibm-plex-sans-400.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"IBM Plex Sans";src:url("/assets/fonts/ibm-plex-sans-500.woff2") format("woff2");font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:"IBM Plex Sans";src:url("/assets/fonts/ibm-plex-sans-600.woff2") format("woff2");font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:"IBM Plex Sans";src:url("/assets/fonts/ibm-plex-sans-700.woff2") format("woff2");font-weight:700;font-style:normal;font-display:swap}

/* ==========================================================================
   Base
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body.ac-root {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 26px;
  color: var(--ink-body);
  background: var(--surface);
  -webkit-font-smoothing: antialiased;
}

.ac-root img { max-width: 100%; }

.ac-container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--space-6);
}

.ac-section { padding-block: var(--space-20); }
.ac-section--cloud { background: var(--cloud); }
.ac-section--surface { background: var(--surface); }
.ac-section--navy { background: var(--navy); color: var(--on-dark-muted); }

@media (max-width: 720px) {
  .ac-section { padding-block: var(--space-12); }
}

.ac-skip-link {
  position: absolute; left: -9999px; top: 0;
  background: var(--signal); color: var(--on-dark);
  padding: var(--space-3) var(--space-4); z-index: 100;
  border-radius: 0 0 var(--radius-sm) 0; font-weight: 600;
}
.ac-skip-link:focus { left: 0; }

.ac-visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ==========================================================================
   Components — ported verbatim from the design system's bundle.css
   ========================================================================== */
.ac-eyebrow{font-family:var(--font-sans);font-size:12px;line-height:16px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--signal);margin:0}
.ac-section-header{text-align:center;max-width:720px;margin:0 auto}
.ac-section-header h2{font-family:var(--font-sans);font-size:40px;line-height:46px;font-weight:700;letter-spacing:-.015em;color:var(--ink);margin:var(--space-2) 0 var(--space-3)}
.ac-section-header p{font-size:18px;line-height:30px;color:var(--ink-body);margin:0}

/* --------------------------------------------------------------------------
   Buttons
   The first pass was a flat rectangle with a 6px corner: correct, and
   completely anonymous. This version gives them the page's own vocabulary.

   Three decisions, applied to every variant:

   1. PILL. The site is already full of circular wells (credentials,
      proof, office icons) and circular arrow chips on every card. A pill
      button belongs to that family; a 6px rectangle belonged to nothing.
      The radius system is now: controls = pill, containers = 12px,
      icon wells = circle. One rule, no exceptions.

   2. MATERIAL, not fill. A one-pixel inner highlight along the top edge
      plus a shadow tinted to the button's own hue (never black) makes the
      button read as a raised object. Flat fills are what make a CTA look
      like a coloured div.

   3. THE ARROW MOVES. The trailing arrow shifts on hover and the whole
      button lifts 1px, then presses down 1px on :active. Feedback, not
      decoration: the pointer gets an answer.
   -------------------------------------------------------------------------- */
.ac-btn{
  position:relative;display:inline-flex;align-items:center;gap:10px;
  font-family:var(--font-sans);font-size:15px;line-height:20px;font-weight:600;
  padding:14px 26px;border-radius:var(--radius-full);
  border:1.5px solid transparent;cursor:pointer;text-decoration:none;
  white-space:nowrap;letter-spacing:.005em;
  transition:background .18s ease,border-color .18s ease,
             transform .18s cubic-bezier(.16,1,.3,1),box-shadow .18s ease;
}
.ac-btn svg{transition:transform .18s cubic-bezier(.16,1,.3,1)}
.ac-btn:hover svg{transform:translateX(3px)}
/* Physical press. Overrides the hover lift, so the button cannot appear
   raised and pressed at the same time. */
.ac-btn:active{transform:translateY(1px)}

.ac-btn--primary{
  background:var(--signal);color:var(--on-dark);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.26),
             0 2px 6px rgba(20,99,255,.24),
             0 8px 20px rgba(20,99,255,.22);
}
.ac-btn--primary:hover{
  background:var(--signal-hover);transform:translateY(-1px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.26),
             0 4px 10px rgba(20,99,255,.28),
             0 14px 30px rgba(20,99,255,.26);
}
.ac-btn--primary:active{
  transform:translateY(1px);
  box-shadow:inset 0 1px 2px rgba(6,18,43,.28);
}

/* Ghost on navy. The border carries the shape; the fill only arrives on
   hover, so the label never changes colour mid-interaction. */
.ac-btn--on-dark{
  background:rgba(255,255,255,.04);color:var(--on-dark);
  border-color:rgba(255,255,255,.45);
}
.ac-btn--on-dark:hover{
  background:rgba(255,255,255,.14);border-color:var(--on-dark);
  transform:translateY(-1px);
}
.ac-btn--on-dark:active{transform:translateY(1px);background:rgba(255,255,255,.08)}

/* Outline on light ground. Fills with the accent on hover, which is why
   the label flips to white with it (see the button colour lock below). */
.ac-btn--secondary{
  background:var(--surface);color:var(--navy);border-color:var(--navy);
  box-shadow:0 1px 2px rgba(11,27,63,.06);
}
.ac-btn--secondary:hover{
  background:var(--signal);border-color:var(--signal);
  transform:translateY(-1px);
  box-shadow:0 2px 6px rgba(20,99,255,.24),0 10px 24px rgba(20,99,255,.20);
}
.ac-btn--secondary:active{transform:translateY(1px);box-shadow:none}

.ac-btn:focus-visible{outline:2px solid var(--signal);outline-offset:3px}

/* The lift and the arrow are decoration. The colour changes are the part
   that carries meaning, so those stay. */
@media (prefers-reduced-motion: reduce){
  .ac-btn,.ac-btn svg{transition:background .18s ease,border-color .18s ease}
  .ac-btn:hover,.ac-btn:active{transform:none}
  .ac-btn:hover svg{transform:none}
}

.ac-card{position:relative;display:flex;flex-direction:column;justify-content:flex-end;min-height:300px;padding:var(--space-6);border-radius:var(--radius-md);overflow:hidden;background:var(--midnight);color:var(--on-dark);text-decoration:none;isolation:isolate}
.ac-card__media{position:absolute;inset:0;z-index:-2}
.ac-card__media img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .5s ease}
.ac-card::before{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(180deg,rgba(6,18,43,.05) 0%,rgba(6,18,43,.45) 38%,rgba(6,18,43,.92) 72%,rgba(6,18,43,.97) 100%)}
.ac-card__icon{color:var(--on-dark);line-height:0;margin-bottom:var(--space-3)}
.ac-card__icon svg{width:32px;height:32px}
.ac-card__title{font-family:var(--font-sans);font-size:17px;line-height:24px;font-weight:700;letter-spacing:.01em;text-transform:uppercase;color:var(--on-dark);margin:0 0 var(--space-2)}
.ac-card__copy{font-size:14px;line-height:22px;color:var(--on-dark-muted);margin:0 0 var(--space-4)}
.ac-card__link{display:inline-flex;align-items:center;gap:10px;font-size:15px;font-weight:600;color:var(--on-dark)}
.ac-arrow{width:28px;height:28px;border-radius:var(--radius-full);background:var(--signal);display:inline-flex;align-items:center;justify-content:center;color:var(--on-dark);transition:transform .2s ease}
.ac-card:hover .ac-card__media img{transform:scale(1.05)}
.ac-card:hover .ac-arrow{transform:translateX(3px);background:var(--signal-hover)}
.ac-card:focus-visible{outline:2px solid var(--signal);outline-offset:3px}
.ac-card-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-4)}
@media (max-width:960px){.ac-card-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:600px){.ac-card-grid{grid-template-columns:1fr}.ac-card{min-height:280px}}

/* --------------------------------------------------------------------------
   Bento — the six solutions
   Six items, six cells, no filler tile. The lead solution takes a tall
   2x2 cell and is the only one carrying a photograph; the rest are compact
   navy tiles. That contrast is what stops this reading as another grid of
   identical boxes.

      +-----------------+-------+
      |                 |  (2)  |
      |    feature      +-------+
      |      (1)        |  (3)  |
      +-----+-----+-----+-------+
      | (4) | (5) |      (6)    |
      +-----+-----+-------------+
   -------------------------------------------------------------------------- */
.ac-bento {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-12);
}
.ac-card--feature { grid-column: span 2; grid-row: span 2; min-height: 480px; }
.ac-card--feature .ac-card__title { font-size: 21px; line-height: 28px; }
.ac-card--feature .ac-card__copy  { font-size: 15px; line-height: 24px; max-width: 46ch; }

/* Every tile is one cell. Six items fill the 3x3 grid exactly once the
   feature has taken its 2x2 footprint, so the last tile lands in the
   bottom-right cell instead of hanging below with a gap beside it. */

.ac-card--tile {
  min-height: 232px;
  background: var(--midnight);
}
.ac-card--tile .ac-card__title { font-size: 16px; line-height: 22px; }
.ac-card--tile .ac-card__copy  { font-size: 14px; line-height: 22px; }
.ac-card--tile:hover { border-color: rgba(143,179,255,.34); }

.ac-card__media, .ac-card__media .ac-slot, .ac-card__media .ac-img {
  height: 100%;
}
/* Inside a card the slot fills the whole cell, so its label cannot sit in
   the middle: the card's own icon (top left) and title and copy (bottom)
   are already there. Park it in the free top-right corner, quietly. */
.ac-card__media .ac-slot {
  aspect-ratio: auto;
  place-items: start end;
  padding: var(--space-3);
}
.ac-card__media .ac-slot__inner {
  padding: 6px 10px; gap: 0;
  background: rgba(6,18,43,.72);
  align-items: flex-end; text-align: right;
}
.ac-card__media .ac-slot__name { font-size: 10px; line-height: 14px; font-weight: 600; }
.ac-card__media .ac-slot__size { font-size: 9px; line-height: 13px; letter-spacing: .06em; }
.ac-card__media .ac-slot__icon { display: none; }
.ac-card__media .ac-slot__note { display: none; }
/* The feature card is large enough to carry the full label, centred. */
.ac-card--feature .ac-card__media .ac-slot { place-items: center; padding: var(--space-4); }
.ac-card--feature .ac-card__media .ac-slot__inner {
  padding: var(--space-4) var(--space-6); gap: 2px;
  align-items: center; text-align: center;
  background: rgba(6,18,43,.55);
}
.ac-card--feature .ac-card__media .ac-slot__icon { display: block; }
.ac-card--feature .ac-card__media .ac-slot__note { display: block; }
.ac-card--feature .ac-card__media .ac-slot__name { font-size: 13px; line-height: 18px; font-weight: 700; }
.ac-card--feature .ac-card__media .ac-slot__size { font-size: 12px; line-height: 16px; letter-spacing: .08em; }

@media (max-width: 960px) {
  .ac-bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ac-card--feature { grid-column: span 2; grid-row: auto; min-height: 400px; }
}
@media (max-width: 600px) {
  .ac-bento { grid-template-columns: 1fr; }
  .ac-card--feature { grid-column: span 1; }
  .ac-card--feature { min-height: 340px; }
  .ac-card--tile { min-height: 0; }
}

/* .ac-proof was a bordered card here. The eight proof points now run as a
   hairline list instead (see "Proof points" further down), so the card rule
   is gone rather than being half-overridden from two places. */

.ac-industry{position:relative;border-radius:var(--radius-md);overflow:hidden;min-height:260px;display:flex;align-items:flex-end;background:var(--midnight)}
.ac-industry__overlay{position:absolute;inset:0;background:var(--navy);opacity:var(--overlay-photo)}
.ac-industry__body{position:relative;padding:var(--space-6);display:flex;flex-direction:column;gap:var(--space-2)}
.ac-industry__title{font-size:20px;line-height:28px;font-weight:600;color:var(--on-dark);margin:0}
.ac-industry__copy{font-size:14px;line-height:22px;color:var(--on-dark-muted);margin:0}

/* ==========================================================================
   Image slots
   No photography exists yet (the brief calls for a half-day shoot), so
   ac_image() renders one of these instead: a correctly-proportioned box
   that names the file and the pixel size it is holding open. Drop that file
   into public/assets/img/ and the slot is replaced by a real <img> with no
   code change (see resources/allied-media.php).

   The slot and the finished <img> occupy identical space, because both are
   sized from the same width/height. That is what keeps layout shift at zero
   while photographs land one at a time.
   ========================================================================== */
.ac-img { display: block; width: 100%; height: 100%; object-fit: cover; }

.ac-slot {
  position: relative;
  width: 100%;
  display: grid; place-items: center;
  padding: var(--space-4);
  color: var(--signal-soft);
  background:
    radial-gradient(120% 90% at 78% 12%, rgba(20,99,255,.30) 0%, rgba(20,99,255,0) 58%),
    linear-gradient(145deg, #12294f 0%, var(--navy) 46%, var(--midnight) 100%);
}
/* Graph-paper wash, so a slot reads as "reserved space" rather than as a
   dark panel someone forgot to fill. */
.ac-slot::after {
  content: ""; position: absolute; inset: 0; opacity: .45; pointer-events: none;
  background-image:
    linear-gradient(rgba(143,179,255,.12) 1px, transparent 1px),
    linear-gradient(90deg, rgba(143,179,255,.12) 1px, transparent 1px);
  background-size: 34px 34px;
}
.ac-slot__inner {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  text-align: center; line-height: 1.35;
  padding: var(--space-4) var(--space-6);
  border: 1px dashed rgba(143,179,255,.45);
  border-radius: var(--radius-sm);
  background: rgba(6,18,43,.55);
  max-width: 100%;
}
.ac-slot__icon { line-height: 0; opacity: .8; margin-bottom: 4px; }
.ac-slot__name {
  font-size: 13px; font-weight: 700; letter-spacing: .01em;
  color: #DCE7FF; word-break: break-all;
}
.ac-slot__size {
  font-size: 12px; font-weight: 600; letter-spacing: .08em;
  color: var(--signal-soft);
}
.ac-slot__note {
  font-size: 11px; line-height: 16px; margin-top: 4px;
  color: rgba(184,196,220,.85); max-width: 26ch;
}
/* In the tightest slots (partner marks, small tiles) the note and icon are
   noise. Keep the filename and the size, drop the rest. */
.ac-slot--compact .ac-slot__icon,
.ac-slot--compact .ac-slot__note { display: none; }

/* ==========================================================================
   Header
   ========================================================================== */
.ac-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.ac-header__bar {
  display: flex; align-items: center; gap: var(--space-4);
  /* 80px is the ceiling for a desktop nav and the lockup needs it. Keep
     --header-h in sync or the 100dvh fold stops landing flush. */
  min-height: 80px;
}
/* The brand is the supplied lockup now, not type plus a monogram tile, so
   .ac-brand is just a sized, clickable box around an image. The old
   .ac-brand__mark rule went with the markup it styled. */
.ac-brand {
  display: inline-flex; align-items: center;
  text-decoration: none; line-height: 0;
}
/* Height drives it and width follows the intrinsic 249x133 ratio, so the
   lockup can never be stretched by a container.

   54px is set by legibility, not by taste: this is a stacked lockup and
   the COMPUTERS line is only about a sixth of its height, so at 48px that
   line fell to roughly 8px and went mushy on a 1x screen. */
.ac-brand__logo {
  height: 54px; width: auto; display: block;
}
@media (max-width: 480px) {
  .ac-brand__logo { height: 40px; }
}
.ac-nav { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }
.ac-nav__link {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 10px 12px; border-radius: var(--radius-sm);
  font-size: 15px; line-height: 20px; font-weight: 600;
  color: var(--ink); text-decoration: none; background: none; border: 0;
  font-family: var(--font-sans); cursor: pointer; white-space: nowrap;
}
.ac-nav__link:hover { color: var(--signal); }
.ac-nav__link[aria-current="page"] { color: var(--signal); }
.ac-nav__chev { transition: transform .15s ease; }
.ac-nav__utility {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 14px; font-weight: 600; color: var(--ink-body); text-decoration: none;
  padding-inline: var(--space-2); white-space: nowrap;
}
.ac-nav__utility:hover { color: var(--signal); }

/* Nav items must never wrap: a two-line "Services & Support" breaks the
   header bar's rhythm. Between the mobile breakpoint and ~1260px there is
   not room for the phone number too, so it drops out there — it is still
   in the CTA band and the footer. */
.ac-nav__link, .ac-nav .ac-btn, .ac-nav__utility { white-space: nowrap; }
@media (min-width: 1041px) and (max-width: 1260px) {
  .ac-nav__utility { display: none; }
  .ac-header__bar { gap: var(--space-4); }
}

/* --- Solutions mega menu (CSS/JS-light: details+summary would break the
       two-level keyboard model, so this uses a button + JS toggle) --- */
/* The panel is centred on the HEADER, not on its trigger: a panel centred
   on the "Solutions" button overflows the left edge of the viewport. The
   header is position:sticky, so it is the containing block here. */
.ac-has-mega { position: static; }
.ac-mega {
  position: absolute; left: 50%; transform: translateX(-50%);
  top: calc(100% + 8px);
  width: min(1100px, calc(100vw - 48px));
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: var(--space-8) var(--space-6);
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-8) var(--space-6);
}
.ac-mega[hidden] { display: none; }
.ac-mega__col h3 {
  font-size: 13px; line-height: 18px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink); margin: 0 0 var(--space-3);
  padding-bottom: var(--space-2); border-bottom: 1px solid var(--line);
}
.ac-mega__col a {
  display: block; padding: 7px 0;
  font-size: 14px; line-height: 22px; color: var(--ink-body); text-decoration: none;
}
.ac-mega__col a:hover { color: var(--signal); }

/* --- Mobile nav --- */
.ac-burger {
  display: none; margin-left: auto;
  width: 42px; height: 42px; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--surface);
  color: var(--ink); cursor: pointer; place-items: center;
}
@media (max-width: 1040px) {
  .ac-burger { display: grid; }
  .ac-nav {
    display: none; position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--surface); border-bottom: 1px solid var(--line);
    padding: var(--space-4) var(--space-6) var(--space-6);
    max-height: calc(100vh - var(--header-h)); overflow-y: auto;
  }
  .ac-nav[data-open="true"] { display: flex; }
  .ac-nav__link { padding: 12px 0; justify-content: space-between; white-space: normal; }
  .ac-nav .ac-btn { white-space: normal; }
  .ac-nav .ac-btn { margin-top: var(--space-3); justify-content: center; }
  .ac-has-mega { position: static; }
  .ac-mega {
    position: static; transform: none; width: auto;
    border: 0; box-shadow: none; padding: 0 0 var(--space-4);
    grid-template-columns: 1fr; gap: var(--space-6);
  }
  .ac-nav__utility { padding: 12px 0; }
}

/* ==========================================================================
   Hero
   ========================================================================== */
.ac-hero {
  position: relative; isolation: isolate;
  background: var(--navy); color: var(--on-dark);
  overflow: hidden;
}
/* Two washes over the navy: a signal-blue glow behind the photograph, and a
   faint grid that ties the hero to the image slots below it. Cheap (no
   image request) and it stops the panel reading as a flat rectangle. */
.ac-hero::before {
  content: ""; position: absolute; inset: 0; z-index: -2;
  background:
    radial-gradient(70% 90% at 82% 8%, rgba(20,99,255,.38) 0%, rgba(20,99,255,0) 62%),
    radial-gradient(60% 70% at 4% 96%, rgba(20,99,255,.16) 0%, rgba(20,99,255,0) 60%);
}
.ac-hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1; opacity: .5;
  background-image:
    linear-gradient(rgba(143,179,255,.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(143,179,255,.07) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: linear-gradient(180deg, #000 0%, transparent 78%);
}

/* Asymmetric on purpose: the copy column is the wider one. */
.ac-hero__grid {
  /* Was 1.12fr .88fr. The copy column only needs to clear the h1's own
     26ch cap (about 570px at this scale), so the surplus goes to the
     photograph rather than sitting as dead measure next to the headline. */
  display: grid; grid-template-columns: 1.04fr .96fr;
  gap: var(--space-12); align-items: center;
  width: 100%;
  /* Inside .ac-fold the hero is a flex child that centres its own content,
     so this is breathing room rather than the thing setting hero height.
     Capped well under the 96px maximum: more than that and the copy starts
     floating down the screen instead of sitting in it. */
  padding-block: var(--space-20) var(--space-12);
}
.ac-hero__eyebrow { color: var(--signal-soft); }
/* Scale and measure are planned together: six words at this size break to
   exactly two lines at the column width, which is the hero rule. Widen the
   measure or drop the size if the headline copy ever grows. */
.ac-hero h1 {
  font-size: clamp(32px, 3.1vw, 40px); line-height: 1.12; font-weight: 700;
  letter-spacing: -.02em;
  color: var(--on-dark); margin: var(--space-4) 0 var(--space-6);
  max-width: 26ch;
}
.ac-hero__sub {
  font-size: 18px; line-height: 30px; color: var(--on-dark-muted);
  margin: 0 0 var(--space-8); max-width: 52ch;
}
.ac-hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-4); }

.ac-hero__figure { position: relative; }
.ac-hero__frame {
  border-radius: var(--radius-md); overflow: hidden;
  background: var(--midnight);
  /* The 1px inner ring matters before the photograph lands: without it the
     placeholder slot is nearly the same navy as the hero, the frame has no
     visible edge, and the badge overlapping its corner reads as a badge
     floating in empty space. */
  box-shadow: 0 24px 70px rgba(3,10,26,.55),
              inset 0 0 0 1px rgba(143,179,255,.22);
}
/* The founding credential, overlapping the photograph's lower-left corner.
   Real figure, computed from the founding year in allied-site.php. */
.ac-hero__badge {
  position: absolute; left: calc(var(--space-6) * -1); bottom: calc(var(--space-6) * -1);
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  background: var(--surface); border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}
.ac-hero__badge-num {
  font-size: 34px; line-height: 1; font-weight: 700; letter-spacing: -.02em;
  color: var(--signal);
}
.ac-hero__badge-label {
  font-size: 13px; line-height: 18px; font-weight: 600; color: var(--ink);
}

@media (max-width: 960px) {
  .ac-hero__grid {
    grid-template-columns: 1fr; gap: var(--space-8);
    padding-block: 56px 116px;
  }
  .ac-hero h1 { max-width: none; }
  .ac-hero__figure { max-width: 560px; }
  .ac-hero__badge { left: var(--space-4); bottom: calc(var(--space-4) * -1); }
}
@media (max-width: 640px) {
  .ac-hero__sub { font-size: 16px; line-height: 26px; }
  .ac-hero__badge { padding: var(--space-3) var(--space-4); }
  .ac-hero__badge-num { font-size: 26px; }
}

/* ==========================================================================
   Credentials band
   Four standing credentials as ONE divided object rather than four cards
   floating over the hero. Hairline rules between columns, flush under the
   hero, no shadow. Fewer edges, less template.
   ========================================================================== */
.ac-credentials { background: var(--surface); border-bottom: 1px solid var(--line); }
.ac-credentials__row {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
}
.ac-credential {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-6) var(--space-6) var(--space-6) 0;
}
.ac-credential + .ac-credential {
  border-left: 1px solid var(--line);
  padding-left: var(--space-6);
}
.ac-credential__icon {
  flex: 0 0 auto; width: 36px; height: 36px; border-radius: var(--radius-full);
  background: var(--sky); color: var(--signal);
  display: grid; place-items: center;
}
.ac-credential__label {
  font-size: 14px; line-height: 20px; font-weight: 600; color: var(--ink);
}
@media (max-width: 860px) {
  .ac-credentials__row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ac-credential { padding: var(--space-4) var(--space-4) var(--space-4) 0; }
  /* Re-draw the rules for a 2-up grid: left rule on the right-hand column,
     top rule on the second row. */
  .ac-credential + .ac-credential { border-left: 0; padding-left: 0; }
  .ac-credential:nth-child(2n) { border-left: 1px solid var(--line); padding-left: var(--space-4); }
  .ac-credential:nth-child(n+3) { border-top: 1px solid var(--line); }
}
@media (max-width: 520px) {
  .ac-credentials__row { grid-template-columns: 1fr; }
  .ac-credential:nth-child(2n) { border-left: 0; padding-left: 0; }
  .ac-credential + .ac-credential { border-top: 1px solid var(--line); }
}

/* ==========================================================================
   Experience That Delivers
   ========================================================================== */
.ac-split {
  display: grid; grid-template-columns: .92fr 1.08fr;
  gap: var(--space-20); align-items: center;
}
.ac-split__figure { position: relative; }
.ac-split__frame {
  border-radius: var(--radius-md); overflow: hidden; background: var(--midnight);
  box-shadow: 0 18px 50px rgba(11,27,63,.18);
}
/* Office count, overlapping the photograph's lower-right corner. Mirrors the
   hero badge so the two read as the same device, flipped. */
.ac-split__badge {
  position: absolute; right: calc(var(--space-6) * -1); bottom: calc(var(--space-6) * -1);
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  background: var(--navy); color: var(--on-dark);
  border-radius: var(--radius-md); box-shadow: 0 12px 34px rgba(11,27,63,.32);
}
.ac-split__badge-num {
  font-size: 30px; line-height: 1; font-weight: 700; letter-spacing: -.02em;
  color: var(--signal-soft);
}
.ac-split__badge-label { font-size: 13px; line-height: 18px; font-weight: 600; max-width: 9ch; }

.ac-split__body .ac-section-header { text-align: left; margin: 0; max-width: none; }
.ac-split__body p { font-size: 18px; line-height: 30px; color: var(--ink-body); }
.ac-split__body p + p { font-size: 16px; line-height: 26px; }
@media (max-width: 960px) {
  .ac-split { grid-template-columns: 1fr; gap: var(--space-12); }
  .ac-split__figure { max-width: 560px; }
  .ac-split__badge { right: var(--space-4); }
}
@media (max-width: 560px) {
  .ac-split__badge { right: var(--space-3); bottom: calc(var(--space-4) * -1); padding: var(--space-3) var(--space-4); }
  .ac-split__badge-num { font-size: 24px; }
}

/* --------------------------------------------------------------------------
   Proof points
   Eight of them. As eight bordered boxes they read as a spec dump, so they
   run as a hairline list instead: one rule above each row, none below, two
   columns on desktop. Lighter than cards and it lets the split above stay
   the section's focal point.
   -------------------------------------------------------------------------- */
.ac-proof-list {
  list-style: none; margin: var(--space-20) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--space-12); row-gap: 0;
}
.ac-proof {
  display: flex; align-items: flex-start; gap: var(--space-4);
  padding-block: var(--space-6);
  border-top: 1px solid var(--line);
}
.ac-proof__well {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: var(--radius-full);
  background: var(--sky); color: var(--signal);
  display: grid; place-items: center;
}
.ac-proof__title { font-size: 16px; line-height: 24px; font-weight: 600; color: var(--ink); margin: 0 0 2px; }
.ac-proof__copy  { font-size: 14px; line-height: 22px; color: var(--ink-body); margin: 0; }
@media (max-width: 760px) {
  .ac-proof-list { grid-template-columns: 1fr; margin-top: var(--space-12); }
}

/* ==========================================================================
   Industry experience
   ========================================================================== */
/* ==========================================================================
   Logo walls (technology partners, clients)
   A grid on desktop. On narrow screens allied.js clones the track and the
   row becomes an auto-scrolling marquee, which is what the client asked
   for: eight logos will not read as a 2-up grid on a phone.

   Slots, not lettering: until a licensed mark is dropped into
   public/assets/img/partner-<slug>.svg (or client-NN) each cell names the
   file it is waiting for, so the row is never mistaken for finished work.
   ========================================================================== */
.ac-logos { position: relative; }
.ac-logos__track {
  list-style: none; margin: var(--space-12) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-4);
}
.ac-logo {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; text-align: center;
  aspect-ratio: 200 / 64; padding: var(--space-3);
  border: 1px dashed var(--line); border-radius: var(--radius-md);
  background: var(--surface);
  transition: border-color .15s ease, background .15s ease;
}
.ac-section--cloud .ac-logo { background: var(--surface); }
.ac-logo:hover { border-color: var(--signal-soft); background: var(--sky); }
.ac-logo__name { font-size: 15px; line-height: 20px; font-weight: 700; color: var(--ink); }
.ac-logo__slot {
  font-size: 10px; line-height: 14px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-muted);
}
/* Once the real mark lands the dashed holder goes with it. */
.ac-logo:has(.ac-logo__img) { border-style: solid; border-color: var(--line); }
.ac-logo__img {
  width: auto; max-width: 100%; height: auto; max-height: 48px; object-fit: contain;
  filter: grayscale(1); opacity: .75;
  transition: filter .15s ease, opacity .15s ease;
}
.ac-logo:hover .ac-logo__img { filter: grayscale(0); opacity: 1; }

@media (max-width: 860px) { .ac-logos__track { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* --- Marquee mode (mobile) ---
   allied.js adds .is-marquee and a cloned, aria-hidden track. Both tracks
   translate by exactly -100% of one track's width, so the loop is seamless.
   Only transform animates, so it stays on the compositor. */
@media (max-width: 720px) {
  .ac-logos__track { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .ac-logos.is-marquee {
    display: flex; gap: var(--space-4);
    overflow: hidden; margin-top: var(--space-12);
    /* Fade the two ends so logos enter and leave rather than being cut. */
    mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  }
  .ac-logos.is-marquee .ac-logos__track {
    display: flex; flex: 0 0 auto; gap: var(--space-4);
    margin: 0; width: max-content;
    animation: ac-marquee 28s linear infinite;
  }
  .ac-logos.is-marquee .ac-logo { flex: 0 0 148px; width: 148px; }
  .ac-logos.is-marquee:hover .ac-logos__track,
  .ac-logos.is-marquee:focus-within .ac-logos__track { animation-play-state: paused; }
}
@keyframes ac-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-100% - var(--space-4))); }
}
/* Motion is decoration here, so it stops entirely rather than degrading. */
@media (prefers-reduced-motion: reduce) {
  .ac-logos.is-marquee .ac-logos__track { animation: none; }
  .ac-logos.is-marquee { overflow-x: auto; }
}

/* ==========================================================================
   CTA band
   The one centred section on the page: here the message IS the section,
   so centring it is a decision rather than a default.
   ========================================================================== */
.ac-cta { background: var(--navy); color: var(--on-dark-muted); }
.ac-cta__inner { max-width: 820px; margin: 0 auto; text-align: center; }
.ac-cta h2 {
  font-size: 40px; line-height: 46px; font-weight: 700; letter-spacing: -.015em;
  color: var(--on-dark); margin: 0 0 var(--space-4);
}
.ac-cta p { font-size: 18px; line-height: 30px; margin: 0 0 var(--space-8); }
.ac-cta__actions { display: flex; flex-wrap: wrap; gap: var(--space-4); justify-content: center; }
@media (max-width: 640px) { .ac-cta h2 { font-size: 30px; line-height: 36px; } }

/* ==========================================================================
   Shop categories
   Six catalogue entry points, every one an external link to the storefront.
   Light cards on the surface: this section is a shop front, not the dark
   solutions bento, and the contrast keeps the two from blurring together.
   ========================================================================== */
.ac-shop__head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--space-8); flex-wrap: wrap;
}
.ac-shop-grid {
  list-style: none; margin: var(--space-12) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
}
/* Two bands: photograph on top, copy on solid ground beneath. The
   solutions bento above uses the opposite anatomy (copy over a scrim on
   the photograph itself), which is what keeps two photo-led card sections
   on one page from reading as the same section twice.

   The category icon straddles the seam between the two bands, so the card
   still has a focal point while the photography is missing. */
.ac-shop-card {
  display: flex; flex-direction: column; height: 100%;
  border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--surface); text-decoration: none; overflow: hidden;
  transition: border-color .2s ease, transform .25s cubic-bezier(.16,1,.3,1), box-shadow .25s ease;
}
.ac-shop-card:hover {
  border-color: var(--signal-soft);
  transform: translateY(-3px);
  box-shadow: 0 14px 34px rgba(11,27,63,.14);
}
.ac-shop-card:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }

.ac-shop-card__band {
  position: relative; display: block; overflow: hidden;
  background: var(--midnight);
}
.ac-shop-card__band .ac-img { aspect-ratio: 16 / 9; }
.ac-shop-card__band .ac-slot { aspect-ratio: 16 / 9; }
.ac-shop-card__band .ac-img { transition: transform .5s ease; }
.ac-shop-card:hover .ac-shop-card__band .ac-img { transform: scale(1.04); }

.ac-shop-card__body {
  display: flex; flex-direction: column; flex: 1 1 auto;
  padding: 0 var(--space-6) var(--space-6);
}
/* Straddles the seam: pulled up out of the body so half of it sits over
   the photograph. In flow rather than absolutely placed, because the band
   clips its own contents. */
.ac-shop-card__icon {
  /* Positioned so it paints above the band. The band is position:relative
     for its own overflow clipping, and a positioned element paints over
     static in-flow content no matter the DOM order, so a static icon here
     loses its top half behind the photograph. */
  position: relative; z-index: 1;
  width: 48px; height: 48px; border-radius: var(--radius-full);
  background: var(--surface); color: var(--signal);
  display: grid; place-items: center;
  margin: -24px 0 var(--space-4);
  box-shadow: 0 4px 14px rgba(11,27,63,.18);
  border: 1px solid var(--line);
}
.ac-shop-card__title {
  font-size: 17px; line-height: 24px; font-weight: 700; color: var(--ink);
  margin: 0 0 var(--space-2);
}
.ac-shop-card__copy {
  font-size: 14px; line-height: 22px; color: var(--ink-body);
  margin: 0 0 var(--space-6); flex: 1 1 auto;
}
.ac-shop-card__link {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 15px; font-weight: 600; color: var(--signal);
}
@media (max-width: 960px) { .ac-shop-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .ac-shop-grid { grid-template-columns: 1fr; } }

/* ==========================================================================
   About page — proof points and offices
   ========================================================================== */
.ac-proof-list {
  list-style: none; margin: var(--space-12) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--space-12); row-gap: 0;
  counter-reset: none;
}
.ac-proof {
  display: flex; align-items: flex-start; gap: var(--space-4);
  padding-block: var(--space-6);
  border-top: 1px solid var(--line);
}
.ac-proof__num {
  flex: 0 0 auto; width: 40px;
  font-size: 13px; font-weight: 700; letter-spacing: .08em;
  color: var(--signal-soft); padding-top: 3px;
}
.ac-proof__body { min-width: 0; }
.ac-proof__title {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: 16px; line-height: 24px; font-weight: 600; color: var(--ink);
  margin: 0 0 2px;
}
.ac-proof__icon { color: var(--signal); line-height: 0; }
.ac-proof__copy { font-size: 14px; line-height: 22px; color: var(--ink-body); margin: 0; }
@media (max-width: 760px) { .ac-proof-list { grid-template-columns: 1fr; } }

.ac-office-grid {
  list-style: none; margin: var(--space-12) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
}
.ac-office-card {
  padding: var(--space-6);
  border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--cloud);
}
.ac-office-card__icon {
  width: 38px; height: 38px; border-radius: var(--radius-full);
  background: var(--sky); color: var(--signal);
  display: grid; place-items: center; margin-bottom: var(--space-4);
}
.ac-office-card__city { font-size: 16px; line-height: 24px; font-weight: 700; color: var(--ink); margin: 0 0 4px; }
.ac-office-card__address { font-size: 14px; line-height: 22px; color: var(--ink-body); margin: 0 0 var(--space-3); }
.ac-office-card__phone {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 14px; font-weight: 600; color: var(--signal); text-decoration: none;
}
@media (max-width: 860px) { .ac-office-grid { grid-template-columns: 1fr; } }

.ac-attribution {
  text-align: center; font-size: 13px; color: var(--ink-muted);
  padding-block: var(--space-8); margin: 0;
}

/* A plain inline link in body copy, with the arrow shifting on hover. */
.ac-textlink {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 16px; font-weight: 600; color: var(--signal); text-decoration: none;
}
.ac-textlink svg { transition: transform .2s ease; }
.ac-textlink:hover { color: var(--signal-hover); }
.ac-textlink:hover svg { transform: translateX(3px); }

.ac-section--tight { padding-bottom: var(--space-12); }

/* ==========================================================================
   Footer
   ========================================================================== */
.ac-footer { background: var(--midnight); color: var(--on-dark-muted); }
.ac-footer__grid {
  display: grid; grid-template-columns: 1.4fr 1fr 1fr 1.3fr;
  gap: var(--space-8) var(--space-6);
  padding-block: var(--space-20) var(--space-12);
}
.ac-footer__brand {
  display: inline-flex; align-items: center;
  text-decoration: none; line-height: 0;
}
/* Slightly larger than the header: the footer has the room, and this is
   the last time the mark is seen on the page. */
.ac-brand__logo--footer { height: 56px; }
.ac-footer p { font-size: 14px; line-height: 22px; margin: var(--space-4) 0 0; }
.ac-footer__signature {
  color: var(--signal-soft); font-weight: 600; font-style: italic;
}
.ac-footer h2 {
  font-size: 13px; line-height: 18px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--on-dark); margin: 0 0 var(--space-4);
}
.ac-footer a { color: var(--on-dark-muted); text-decoration: none; }
.ac-footer a:hover { color: var(--on-dark); }
.ac-footer__col a { display: block; font-size: 14px; line-height: 22px; padding-block: 5px; }
.ac-office { font-size: 14px; line-height: 22px; margin-bottom: var(--space-4); }
.ac-office strong { display: block; color: var(--on-dark); font-weight: 600; }
.ac-footer__bar {
  border-top: 1px solid rgba(184,196,220,.18);
  padding-block: var(--space-6);
  display: flex; flex-wrap: wrap; gap: var(--space-4);
  align-items: center; justify-content: space-between;
  font-size: 14px;
}
.ac-footer__legal { display: flex; flex-wrap: wrap; gap: var(--space-4); }
@media (max-width: 960px) { .ac-footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .ac-footer__grid { grid-template-columns: 1fr; padding-block: var(--space-12); } }

/* ==========================================================================
   Inner pages — page head and prose
   ========================================================================== */
.ac-pagehead {
  background: var(--navy); color: var(--on-dark-muted);
  padding-block: var(--space-20) var(--space-12);
}
.ac-pagehead h1 {
  font-size: 40px; line-height: 46px; font-weight: 700; letter-spacing: -.015em;
  color: var(--on-dark); margin: var(--space-4) 0 var(--space-3);
}
.ac-pagehead__lead { font-size: 18px; line-height: 30px; margin: 0; max-width: 680px; }
@media (max-width: 640px) {
  .ac-pagehead { padding-block: var(--space-12) var(--space-8); }
  .ac-pagehead h1 { font-size: 30px; line-height: 36px; }
}

.ac-prose { max-width: 760px; }
.ac-prose h2 {
  font-size: 28px; line-height: 34px; font-weight: 700; letter-spacing: -.01em;
  color: var(--ink); margin: var(--space-12) 0 var(--space-3);
}
.ac-prose h2:first-child { margin-top: 0; }
.ac-prose h2 a { color: inherit; text-decoration: none; }
.ac-prose h2 a:hover { color: var(--signal); }
.ac-prose p { font-size: 16px; line-height: 26px; color: var(--ink-body); margin: 0 0 var(--space-4); }
.ac-prose a { color: var(--signal); }
.ac-prose a:hover { color: var(--signal-hover); }

/* Marks copy that is not ready to ship. Remove the element, not the style,
   when the real text lands. */
.ac-notice {
  background: var(--sky); border-left: 3px solid var(--signal);
  border-radius: var(--radius-sm);
  padding: var(--space-4) var(--space-6);
  color: var(--ink) !important;
}

/* ==========================================================================
   Section headers — left-aligned variant
   The centred header is kept for the CTA band, where the message is the
   whole section. Everywhere else the header sits left, so the page has a
   reading edge instead of seven centred blocks stacked down the middle.
   ========================================================================== */
.ac-section-header--start { text-align: left; margin-inline: 0; max-width: 46ch; }
.ac-section-header--start h2 { max-width: 20ch; }

/* ==========================================================================
   Motion — MOTION_INTENSITY 4
   One device only: content rises into place as it enters the viewport.
   Driven by IntersectionObserver in allied.js (never a scroll listener),
   and only transform/opacity animate, so it stays on the compositor.

   The .ac-reveal class does nothing until JS adds data-reveal="ready" to
   <html>. With JS off or blocked, every element renders in its final state
   rather than staying invisible, which is the failure mode that matters.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  [data-reveal="ready"] .ac-reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity .6s cubic-bezier(.16, 1, .3, 1),
                transform .6s cubic-bezier(.16, 1, .3, 1);
  }
  [data-reveal="ready"] .ac-reveal.is-visible {
    opacity: 1;
    transform: none;
  }
  /* Tiles in a grid arrive in sequence rather than all at once, so the eye
     is led across the bento instead of being hit with six cards at a time. */
  [data-reveal="ready"] .ac-bento .ac-reveal:nth-child(2)  { transition-delay: .06s; }
  [data-reveal="ready"] .ac-bento .ac-reveal:nth-child(3)  { transition-delay: .12s; }
  [data-reveal="ready"] .ac-bento .ac-reveal:nth-child(4)  { transition-delay: .18s; }
  [data-reveal="ready"] .ac-bento .ac-reveal:nth-child(5)  { transition-delay: .24s; }
  [data-reveal="ready"] .ac-bento .ac-reveal:nth-child(6)  { transition-delay: .30s; }
}

/* Hover feedback on the cards: a small lift, tinted to the page ground
   rather than a black drop shadow. */
.ac-card { transition: transform .25s cubic-bezier(.16, 1, .3, 1), box-shadow .25s ease; }
.ac-card:hover { transform: translateY(-4px); box-shadow: 0 18px 44px rgba(11,27,63,.28); }
.ac-btn:active { transform: translateY(1px); }

@media (prefers-reduced-motion: reduce) {
  .ac-card, .ac-btn, .ac-industry .ac-img, .ac-card__media .ac-img { transition: none; }
  .ac-card:hover { transform: none; }
  .ac-industry:hover .ac-img { transform: none; }
}

/* ==========================================================================
   Button colour lock
   app.css (PlugPHP's original stylesheet) carries `a:hover{color:...}`.
   That selector scores 0,1,1 and .ac-btn--primary only scores 0,1,0, so on
   hover every Allied button was repainting its label in PlugPHP's accent
   colour: unreadable text on a blue background. These rules pin the label
   colour for every state of every button variant.

   Do not "simplify" them back to a single .ac-btn rule. The specificity is
   the point: each selector here has to out-score a bare a:hover.
   ========================================================================== */
.ac-btn--primary,
.ac-btn--primary:link,
.ac-btn--primary:visited,
.ac-btn--primary:hover,
.ac-btn--primary:focus,
.ac-btn--primary:active { color: var(--on-dark); }

.ac-btn--on-dark,
.ac-btn--on-dark:link,
.ac-btn--on-dark:visited,
.ac-btn--on-dark:hover,
.ac-btn--on-dark:focus,
.ac-btn--on-dark:active { color: var(--on-dark); }

/* The ghost button had no hover state at all. A translucent white fill
   reads as pressed against navy without swapping to a light background,
   which would flip the label to dark mid-interaction. */
.ac-btn--on-dark:hover { background: rgba(255, 255, 255, .14); }

/* Secondary sits on light ground: navy label at rest, and on hover it
   becomes the solid blue button, so the label goes white with it. */
.ac-btn--secondary,
.ac-btn--secondary:link,
.ac-btn--secondary:visited { color: var(--navy); }
.ac-btn--secondary:hover,
.ac-btn--secondary:focus,
.ac-btn--secondary:active {
  background: var(--signal);
  border-color: var(--signal);
  color: var(--on-dark);
}

/* Same fix for the card and shop links, which are also anchors. */
.ac-card__link, .ac-card:hover .ac-card__link { color: var(--on-dark); }
.ac-shop-card__link, .ac-shop-card:hover .ac-shop-card__link { color: var(--signal); }
.ac-shop-card:hover .ac-arrow { background: var(--signal-hover); transform: translateX(3px); }

/* The footer build credit. */
.ac-footer__credit { color: var(--on-dark-muted); }
.ac-footer__credit a { color: var(--on-dark); font-weight: 600; }
.ac-footer__credit a:hover { color: var(--signal-soft); }

/* A blue-tinted shadow under a blue button reads as elevation on a light
   ground and as a neon glow on a navy one. On the dark sections the lift
   is carried by a tight contact shadow instead, so the CTA still sits
   above the surface without haloing. */
.ac-hero .ac-btn--primary,
.ac-cta .ac-btn--primary {
  box-shadow: inset 0 1px 0 rgba(255,255,255,.26),
              0 2px 6px rgba(3,10,26,.45);
}
.ac-hero .ac-btn--primary:hover,
.ac-cta .ac-btn--primary:hover {
  box-shadow: inset 0 1px 0 rgba(255,255,255,.26),
              0 6px 16px rgba(3,10,26,.55);
}
.ac-hero .ac-btn--primary:active,
.ac-cta .ac-btn--primary:active {
  box-shadow: inset 0 1px 2px rgba(3,10,26,.5);
}

/* ==========================================================================
   The fold
   Hero and credentials band are one screen, so they are measured as one.
   The wrapper claims exactly one viewport minus the sticky header, the hero
   takes whatever height is left after the band, and the band lands flush on
   the fold line. Previously the hero carried a fixed 124px bottom padding
   and the first screen ended on a strip of empty ground below the band.

   dvh, not vh: on mobile browsers vh is the tallest viewport (address bar
   retracted), so a 100vh fold is taller than what the user can actually see
   and the bottom is cut off until they scroll.
   ========================================================================== */
@media (min-width: 961px) {
  .ac-fold {
    display: flex;
    flex-direction: column;
    min-height: calc(100vh - var(--header-h));
    min-height: calc(100dvh - var(--header-h));
  }
  /* Grows into the leftover space and centres the hero grid inside it. */
  .ac-fold .ac-hero { flex: 1 1 auto; display: flex; align-items: center; }
  /* Never squeezed: the band is the fold line. */
  .ac-fold .ac-credentials { flex: 0 0 auto; }
}

/* Below 961px the hero copy plus four stacked credentials is taller than a
   viewport. Forcing them into one would push the CTA below the fold, which
   is the opposite of the point, so there the two sections simply flow. */

/* ==========================================================================
   Header: centred navigation
   Three columns, the outer two equal, so the menu is centred on the header
   itself rather than on whatever space the wordmark and button leave over.
   Equal 1fr tracks are what make it truly centred: sizing the outer columns
   to their content would push the menu off-centre by the difference between
   the wordmark and the button.
   ========================================================================== */
@media (min-width: 1041px) {
  .ac-header__bar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
  }
  .ac-brand { grid-column: 1; justify-self: start; }
  .ac-nav {
    grid-column: 2; justify-self: center;
    margin-left: 0;            /* was margin-left:auto, which pinned it right */
    gap: var(--space-1);
  }
  /* allied.js lifts the CTA out of the nav at this width. Until it does (or
     if JS never runs) the button stays in the nav and the cluster centres
     as one, which is why this rule targets the bar-level child only. */
  .ac-header__bar > .ac-header__cta { grid-column: 3; justify-self: end; }
}

/* Short laptop viewports (1280x620 and friends). The fold uses min-height,
   so content always wins over the viewport rather than being clipped, but
   left alone the credentials band ends up bisected by the fold line. Pulling
   the hero's padding in and capping the figure keeps the whole first screen
   inside one viewport down to roughly 600px of height.

   Keyed on height, not width: a 1440x640 window has the same problem as a
   1280x640 one, and a width query would miss it. */
@media (min-width: 961px) and (max-height: 820px) {
  .ac-hero__grid { padding-block: var(--space-12) var(--space-8); }
  /* 420px here was throttling the hero image on an ordinary 1280x800
     laptop, where the hero still had ~240px of unused vertical slack. The
     cap exists to protect the fold on genuinely short screens, so it is set
     to the widest the column ever gets at this height instead. */
  .ac-hero__figure { max-width: 560px; margin-left: auto; }
}
@media (min-width: 961px) and (max-height: 680px) {
  .ac-hero__grid { padding-block: var(--space-8); gap: var(--space-8); }
  .ac-hero__figure { max-width: 420px; }
  .ac-hero h1 { font-size: clamp(30px, 2.6vw, 34px); }
  .ac-hero__sub { margin-bottom: var(--space-6); }
}

/* The Solutions and Services triggers are <button>s carrying an inline
   chevron <span>. An inline box reserves descender space, so those two sat
   2px taller than the plain <a> items and the row was a pixel out of
   alignment. Zeroing the line box on the chevron makes every nav item the
   same height. More visible now the menu is centred rather than tucked
   against the right edge. */
.ac-nav__chev { display: inline-flex; line-height: 0; }
.ac-nav__link { line-height: 20px; }

/* ==========================================================================
   About page
   ========================================================================== */

/* --- Hero: copy over a photograph ---------------------------------------
   The reference layout puts the picture behind the words, not under them,
   so the first screen is one object. The scrim is the load-bearing part:
   white text over an uncontrolled photograph fails contrast the moment a
   bright frame is dropped in, so the navy wash is strong enough to hold
   AA on any image and the photo reads as atmosphere. */
.ac-pagehero {
  position: relative; isolation: isolate;
  background: var(--navy); color: var(--on-dark);
  display: flex; align-items: center;
  min-height: 460px;
  overflow: hidden;
}
.ac-pagehero__media { position: absolute; inset: 0; z-index: -2; }
.ac-pagehero__media .ac-img { width: 100%; height: 100%; object-fit: cover; }
.ac-pagehero__media .ac-slot { width: 100%; height: 100%; aspect-ratio: auto; }
.ac-pagehero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(90deg, rgba(6,18,43,.94) 0%, rgba(6,18,43,.86) 42%, rgba(11,27,63,.66) 100%),
    radial-gradient(70% 90% at 82% 8%, rgba(20,99,255,.26) 0%, rgba(20,99,255,0) 62%);
}
/* No max-width here. This element is also .ac-container, which carries
   margin-inline:auto, so narrowing it centred the whole box in the viewport
   and pushed the hero copy ~260px right of the content below it. The measure
   belongs on the text itself (h1 and sub each have their own), not on the
   container that sets the page's left gutter. */
.ac-pagehero__inner { padding-block: var(--space-20); }
.ac-pagehero h1 {
  font-size: clamp(30px, 3.2vw, 42px); line-height: 1.14; font-weight: 700;
  letter-spacing: -.02em; color: var(--on-dark);
  margin: var(--space-4) 0 var(--space-3); max-width: 20ch;
}
/* The second sentence of the headline, set as the subline: it is the turn
   the whole page rests on, so it keeps display weight rather than dropping
   to body colour. */
.ac-pagehero__sub {
  font-size: clamp(19px, 1.9vw, 23px); line-height: 1.4; font-weight: 400;
  color: var(--signal-soft); margin: 0 0 var(--space-8); max-width: 34ch;
}
@media (max-width: 640px) {
  .ac-pagehero { min-height: 0; }
  .ac-pagehero__inner { padding-block: var(--space-12); }
}

/* --- Alliance Built on Commitment ---------------------------------------
   The page's only dark section, because it is the one the strapline has to
   earn. Four commitments, no boxes: a hairline above each and space doing
   the separating. */
.ac-commitment { background: var(--navy); color: var(--on-dark-muted); }
.ac-commitment__head { max-width: 58ch; }
.ac-commitment__head h2 {
  font-size: clamp(28px, 3vw, 38px); line-height: 1.15; font-weight: 700;
  letter-spacing: -.015em; color: var(--on-dark); margin: 0 0 var(--space-3);
}
.ac-commitment__head p { font-size: 18px; line-height: 30px; margin: 0; }
.ac-commitment__grid {
  list-style: none; margin: var(--space-20) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--space-20); row-gap: 0;
}
.ac-commitment__item {
  padding-block: var(--space-8);
  border-top: 1px solid rgba(143, 179, 255, .22);
}
.ac-commitment__icon {
  width: 40px; height: 40px; border-radius: var(--radius-full);
  background: rgba(143, 179, 255, .14); color: var(--signal-soft);
  display: grid; place-items: center; margin-bottom: var(--space-4);
}
.ac-commitment__item h3 {
  font-size: 19px; line-height: 27px; font-weight: 600;
  color: var(--on-dark); margin: 0 0 var(--space-2);
}
.ac-commitment__item p { font-size: 15px; line-height: 25px; margin: 0; max-width: 46ch; }
@media (max-width: 860px) {
  .ac-commitment__grid { grid-template-columns: 1fr; margin-top: var(--space-12); }
}

/* --- Offices: three map links -------------------------------------------
   No photographs. A generic office exterior tells a visitor nothing they
   need, and the useful action here is "show me where this is", so the whole
   tile is the link and the address is the content. */
.ac-offices {
  list-style: none; margin: var(--space-12) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
}
.ac-office-tile {
  display: flex; flex-direction: column; height: 100%;
  padding: var(--space-6);
  border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--surface); text-decoration: none;
  transition: border-color .2s ease, transform .25s cubic-bezier(.16,1,.3,1), box-shadow .25s ease;
}
.ac-office-tile:hover {
  border-color: var(--signal-soft);
  transform: translateY(-3px);
  box-shadow: 0 14px 34px rgba(11,27,63,.14);
}
.ac-office-tile:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }
.ac-office-tile__icon {
  width: 42px; height: 42px; border-radius: var(--radius-full);
  background: var(--sky); color: var(--signal);
  display: grid; place-items: center; margin-bottom: var(--space-4);
  transition: background .2s ease, color .2s ease;
}
.ac-office-tile:hover .ac-office-tile__icon { background: var(--signal); color: var(--on-dark); }
.ac-office-tile__city {
  font-size: 17px; line-height: 25px; font-weight: 700; color: var(--ink);
  margin: 0 0 var(--space-2);
}
.ac-office-tile__address {
  font-size: 14px; line-height: 22px; color: var(--ink-body);
  margin: 0 0 var(--space-6); flex: 1 1 auto;
}
.ac-office-tile__link {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 15px; font-weight: 600; color: var(--signal);
}
.ac-office-tile__link svg { transition: transform .18s cubic-bezier(.16,1,.3,1); }
.ac-office-tile:hover .ac-office-tile__link svg { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) {
  .ac-office-tile, .ac-office-tile__link svg { transition: none; }
  .ac-office-tile:hover { transform: none; }
  .ac-office-tile:hover .ac-office-tile__link svg { transform: none; }
}
@media (max-width: 860px) { .ac-offices { grid-template-columns: 1fr; } }

/* --- Vision, mission, values ---------------------------------------------
   The two statements are the point, so they get display scale. The four
   values sit under them as a definition list, which is what they are. */
.ac-statements {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-12); margin-top: var(--space-12);
}
.ac-statement h3 {
  font-size: 13px; line-height: 18px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--signal); margin: 0 0 var(--space-3);
}
.ac-statement p {
  font-size: clamp(19px, 1.9vw, 23px); line-height: 1.45;
  color: var(--ink); margin: 0; max-width: 34ch;
}
@media (max-width: 860px) { .ac-statements { grid-template-columns: 1fr; gap: var(--space-8); } }

.ac-values {
  margin: var(--space-20) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--space-12); row-gap: 0;
}
.ac-value { padding-block: var(--space-6); border-top: 1px solid var(--line); }
.ac-value dt { font-size: 16px; line-height: 24px; font-weight: 700; color: var(--ink); margin: 0 0 2px; }
.ac-value dd { font-size: 14px; line-height: 22px; color: var(--ink-body); margin: 0; max-width: 52ch; }
@media (max-width: 860px) { .ac-values { grid-template-columns: 1fr; margin-top: var(--space-12); } }

/* ==========================================================================
   Inner pages: solutions, service detail, contact, blog, 404
   Everything below reuses the tokens and components already established on
   the homepage and About page. No new colours, no new radii, no new type
   sizes: the point of this pass is that the rest of the site stops looking
   like a different website.
   ========================================================================== */

.ac-container--narrow { max-width: 820px; }

/* --- Service detail: body copy with a sidebar --------------------------- */
.ac-pagehero--service .ac-pagehero__inner { padding-block: var(--space-12); }
.ac-pagehero__icon {
  display: grid; place-items: center;
  width: 52px; height: 52px; border-radius: var(--radius-full);
  background: rgba(143,179,255,.16); color: var(--signal-soft);
  margin-bottom: var(--space-4);
}
/* Back-link arrow points the way it travels, so it is flipped rather than
   given an icon of its own. */
.ac-backlink {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 14px; font-weight: 600; color: var(--signal-soft);
  text-decoration: none; margin-bottom: var(--space-6);
}
.ac-backlink svg { transform: rotate(180deg); transition: transform .18s ease; }
.ac-backlink:hover { color: var(--on-dark); }
.ac-backlink:hover svg { transform: rotate(180deg) translateX(3px); }

.ac-detail { display: grid; grid-template-columns: 1.55fr .95fr; gap: var(--space-20); align-items: start; }
.ac-detail__aside {
  padding: var(--space-6); border: 1px solid var(--line);
  border-radius: var(--radius-md); background: var(--cloud);
}
.ac-detail__aside h2 { font-size: 16px; line-height: 24px; font-weight: 700; color: var(--ink); margin: 0 0 var(--space-4); }
.ac-detail__aside ul { list-style: none; margin: 0 0 var(--space-6); padding: 0; }
.ac-detail__aside li {
  font-size: 14px; line-height: 22px; color: var(--ink-body);
  padding-block: var(--space-3); border-top: 1px solid var(--line);
}
.ac-detail__aside li:first-child { border-top: 0; padding-top: 0; }
@media (max-width: 960px) { .ac-detail { grid-template-columns: 1fr; gap: var(--space-8); } }

/* --- The other solutions, as a plain run of links ----------------------- */
.ac-otherlist {
  list-style: none; margin: var(--space-8) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--space-12);
}
.ac-otherlist__link {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-4);
  padding-block: var(--space-4); border-top: 1px solid var(--line);
  font-size: 16px; font-weight: 600; color: var(--ink); text-decoration: none;
}
.ac-otherlist__icon {
  width: 36px; height: 36px; border-radius: var(--radius-full);
  background: var(--sky); color: var(--signal); display: grid; place-items: center;
  transition: background .18s ease, color .18s ease;
}
.ac-otherlist__link svg:last-child { color: var(--signal); transition: transform .18s ease; }
.ac-otherlist__link:hover .ac-otherlist__icon { background: var(--signal); color: var(--on-dark); }
.ac-otherlist__link:hover svg:last-child { transform: translateX(3px); }
@media (max-width: 760px) { .ac-otherlist { grid-template-columns: 1fr; } }

/* --- Contact -------------------------------------------------------------
   Form left, the ways to reach a human right. The aside is the quieter of
   the two: someone who wanted to phone has already phoned. */
.ac-contact { display: grid; grid-template-columns: 1.3fr .7fr; gap: var(--space-20); align-items: start; }
.ac-contact__aside {
  padding: var(--space-6); border: 1px solid var(--line);
  border-radius: var(--radius-md); background: var(--cloud);
}
.ac-contact__aside h2 { font-size: 16px; line-height: 24px; font-weight: 700; color: var(--ink); margin: 0 0 var(--space-4); }
.ac-contact__aside h3 {
  font-size: 13px; line-height: 18px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-muted);
  margin: var(--space-6) 0 var(--space-3);
}
.ac-contact__line {
  display: flex; align-items: center; gap: var(--space-3);
  padding-block: var(--space-2);
  font-size: 15px; font-weight: 600; color: var(--ink); text-decoration: none;
  word-break: break-word;
}
.ac-contact__line:hover { color: var(--signal); }
.ac-contact__icon {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: var(--radius-full);
  background: var(--sky); color: var(--signal); display: grid; place-items: center;
}
.ac-contact__offices { list-style: none; margin: 0; padding: 0; }
.ac-contact__offices a {
  display: block; padding-block: var(--space-3);
  border-top: 1px solid var(--line); text-decoration: none;
}
.ac-contact__offices strong { display: block; font-size: 14px; color: var(--ink); }
.ac-contact__offices span { display: block; font-size: 13px; line-height: 20px; color: var(--ink-body); }
.ac-contact__offices a:hover strong { color: var(--signal); }
@media (max-width: 960px) { .ac-contact { grid-template-columns: 1fr; gap: var(--space-12); } }

/* --- Form controls -------------------------------------------------------
   Label above, hint under the label, error under the field. The border is
   the state: 1.5px at rest so the error's colour change is visible without
   the control resizing and shifting everything below it. */
.ac-form { display: flex; flex-direction: column; gap: var(--space-6); max-width: 34rem; }
.ac-field { display: flex; flex-direction: column; gap: var(--space-2); }
.ac-field label { font-size: 15px; line-height: 22px; font-weight: 600; color: var(--ink); }
.ac-field__hint { font-size: 13px; line-height: 20px; color: var(--ink-muted); margin: -2px 0 0; }
.ac-input {
  width: 100%; font-family: var(--font-sans); font-size: 16px; line-height: 24px;
  color: var(--ink); background: var(--surface);
  padding: 12px 14px;
  border: 1.5px solid var(--line); border-radius: var(--radius-sm);
  transition: border-color .15s ease, box-shadow .15s ease;
}
/* Placeholder contrast: the browser default is far below AA. There are no
   placeholders in this form by design, but any added later inherit this. */
.ac-input::placeholder { color: var(--ink-muted); opacity: 1; }
.ac-input:hover { border-color: var(--ink-muted); }
.ac-input:focus-visible {
  outline: none;
  border-color: var(--signal);
  box-shadow: 0 0 0 3px rgba(20,99,255,.22);
}
.ac-input--textarea { resize: vertical; min-height: 140px; }
.ac-input[aria-invalid="true"] { border-color: #B42318; }
.ac-input[aria-invalid="true"]:focus-visible { box-shadow: 0 0 0 3px rgba(180,35,24,.20); }
/* #B42318 on white is 5.9:1, so the error text passes AA on its own and is
   not carried by colour alone: it also sits directly under its field. */
.ac-field__error { font-size: 13px; line-height: 20px; font-weight: 600; color: #B42318; margin: 0; }

.ac-alert {
  display: flex; gap: var(--space-4); align-items: flex-start;
  padding: var(--space-6); border-radius: var(--radius-md);
  margin-bottom: var(--space-8);
}
.ac-alert__icon { flex: 0 0 auto; width: 38px; height: 38px; border-radius: var(--radius-full); display: grid; place-items: center; }
.ac-alert__title { font-size: 16px; line-height: 24px; font-weight: 700; margin: 0 0 4px; }
.ac-alert p { font-size: 14px; line-height: 22px; margin: 0 0 var(--space-3); }
.ac-alert__list { margin: 0; padding-left: 1.1em; font-size: 14px; line-height: 22px; }
.ac-alert--success { background: var(--sky); border: 1px solid var(--signal-soft); }
.ac-alert--success .ac-alert__icon { background: var(--signal); color: var(--on-dark); }
.ac-alert--success .ac-alert__title, .ac-alert--success p { color: var(--ink); }
.ac-alert--error { background: #FEF3F2; border: 1px solid #FDA29B; }
.ac-alert--error .ac-alert__icon { background: #B42318; color: #fff; }
.ac-alert--error .ac-alert__title { color: #912018; }
.ac-alert--error a { color: #912018; }

/* --- Empty states --------------------------------------------------------
   An empty screen is an invitation to act, so it names what will fill it
   and offers the next step rather than apologising. */
.ac-empty {
  text-align: center; max-width: 42ch; margin-inline: auto;
  padding-block: var(--space-20);
}
.ac-empty__icon {
  width: 56px; height: 56px; border-radius: var(--radius-full);
  background: var(--sky); color: var(--signal);
  display: grid; place-items: center; margin: 0 auto var(--space-4);
}
.ac-empty h2 { font-size: 20px; line-height: 28px; font-weight: 700; color: var(--ink); margin: 0 0 var(--space-2); }
.ac-empty p { font-size: 15px; line-height: 24px; color: var(--ink-body); margin: 0 0 var(--space-6); }

/* --- Blog ---------------------------------------------------------------- */
.ac-postlist { display: flex; flex-direction: column; gap: var(--space-4); }
.ac-post {
  display: grid; grid-template-columns: 240px 1fr; gap: var(--space-6);
  padding: var(--space-4); border: 1px solid var(--line);
  border-radius: var(--radius-md); background: var(--surface);
  text-decoration: none;
  transition: border-color .2s ease, transform .25s cubic-bezier(.16,1,.3,1), box-shadow .25s ease;
}
.ac-post:hover { border-color: var(--signal-soft); transform: translateY(-2px); box-shadow: 0 12px 28px rgba(11,27,63,.12); }
.ac-post:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }
.ac-post__media {
  border-radius: var(--radius-sm); overflow: hidden; background: var(--midnight);
  aspect-ratio: 16 / 9;
}
.ac-post__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ac-post__date { font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-muted); }
.ac-post__title { font-size: 19px; line-height: 27px; font-weight: 700; color: var(--ink); margin: var(--space-2) 0 var(--space-2); }
.ac-post__excerpt { font-size: 14px; line-height: 22px; color: var(--ink-body); margin: 0; max-width: 62ch; }
@media (max-width: 720px) { .ac-post { grid-template-columns: 1fr; } }

.ac-pager {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  margin-top: var(--space-12); padding-top: var(--space-6); border-top: 1px solid var(--line);
  font-size: 15px; font-weight: 600;
}
.ac-pager__page { color: var(--ink-muted); font-weight: 500; }
.ac-pager__disabled { color: var(--line); }

/* --- 404 ----------------------------------------------------------------- */
.ac-notfound { background: var(--navy); color: var(--on-dark-muted); }
.ac-notfound__inner { max-width: 60ch; text-align: center; margin-inline: auto; }
.ac-notfound__code {
  font-size: clamp(64px, 12vw, 120px); line-height: 1; font-weight: 700;
  letter-spacing: -.04em; color: rgba(143,179,255,.28); margin: 0;
}
.ac-notfound h1 {
  font-size: clamp(26px, 3vw, 36px); line-height: 1.16; font-weight: 700;
  letter-spacing: -.02em; color: var(--on-dark); margin: var(--space-4) 0 var(--space-3);
}
.ac-notfound__lead { font-size: 17px; line-height: 28px; margin: 0 auto var(--space-8); max-width: 44ch; }
.ac-notfound__actions { display: flex; flex-wrap: wrap; gap: var(--space-4); justify-content: center; }
.ac-notfound__nav {
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); justify-content: center;
  margin-top: var(--space-20); padding-top: var(--space-6);
  border-top: 1px solid rgba(143,179,255,.22);
}
.ac-notfound__nav a { font-size: 14px; font-weight: 600; color: var(--signal-soft); text-decoration: none; }
.ac-notfound__nav a:hover { color: var(--on-dark); }
.ac-notfound__credit { font-size: 13px; color: rgba(184,196,220,.6); margin: var(--space-8) 0 0; }

/* Blog post: the featured image sits between the head and the body rather
   than inside either, so it reads as the article's own plate. */
.ac-postfigure { background: var(--surface); padding-top: var(--space-12); }
.ac-postfigure img {
  display: block; width: 100%; height: auto; aspect-ratio: 16 / 9;
  object-fit: cover; border-radius: var(--radius-md); background: var(--midnight);
}
.ac-prose--lg p { font-size: 17px; line-height: 30px; }

/* The template's own empty-image placeholder, inside an Allied post card.
   Kept quiet: it is scaffolding, not content. */
.ac-post__media .img-slot,
.ac-post__media .ratio {
  width: 100%; height: 100%;
  display: grid; place-items: center; gap: 4px;
  background: var(--cloud); color: var(--ink-muted);
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
}

/* ==========================================================================
   Auth screens (log in, register, forgot / reset password)
   These render with $bareLayout, so there is no header or footer to carry
   the brand. The lockup does it instead, and the card is the only object on
   the page. The admin dashboard behind them is deliberately left on the
   template's own styling: it is private, dense product UI, and a different
   problem from a marketing site.
   ========================================================================== */
.ac-auth {
  min-height: 100vh; min-height: 100dvh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-8); padding: var(--space-8) var(--space-6);
  background: var(--cloud);
}
.ac-auth__brand { display: inline-flex; line-height: 0; text-decoration: none; }
.ac-auth__logo { height: 48px; width: auto; display: block; }
.ac-auth__card {
  width: 100%; max-width: 27rem;
  padding: var(--space-8);
  background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}
.ac-auth__card h1 {
  font-size: 24px; line-height: 32px; font-weight: 700; letter-spacing: -.015em;
  color: var(--ink); margin: 0;
}
.ac-auth__sub { font-size: 15px; line-height: 24px; color: var(--ink-body); margin: var(--space-2) 0 0; }
.ac-auth__card form { display: flex; flex-direction: column; gap: var(--space-6); margin-top: var(--space-6); }
.ac-auth__foot {
  font-size: 14px; line-height: 22px; color: var(--ink-body);
  margin: var(--space-6) 0 0; padding-top: var(--space-6);
  border-top: 1px solid var(--line);
}
.ac-field__labelrow { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); }
.ac-field__labelrow .ac-textlink { font-size: 13px; }
.ac-btn--block { width: 100%; justify-content: center; }
/* Inline alerts sit inside a card, so they lose the section-level margin. */
.ac-alert--inline { margin-bottom: 0; margin-top: var(--space-6); padding: var(--space-4); align-items: center; }
.ac-alert--inline svg { flex: 0 0 auto; }

/* ==========================================================================
   Coming soon
   For a page that is in the information architecture but whose copy is not
   written yet. Deliberately NOT styled as a warning: amber or red would
   read as something broken. This is the sky/signal pair the rest of the
   site uses for "here is where to go next", because that is what it is.

   The heading is an h2 and the section already has its h1, so the page
   keeps one heading level per rank with the placeholder in place.
   ========================================================================== */
.ac-soon {
  max-width: 54ch;
  padding: var(--space-8);
  border: 1px solid var(--signal-soft);
  border-radius: var(--radius-md);
  background: var(--sky);
}
.ac-soon__icon {
  display: grid; place-items: center;
  width: 48px; height: 48px; border-radius: var(--radius-full);
  background: var(--signal); color: var(--on-dark);
  margin-bottom: var(--space-4);
}
.ac-soon h2 {
  font-size: 21px; line-height: 29px; font-weight: 700; letter-spacing: -.01em;
  color: var(--ink); margin: 0 0 var(--space-2);
}
.ac-soon p {
  font-size: 16px; line-height: 26px; color: var(--ink-body);
  margin: 0 0 var(--space-6);
}
.ac-soon__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }
@media (max-width: 560px) {
  .ac-soon { padding: var(--space-6); }
  .ac-soon__actions .ac-btn { width: 100%; justify-content: center; }
}
