/* Fortified Networks, Option 3: page sections and footer.
   Scroll-reveal gating lives in chapter-scroll.css.

   The homepage used to run a "capabilities" list before "services" —
   dropped (with its cap-section/cap-grid/.cap rules) once the two turned
   out to preview the same ground: 3 of its 5 cards repeated a Services
   headline verbatim, seconds apart on the same scroll. Services (dark
   ground, big serif rows, sticky heading) is the homepage's only
   "what we do" list now, widened from 3 to 5 categories to cover for it.
   .diff-grid below (light ground, tightest padding, 4-up strip) is the
   About page's own "why us" strip, unrelated to homepage hierarchy. */

/* ---------- page grid ---------- */
.wrap {
  width: 100%;
  padding-inline: var(--rail);
}

.skip-link {
  position: fixed;
  top: -60px;
  left: 1rem;
  z-index: 100;
  background: var(--ink);
  color: var(--cream-soft);
  padding: .8rem 1.2rem;
  font-family: var(--font-body);
  font-size: 14px;
  transition: top 160ms var(--ease-out);
}
.skip-link:focus { top: 1rem; }

main { display: block; }

main ol, main ul, footer ol, footer ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
main p, main h2, main h3, footer p, footer h2 { margin: 0; }

/* ---------- shared section furniture ---------- */

/* A link embedded inside body copy or a heading that already has its own
   color, rather than a standalone CTA: underline appears on hover instead
   of a link-blue color change, so it reads as "this is clickable" without
   fighting the section's own palette. Used to route homepage teasers
   (capabilities, safeguard strip, program cards) to the real pages that now
   back them. */
/* Idle underline sits at 35% of the text color (not full-strength — still
   reads as "quiet" against the loud .svc-more/.cta-ink links), full-strength
   on hover/active. Originally this link had zero idle affordance and relied
   on hover alone, which meant a mouse user scanning a paragraph had no way
   to tell "sentence" from "link" without hovering it, and touch visitors
   (no hover at all) saw inert body copy. The why-us section surfaced this:
   with 3-4 of these per paragraph, a whole section's worth of CTAs were
   effectively invisible at rest. */
.quiet-link {
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
  text-underline-offset: .2em;
  transition: text-decoration-color 160ms var(--ease-out);
}
.quiet-link:hover,
.quiet-link:active { text-decoration-color: currentColor; }

.eyebrow {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--o3-meta);
  margin-bottom: clamp(1rem, 2vh, 1.5rem);
}

.section-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2rem, 4.1vw, 3.4rem);
  line-height: 1.04;
  letter-spacing: -.028em;
  color: var(--ink);
  text-wrap: balance;
  transform-origin: left top;
}

/* Light-on-dark button, the inverse of buttons.css .cta-solid, for the two
   light-ground sections that carry a CTA. */
.cta-ink {
  cursor: pointer;
  border: none;
  background: var(--ink);
  color: var(--cream-soft);
  padding: 17px 28px;
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 600;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  transition: transform 160ms var(--ease-out), box-shadow 160ms var(--ease-out);
}
.cta-ink:hover { transform: translateY(-2px); box-shadow: 0 10px 30px rgba(1, 3, 20, .2); }
.cta-ink:active { transform: translateY(-2px) scale(.97); }
.cta-ink .arrow { font-family: var(--font-mono); color: var(--accent); }

/* =========================================================
   PRIMARY: the services — the homepage's sole "what we do" moment
   (see the HTML comment above #services). --o3-pad-primary was defined
   for exactly this and had gone unused since the old capabilities
   section was removed, leaving Services spacing-equal to Technology
   Partnerships and the Close CTA even though it's the section carrying
   the whole "what we do" job by itself. Restored here so the section's
   padding tier matches its actual narrative weight. */
.svc-section {
  background: var(--o3-svc-bg);
  color: var(--o3-heading-ink);
  padding-block: var(--o3-pad-primary);
}

.svc-inner {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 2fr);
  column-gap: clamp(2.5rem, 6vw, 6rem);
  align-items: start;
}

/* Sticky rather than pinned: the heading tracks the rows for the length of
   the section without adding a scroll runway, so the section is never taller
   than its own content. */
.svc-head {
  position: sticky;
  top: clamp(4rem, 10vh, 7rem);
}
.svc-head .section-title { color: var(--o3-heading-ink); }

.svc {
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr);
  column-gap: clamp(1rem, 2vw, 1.75rem);
  border-top: 1px solid var(--o3-dark-rule);
  padding-block: clamp(2rem, 5vh, 3.25rem);
  /* Each of the 9 categories is a #hash link target from other pages —
     without this a jump lands the heading flush against the viewport
     edge, no breathing room above it. */
  scroll-margin-top: 2rem;
}
.svc:first-child { padding-top: 0; border-top: none; }
.svc:last-child { padding-bottom: 0; }

/* ---------- services index: the 9-category carousel ----------
   The homepage's 3-item teaser above stays the sticky-label/stacked-list
   shape (.svc-inner/.svc-head/.svc-list/.svc) — three items reading
   top-to-bottom is fine. Nine is not: stacked, it's a long scroll of
   equal-weight blocks. This centers one card at a time with the
   neighbours peeking in on both sides (App Store / wallet-card pattern —
   no tilt, no perspective, just a flat centered card with its neighbours
   dimmed), browsed by swipe, trackpad, the prev/next buttons or the dot
   row. Nothing hidden behind a click. */
.svc-carousel-section .wrap { display: block; }

.svc-carousel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  margin-bottom: clamp(1.75rem, 4vh, 2.75rem);
}
.svc-carousel-head .section-title { color: var(--o3-heading-ink); margin: 0; }

.svc-carousel-controls { display: flex; gap: .6rem; flex: none; }
.svc-carousel-btn {
  position: relative;
  width: 42px;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: transparent;
  border: 1px solid var(--o3-dark-rule-strong);
  color: var(--o3-heading-ink);
  font-size: 16px;
  line-height: 1;
  transition: background 160ms var(--ease-out), border-color 160ms var(--ease-out), opacity 160ms var(--ease-out);
}
.svc-carousel-btn:hover { background: rgba(255, 255, 255, .06); border-color: var(--o3-nav-hover); }
.svc-carousel-btn:disabled { opacity: .3; cursor: default; pointer-events: none; }

/* Touch controls hide below 720 (see @media below), but this row is still
   reachable at pointer:coarse above that width — a tablet in landscape, a
   touch laptop. 42px sits 2px under the 44px minimum every other target on
   this page is held to. */
@media (pointer: coarse) {
  .svc-carousel-btn::before {
    content: "";
    position: absolute;
    inset: -1px;
  }
}

.svc-carousel-viewport { position: relative; }

/* Native scroll + scroll-snap, not a JS-driven slider: works with trackpad,
   mouse-wheel-shift, touch swipe and the prev/next buttons alike, and
   keeps working if JS fails to load (buttons just wouldn't, the scroll
   itself still would).

   Desktop shows three-ish cards at once, so it starts flush at the page's
   own rail like a normal row (scroll-padding-left, not centering padding)
   -- centering card 1 against a viewport several cards wide would reserve
   empty space nearly half the viewport wide before it even starts, which
   is exactly the dead gutter this replaced. True centered-with-peek only
   turns on below 720, where one card fills most of the screen and
   centering it (wallet-card style) is what makes the neighbours peek in
   evenly on both sides — see the media query for that variant. */
.svc-carousel {
  --svc-card-w: clamp(270px, 30vw, 360px);
  /* Read by js/svc-carousel.js so the dim/scale contrast can be stronger
     on mobile (one card dominant, neighbours need to visibly announce
     themselves) without also muddying the desktop row, where three cards
     are legitimately all "in view" at once and a heavy dim would fight
     that. Redeclared inside the mobile media query below. */
  --svc-dim-floor: .45;
  --svc-dim-scale: 1;
  display: flex;
  align-items: flex-start;
  gap: clamp(1.25rem, 2.5vw, 2rem);
  margin: 0;
  padding: 0;
  /* Without this, the LAST card can never reach its own flush-left snap
     position: the browser can't scroll past scrollWidth-clientWidth, and
     with no trailing space that ceiling falls short of where the last
     card would sit flush -- verified directly (9 cards, only 8 distinct
     scrollLeft stops were ever reachable via real scroll-snap). Padding
     the end by one card's own width worth of empty space gives it the
     same full range of motion every earlier card already has, so it gets
     a genuine independent snap stop instead of permanently sharing one
     with its neighbour. */
  padding-right: calc(100% - var(--svc-card-w));
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  /* Without this, a touch drag on the track has no axis lock: the browser
     is free to read it as vertical page-scroll, horizontal card-scroll, or
     some diagonal blend of both depending on the finger's exact angle --
     reported on a real device as the row itself feeling draggable up/down,
     not just left/right. pan-x tells the browser this element only ever
     consumes horizontal drag; any vertical component of the gesture passes
     straight through to the page's own scroll instead of fighting it. */
  touch-action: pan-x;
  /* touch-action alone locks scroll-vs-pan, but iOS Safari can still read a
     slower drag that starts on the card's own text as a text-selection
     gesture rather than a scroll -- once that engages, the selection (and
     its drag handles) moves in any direction, completely independent of
     this element's scroll axis. That's the actual "drag it everywhere"
     reported on a real device, not a touch-action gap. Disabling selection
     and the iOS long-press callout on the track removes that alternate
     gesture path entirely, so a touch here can only ever be the swipe. */
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  scroll-snap-type: x mandatory;
  scroll-padding-left: var(--rail);
  /* The scroll itself is the point (native, no JS dependency) -- the
     scrollbar chrome that comes with it isn't; it read as a stray system
     control sitting under an otherwise custom-styled section. Touch swipe,
     trackpad and the prev/next buttons all still work with it hidden. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.svc-carousel::-webkit-scrollbar { display: none; }
.svc-carousel:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.svc-card {
  flex: 0 0 var(--svc-card-w);
  scroll-snap-align: start;
  border-top: 1px solid var(--o3-dark-rule);
  padding-top: clamp(1.25rem, 2.5vh, 1.75rem);
  /* Opacity is set inline per-card by js/svc-carousel.js as a continuous
     function of distance from the track's own center on every scroll tick
     -- with 3 cards visible at once on desktop this just gives the
     middle-most a slight lift over its neighbours; on mobile, where it's
     the one centered wallet-style card, it's the full-strength/dimmed
     contrast. transition smooths the steps between scroll updates. */
  opacity: .45;
  transform: scale(1);
  /* Anchor the scale to the top edge, not the default center. Cards sit in
     a top-aligned row (.svc-carousel: align-items: flex-start) with uneven
     heights, so a center-origin scale visibly shifts each card's top edge
     up as it grows toward 1 and down as it shrinks toward --svc-dim-scale
     (mobile: .9) -- exactly the "row bobs up and down while swiping" glitch
     reported on mobile. Top-anchoring keeps every card's top edge fixed at
     the same y position; only the bottom and sides breathe with the scale. */
  transform-origin: top center;
  transition: opacity 120ms linear, transform 120ms linear;
}

/* Dot row: which of the nine is centered, and a direct way to jump to any
   one of them without scrubbing past the rest — the reference pattern
   this replaced the raw scrollbar/edge-fade with. */
.svc-carousel-dots {
  display: flex;
  justify-content: center;
  gap: .55rem;
  margin-top: clamp(1.5rem, 3vh, 2rem);
}
.svc-dot {
  position: relative;
  width: 7px;
  height: 7px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--o3-dark-rule-strong);
  cursor: pointer;
  transition: background 160ms var(--ease-out), transform 160ms var(--ease-out);
}
.svc-dot:hover { background: var(--o3-nav-muted); }
.svc-dot.is-active { background: var(--accent); transform: scale(1.3); }

/* Same convention as every other small target on this page (.hero-incident,
   .footer-col a, .page-toc a): a 7px dot is well under the 44px minimum, so
   a pseudo-element grows the real hit area without touching the visible
   size the row's rhythm is built around. */
@media (pointer: coarse) {
  .svc-dot::before {
    content: "";
    position: absolute;
    inset: -18px;
  }
}

@media (max-width: 720px) {
  /* Horizontal swipe stays on mobile (it's a natural touch gesture) --
     only the prev/next buttons go, since arrow controls read as a
     desktop pattern bolted onto a touch screen. Dots + the peeking,
     dimmed neighbours are the affordance instead.

     This is also where centering-with-symmetric-peek switches on: one
     card fills most of a phone screen, so centering it reserves only a
     small, even margin on both sides for the neighbour to peek through
     (the wallet-card reference), instead of the near-half-viewport void
     that same math produces on a wide desktop row. */
  .svc-carousel-controls { display: none; }
  .svc-carousel {
    /* Narrower than a first pass (was 78vw): the neighbour needs to be
       unmistakably a card sitting right there, not a sliver you could
       miss. At 66vw roughly a fifth of each neighbour shows on either
       side. */
    --svc-card-w: 66vw;
    /* Stronger contrast than the desktop row needs: this is the only card
       on screen that matters, so its neighbours should read as clearly
       "not it yet" -- both dimmer AND visibly smaller, not just a faint
       opacity shift that's easy to miss while scrolling past. */
    --svc-dim-floor: .32;
    --svc-dim-scale: .9;
    gap: 1rem;
    padding-inline: calc((100% - var(--svc-card-w)) / 2);
    scroll-padding-left: 0;
  }
  .svc-card { scroll-snap-align: center; }
}

/* The three services aren't a sequence — no step depends on the one before
   it — so unlike the dated /resources/ blog list (a real chronology, kept
   on .svc-idx), this listing drops the index column entirely rather than
   implying an order that doesn't exist. */
.svc--noidx { grid-template-columns: minmax(0, 1fr); }

.svc-idx {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .12em;
  color: var(--o3-nav-muted);
  padding-top: .75em;
}

/* Category label above each of the 9 service headings — same eyebrow
   shape as .eyebrow elsewhere, but keyed to --o3-nav-muted rather than
   --o3-meta since this list lives on the dark svc-section ground and
   --o3-meta is only contrast-checked against the cream grounds. */
.svc-eyebrow {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--o3-nav-muted);
  margin-bottom: clamp(.6rem, 1.2vh, .9rem);
}

.svc-body h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.65rem, 3vw, 2.6rem);
  line-height: 1.06;
  letter-spacing: -.026em;
  color: var(--o3-heading-ink);
  margin-bottom: clamp(.75rem, 1.6vh, 1.1rem);
  text-wrap: balance;
}
.svc-body p {
  font-size: clamp(15.5px, 1.15vw, 17px);
  line-height: 1.6;
  color: var(--o3-subhead-ink);
  max-width: 54ch;
  text-wrap: pretty;
}
.svc-more {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: clamp(1rem, 2.2vh, 1.5rem);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
  border-bottom: 1px solid transparent;
  padding-bottom: 3px;
  transition: color 160ms var(--ease-out), border-color 160ms var(--ease-out);
}
.svc-more .arrow { transition: transform 160ms var(--ease-out); }
.svc-more:hover { color: var(--o3-nav-hover); border-color: var(--o3-dark-rule-strong); }
.svc-more:hover .arrow { transform: translateX(3px); }

/* Safe to grow, unlike .quiet-link: this always sits alone as its own
   element after a paragraph, never embedded mid-sentence, so there's no
   adjacent inline text an expanded hit area could swallow. Measured 18px
   tall against a 44px minimum. */
@media (pointer: coarse) {
  .svc-more::before {
    content: "";
    position: absolute;
    inset: -13px -4px;
  }
}

/* =========================================================
   TERTIARY: what makes them different
   ========================================================= */
.diff-section {
  background: var(--o3-diff-bg);
  padding-block: var(--o3-pad-tertiary);
  border-top: 1px solid var(--o3-rule);
}

/* align-items was `baseline`, which is doing exactly what it says and is
   exactly wrong for this pairing. The title is one 41.6px line and the
   sub is two 17.3px lines: matching their first *baselines* drops the sub
   18px down the row, so the title floats with a void under it while the
   sub's second line hangs below the title entirely and crowds the rule
   beneath -- the "off" alignment in the screenshot.

   `start` matches their first lines' cap-tops instead, which for this
   type pairing lands within a fraction of a pixel (Inter, cap height
   .727em: 7.8px into the title's line box, 7.6px into the sub's). Optical
   top alignment, no magic number, and it stays correct if either column
   wraps to a different number of lines. */
.diff-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: clamp(2.5rem, 6vw, 6rem);
  align-items: start;
  padding-bottom: clamp(2.25rem, 5vh, 3.25rem);
}

/* Was clamp(1.5rem, 2.4vw, 2.1rem) -- at 33.6px max it read smaller than
   .svc-body h3 (a Services *item* heading, one section up, 41.6px max),
   so the section title for the page's trust/credibility beat lost to a
   nested card heading in the section before it. Bumped so it reads as
   its own section-level heading while staying clearly under
   .section-title/.close-inner h2 -- tertiary tier, not tertiary-sized
   into illegibility. */
.diff-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.75rem, 3.2vw, 2.6rem);
  line-height: 1.1;
  letter-spacing: -.02em;
  color: var(--ink);
  text-wrap: balance;
}
/* Was a flat 15.5px, the only section lede on the page that wasn't
   fluid and the only one that never reached 16px -- .hero-lede,
   .tech-body p and .close-lede (the same "intro sentence under a
   section heading" role) all use this exact clamp. */
.diff-sub {
  font-size: clamp(16px, 1.2vw, 17.5px);
  line-height: 1.6;
  color: var(--o3-body);
  max-width: 44ch;
  text-wrap: pretty;
}

.diff-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: clamp(1.5rem, 3vw, 2.75rem);
}
.diff {
  border-top: 1px solid var(--o3-rule-strong);
  padding-top: clamp(1.1rem, 2.4vh, 1.5rem);
}
/* Was a flat 15px sitting 1px above .diff p's 14px -- a heading/body
   pair that close together isn't a legible hierarchy signal on its own;
   it survived only on the 600-vs-400 weight jump. Matches the fluid
   range About's own page.css override already settled on for this same
   role (.diff-section--why .diff h3), reused here instead of
   reinventing a second value for one heading. */
.diff h3 {
  font-family: var(--font-body);
  font-size: clamp(1.05rem, 1.7vw, 1.3rem);
  font-weight: 600;
  line-height: 1.3;
  color: var(--ink);
  margin-bottom: clamp(.5rem, 1.2vh, .65rem);
  text-wrap: balance;
}
/* Was a flat 14px -- running body copy in a trust/credibility section,
   not a caption, and below the 16px floor. */
.diff p {
  font-size: clamp(16px, 1vw, 17px);
  line-height: 1.6;
  color: var(--o3-body);
  text-wrap: pretty;
}

/* The homepage's condensed teaser adds this single "view the full page"
   link after the grid (About itself has no need for it — it IS the full
   page). font-body rather than svc-more's mono/uppercase treatment: this
   sits on the same light ground as the h3s above it, reads as a plain
   continuation of the section, not a second all-caps label competing
   with .eyebrow elsewhere on the page. */
.diff-more {
  display: inline-block;
  margin-top: clamp(2rem, 4.5vh, 3rem);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}

/* =========================================================
   Technology partnerships
   ========================================================= */
.tech-section {
  background: var(--o3-tech-bg);
  padding-block: var(--o3-pad-secondary);
  /* --o3-rule-strong, not --o3-rule: this seam sits between the two
     lightest, closest-in-value backgrounds on the page (cream vs.
     cream-soft, ~2.5% apart — see tokens.css). The weak rule reads as a
     stray hairline at that contrast; the strong one (already used for
     .diff item borders and the vendor list, so no new token) is what
     actually marks the chapter break instead of leaving it to a subtle
     color shift alone. */
  border-top: 1px solid var(--o3-rule-strong);
}

.tech-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
  column-gap: clamp(2.5rem, 6vw, 6rem);
  align-items: start;
}

.tech-head .section-title { max-width: 14ch; }

.vendor-list {
  margin-top: clamp(1.75rem, 4vh, 2.5rem);
  border-top: 1px solid var(--o3-rule-strong);
}
.vendor-list li {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: .06em;
  color: var(--ink);
  padding-block: clamp(.7rem, 1.6vh, .95rem);
  border-bottom: 1px solid var(--o3-rule);
}

.tech-body {
  display: flex;
  flex-direction: column;
  gap: clamp(1.25rem, 3vh, 1.75rem);
}
.tech-body p {
  font-size: clamp(16px, 1.25vw, 18px);
  line-height: 1.62;
  color: var(--o3-body);
  max-width: 60ch;
  text-wrap: pretty;
}
/* No explicit layout here used to mean the button and the link were
   just sitting in normal inline flow, spaced by whatever whitespace
   happened to collapse out of the HTML source (~4-6px) -- not a real
   gap, an accident of markup formatting. flex-wrap so it drops to its
   own line on narrow widths instead of the two colliding. */
.tech-cta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: clamp(1.25rem, 3vw, 2rem);
  margin-top: clamp(.5rem, 1.5vh, 1rem);
}

/* .svc-more's hover state (color: var(--o3-nav-hover), a near-white
   #f7f8fa) was built for its one original home: the dark .svc-section.
   Reused here on the light .tech-section with no override, hovering
   turned the link near-white on a near-cream background — invisible.
   Same bug shape as the diff/tech seam fix above: a token built for one
   background silently breaking when the class it's part of gets reused
   on the opposite one. Light-appropriate equivalents, already used
   elsewhere on this section's own light ground (--o3-rule-strong is the
   vendor-list divider color; --accent-deep is the brand's darker blue,
   for contrast a plain --accent hover wouldn't add over the resting
   state). */
.tech-cta .svc-more:hover {
  color: var(--accent-deep);
  border-color: var(--o3-rule-strong);
}

/* =========================================================
   Close: schedule a consultation
   ========================================================= */
.close-section {
  background: var(--o3-close-bg);
  color: var(--o3-heading-ink);
  padding-block: var(--o3-pad-secondary);
}

/* Services index only: the carousel section directly above is dark too, and
   with no light section between them (unlike every other page that uses
   .close-section) the two read as one long stretch instead of separate
   chapters. Same fix as .prog-section in program.css -- reuse its blue-lift
   ground plus a hairline, rather than inventing a third dark value. */
.svc-carousel-section + .close-section {
  background: var(--o3-prog-bg);
  border-top: 1px solid var(--o3-dark-rule);
}

.close-inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(1.25rem, 3vh, 2rem);
}

/* Was clamp(2.2rem, 5.2vw, 4.25rem) -- at 68px max it outscaled
   .section-title (Services/Technology Partnerships, 54.4px max), giving
   the closing CTA more visual weight than the page's primary content
   section. Reined in below that ceiling: still the second-largest
   heading on the page after the hero, just no longer beating the
   section it's supposed to be closing out. */
.close-inner h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.9rem, 4vw, 3.1rem);
  line-height: 1.04;
  letter-spacing: -.03em;
  color: var(--o3-heading-ink);
  max-width: 14ch;
  text-wrap: balance;
}

.close-lede {
  font-size: clamp(16px, 1.25vw, 18px);
  line-height: 1.6;
  color: var(--o3-subhead-ink);
  max-width: 52ch;
  text-wrap: pretty;
}

.close-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  /* Same fix as .hero-actions in hero.css: the coarse-pointer touch target on
     .close-incident (below) expands into this gap, and 1rem left too little
     clearance from the CTA button above it once wrapped to two lines. */
  gap: 1.25rem 1.75rem;
  margin-top: clamp(.25rem, 1vh, .75rem);
}

.close-direct {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .75rem;
  margin-top: clamp(1rem, 3vh, 2rem);
  padding-top: clamp(1rem, 2.5vh, 1.75rem);
  border-top: 1px solid var(--o3-dark-rule);
  width: 100%;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: .04em;
  color: var(--o3-subhead-ink);
}
.close-direct a {
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: border-color 160ms var(--ease-out);
}
.close-direct a:hover { border-color: var(--o3-dark-rule-strong); }
.close-direct span { color: var(--o3-nav-muted); }

/* =========================================================
   Footer
   ========================================================= */
footer {
  background: var(--o3-footer-bg);
  color: var(--o3-subhead-ink);
  border-top: 1px solid var(--o3-dark-rule);
  padding-block: clamp(2.75rem, 7vh, 4.5rem);
}

.footer-in {
  display: flex;
  flex-direction: column;
  gap: clamp(2rem, 5vh, 3.25rem);
}

.footer-wordmark { display: inline-block; }
.footer-wordmark img {
  height: 20px;
  width: auto;
  display: block;
}

.footer-cols {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: clamp(1.5rem, 3vw, 3rem);
  row-gap: 2rem;
  border-top: 1px solid var(--o3-dark-rule);
  padding-top: clamp(1.75rem, 4vh, 2.5rem);
}
/* Was .16em -- see hero.css main-nav a for why this is now .18em: one
   shared tracking value for every 11px all-caps mono label site-wide.
   Weight stays 500 (unlike the others in this tier): it's a heading over
   a list of footer links, not a peer label, and the extra weight is what
   marks that. */
.footer-col h2 {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--o3-nav-muted);
  margin-bottom: 1rem;
}
.footer-col li + li { margin-top: .6rem; }
.footer-col a {
  position: relative;
  display: inline-block;
  font-size: 14.5px;
  line-height: 1.4;
  color: var(--o3-subhead-ink);
  /* The sales address is a single 27-character token: without this it is
     wider than a two-up footer column at 375 and pushes the page into
     horizontal scroll. */
  overflow-wrap: anywhere;
  transition: color 160ms var(--ease-out);
}
.footer-col a:hover { color: var(--o3-heading-ink); }

/* Real tap target: single-line entries measured 20px tall against a 44px
   minimum. A ::before (not padding) so the .6rem li+li rhythm above stays
   exactly as spaced; adjacent links' expanded zones touching in that small
   gap is harmless since every row does the same thing (navigate). */
@media (pointer: coarse) {
  .footer-col a::before {
    content: "";
    position: absolute;
    inset: -10px 0;
  }
}

.footer-base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
  border-top: 1px solid var(--o3-dark-rule);
  padding-top: clamp(1.5rem, 3.5vh, 2rem);
}
.footer-copy {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .04em;
  color: var(--o3-nav-muted);
}
.footer-social {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem 1.5rem;
}
.footer-social a {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--o3-nav-muted);
  transition: color 160ms var(--ease-out);
}
.footer-social a:hover { color: var(--o3-heading-ink); }

/* =========================================================
   Responsive
   ========================================================= */
@media (max-width: 999px) {
  .section-head,
  .diff-head {
    grid-template-columns: minmax(0, 1fr);
    row-gap: clamp(1.25rem, 3vh, 1.75rem);
  }
  .svc-inner,
  .tech-inner {
    grid-template-columns: minmax(0, 1fr);
    row-gap: clamp(2rem, 5vh, 3rem);
  }
  .svc-head { position: static; }
  .diff-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: clamp(1.5rem, 3.5vh, 2.25rem); }
  .tech-head .section-title { max-width: 20ch; }
  .vendor-list { margin-top: clamp(1.25rem, 3vh, 1.75rem); }
}

@media (max-width: 719px) {
  /* Same fix as .hero-incident (hero.css): once .close-actions wraps, a bare
     text link alone under the full-width solid button read as an orphaned
     scrap in the dark ground below it, not a real second action. Bordered
     and stretched to match. align-items:stretch alone only affects height
     on a row-direction container -- .cta-solid needs its own width:100%
     too, or it stays content-sized while .close-incident goes full width,
     leaving the pair visibly unaligned (same bug as .hero-actions). */
  .close-actions { align-items: stretch; }
  .close-actions .cta-solid { width: 100%; justify-content: center; }
  .close-incident {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    border: 1px solid var(--o3-dark-rule-strong);
    padding: 13px 16px;
  }
  .close-incident:hover { border-color: var(--o3-nav-hover); }

  .diff-grid { grid-template-columns: minmax(0, 1fr); row-gap: 0; }
  .diff { padding-block: clamp(1.1rem, 2.4vh, 1.5rem); }
  .diff:last-child { border-bottom: 1px solid var(--o3-rule-strong); }
  .svc { grid-template-columns: minmax(0, 1fr); row-gap: .5rem; }
  .svc-idx { padding-top: 0; }
  .footer-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .close-inner h2,
  .close-lede,
  .tech-head .section-title { max-width: none; }
  .footer-base { align-items: flex-start; }
}
