/* =====================================================================
   services.css — CyMobility Services hub (/services/)
   Page-scoped (.page-services) styles that sit on top of the shared About
   design system (styles.css), the header/footer chrome (site-chrome.css)
   and the interior page components (interior.css).

   interior.css already supplies everything this page shares with the
   Industry pages: the hero + regulation pills, the capability card grid,
   the typographic stage flow (.jflow), the proof strip, the FAQ accordion
   and the final CTA. Only what is genuinely specific to the services hub
   lives here — the per-card capability pills, the 4-step (not 5-step)
   lifecycle, and this page's section rhythm.
   ===================================================================== */

/* This hero deliberately carries no ambient background layer. Two were tried
   and both removed: the linked particle net (js/bg-net.js), whose links drew
   angular polygons across the ground behind the wireframe car and read as a
   box, and the point halo (js/hero-tunnel.js), whose scattered points read as
   noise across the whole band. The gradient plus the wireframe car is the
   background. */

/* ======================= Section rhythm ============================== */
/* Matches the About page's band pattern — a dark band and a lavender band,
   each separated by white, so no two same-tone sections ever touch.

   HUB (/services/) and the 6-section sub-pages (.page-svc-sub):
     hero(dark) → lifecycle | why-it-matters(dark, reads as part of the hero
     like About's stat strip) → grid(white) → proof(LAVENDER) → faq(white)
     → final CTA(dark).
   interior.css already defaults .ind-proof to lavender and .ind-faq to white,
   so these pages need no override. Four content sections leaves no room for a
   mid-page dark beat; the hero-attached one is the maximum.

   7-SECTION SUB-PAGES (.page-svc-flow — those with a staged methodology):
     hero(dark) → why(dark) → grid(white) → flow(DARK) → proof(white)
     → faq(LAVENDER) → final CTA(dark)
   That fifth content section buys the mid-page dark beat, so these match the
   About reference exactly — and their tail flips to stay alternating, the same
   way the Industry pages' does. */
.page-svc-flow .ind-proof { background: var(--color-white); box-shadow: none; }
.page-svc-flow .ind-faq {
  background: var(--color-lavender);
  box-shadow: inset 0 10px 30px rgba(0,0,59,.02), inset 0 -10px 30px rgba(0,0,59,.02);
}
/* The lavender hairline is invisible on the lavender band — neutral navy here. */
.page-svc-flow .ind-faq .faq-item { border-bottom-color: rgba(0, 0, 59, 0.1); }
.page-svc-flow .ind-faq .faq-item:first-child { border-top-color: rgba(0, 0, 59, 0.1); }

/* Sub-page flows are staged methodologies, not the hub's fixed 4-step loop, so
   they size to whatever the sheet defines rather than the hub's 4 columns. */
.page-svc-sub .jflow { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* ==================== Sub-page grid alignment ======================== */
/* The sheets hand these pages 2, 4 and 5 cards, and a fixed 3-column grid
   cannot place any of those evenly: 5 leaves a hole at the bottom-right, 4
   leaves three, and 2 sit off to the left with a dead third beside them.

   Flex + wrap + centre fixes the ragged last row — whatever wraps is centred
   instead of stranded left. The max-width is what keeps every card the width it
   would have had in a 3-up row, so a wrapped row never renders wider cards than
   the row above it (which is what `flex-grow` alone would do).

   The two quantity queries below are the cases where a third-width card would
   look stranded rather than deliberate: 2 cards take half the row each, and 4
   become a tidy 2x2 instead of 3-plus-orphan. If :has() is unavailable the rule
   is simply dropped and the cards stay third-width and centred — still fine. */
.page-svc-sub .ind-caps .cards-grid,
.page-svc-sub .proof-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
}
.page-svc-sub .ind-caps .cards-grid > .card {
  flex: 1 1 300px;
  max-width: calc((100% - 5rem) / 3);          /* .cards-grid gap is 2.5rem */
}
.page-svc-sub .proof-grid > .proof-card {
  flex: 1 1 280px;
  max-width: calc((100% - 3.2rem) / 3);        /* .proof-grid gap is 1.6rem */
}
/* flex-basis, not just max-width: the basis is what decides where the row
   breaks. Capping the width alone still let three cards onto the first row and
   left the fourth wrapping BELOW at half width — an orphan wider than the row
   above it. Setting the basis to half forces exactly two per row, so 4 lays out
   as a true 2x2 and 2 fills a single row. */
.page-svc-sub .ind-caps .cards-grid:has(> .card:nth-child(2):last-child) > .card,
.page-svc-sub .ind-caps .cards-grid:has(> .card:nth-child(4):last-child) > .card {
  flex: 1 1 calc((100% - 2.5rem) / 2);
  max-width: calc((100% - 2.5rem) / 2);
}
.page-svc-sub .proof-grid:has(> .proof-card:nth-child(2):last-child) > .proof-card,
.page-svc-sub .proof-grid:has(> .proof-card:nth-child(4):last-child) > .proof-card {
  flex: 1 1 calc((100% - 1.6rem) / 2);
  max-width: calc((100% - 1.6rem) / 2);
}

@media (max-width: 900px) {
  /* Below the 3-up breakpoint the thirds/halves stop helping — let the cards
     find their own width so they never squeeze. */
  .page-svc-sub .ind-caps .cards-grid > .card,
  .page-svc-sub .proof-grid > .proof-card,
  .page-svc-sub .ind-caps .cards-grid:has(> .card:nth-child(2):last-child) > .card,
  .page-svc-sub .ind-caps .cards-grid:has(> .card:nth-child(4):last-child) > .card,
  .page-svc-sub .proof-grid:has(> .proof-card:nth-child(2):last-child) > .proof-card,
  .page-svc-sub .proof-grid:has(> .proof-card:nth-child(4):last-child) > .proof-card {
    max-width: 100%;
  }
}

/* ============ Interference-field hero background (js/hero-wave.js) ====
   Currently only on /services/security-testing/. Sits at z-index -1 inside
   .hero, which already sets position: relative and isolation: isolate in
   styles.css — so it paints above the hero's gradient and below all of its
   content without any content element needing its own z-index.

   The hero copy is left-aligned to the 8% gutter, so the mask holds the field
   back behind the text rather than erasing it — an earlier version faded to
   fully transparent across the left half and, combined with the falloff in the
   shader, left the whole hero looking empty. It now starts at 30% and reaches
   full strength past the text column. Strength overall is trimmed with
   data-level on the canvas, so the mask and the level never fight. */
/* NOT CURRENTLY WIRED TO ANY PAGE. Kept, with js/hero-wave.js, so the
   interference field is a two-line revert if the lab-bench story below turns
   out to be the wrong call for security-testing. */
.page-services .hero .hero-wave {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0.30) 0%, rgba(0, 0, 0, 0.5) 30%, rgba(0, 0, 0, 0.82) 55%, #000 74%);
          mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0.30) 0%, rgba(0, 0, 0, 0.5) 30%, rgba(0, 0, 0, 0.82) 55%, #000 74%);
}
/* Stacked hero, so the copy runs the full width — feather from the top instead
   and keep it well back. */
@media (max-width: 900px) {
  .page-services .hero .hero-wave {
    opacity: 0.6;
    -webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.35) 0%, transparent 55%);
            mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.35) 0%, transparent 55%);
  }
}

/* ==== Story hero backgrounds (sectest-hero.js, monitor-hero.js, tara-hero.js) ====
   /services/security-testing/. This REPLACED the interference field above as
   that page's hero background: on a wide hero the field read as almost nothing,
   and more to the point it said nothing — it was texture, not the page's
   argument. This one is the argument: three methods fire at a target under
   test, findings drop out severity-rated, security.core turns them into a
   report, and the report is UN R155 evidence.

   Hero only. The canvas is a child of .hero, which already carries
   position: relative, overflow: hidden and isolation: isolate from styles.css,
   so z-index -1 puts it above the hero gradient and below every piece of copy
   without any content element needing its own z-index. Nothing here can reach
   the sections below the hero.

   The script anchors the whole composition to a band on the right and draws
   nothing to the left of it, so this mask is a second line of defence rather
   than the thing doing the work — which is why it can fade fully transparent
   here without emptying the graphic, the way it did on .hero-wave. */
.page-services .hero .hero-story {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, transparent 30%, rgba(0, 0, 0, 0.35) 42%, rgba(0, 0, 0, 0.85) 50%, #000 58%);
          mask-image: linear-gradient(90deg, transparent 0%, transparent 30%, rgba(0, 0, 0, 0.35) 42%, rgba(0, 0, 0, 0.85) 50%, #000 58%);
}
/* Stacked hero. The canvas used to be hidden here, because a right-anchored
   band behind full-width copy is illegible at phone size. Instead of hiding it,
   it LEAVES the background: position goes static, `order` puts it last in the
   hero's flex column, and it becomes a figure under the copy — the same move
   .page-svc-anim makes when its two-column hero stacks. The mask goes with it,
   since there is no copy column on the left to protect any more, and the script
   spans the full width once it sees this breakpoint.

   Taller than the About and Contact bands: these three graphics stack labelled
   rows rather than two cards, so they need the extra height to stay readable. */
@media (max-width: 900px) {
  /* Heading -> animation -> content, the order the home page hero uses when it
     stacks (style.css .hero-wrap). The h1 and the sub-headline sit in the same
     .hero-content div, so the canvas cannot slot between them as a sibling.
     display: contents drops that wrapper's box for LAYOUT only, promoting its
     children to direct flex items of .hero so all three can be ordered. Safe
     because .hero is already align-items: flex-start / text-align: left —
     exactly what .hero-content was contributing — so only its max-width has to
     be handed down.

     Scoped to the three body classes that actually carry a .hero-story rather
     than to .page-services, which would flatten the wrapper on every other
     Services page too — including the .page-svc-anim heroes, whose figure is
     already a sibling and already stacks in the right order. */
  .page-svc-sectest .hero .hero-content,
  .page-svc-monitor .hero .hero-content,
  .page-svc-tara .hero .hero-content { display: contents; }
  .page-svc-sectest .hero .hero-content > *,
  .page-svc-monitor .hero .hero-content > *,
  .page-svc-tara .hero .hero-content > * { max-width: 68ch; }
  .page-svc-sectest .hero .hero-content > h1,
  .page-svc-monitor .hero .hero-content > h1,
  .page-svc-tara .hero .hero-content > h1 { order: 1; }
  .page-svc-sectest .hero .hero-content > :not(h1),
  .page-svc-monitor .hero .hero-content > :not(h1),
  .page-svc-tara .hero .hero-content > :not(h1) { order: 3; }

  .page-services .hero .hero-story {
    position: relative;
    inset: auto;
    order: 2;
    width: 100%;
    height: clamp(300px, 46vh, 380px);
    /* Sits between the heading and the copy now, so it needs room on both. */
    margin: clamp(18px, 4vw, 30px) 0 clamp(8px, 2.5vw, 18px);
    z-index: 0;
    -webkit-mask-image: none;
            mask-image: none;
  }
}
/* .hero-content's own box carried this indent; display: contents above drops it,
   so hand it to the children that were inside it. */
@media (max-width: 420px) {
  .page-svc-sectest .hero .hero-content > *,
  .page-svc-monitor .hero .hero-content > *,
  .page-svc-tara .hero .hero-content > * { padding-left: 20px; }
}

/* ---- Coverage band (.page-svc-cover) ----
   A "what we test" list of bare labels. On the Industry pages this band is the
   page's DARK beat; on a Services sub-page it is the LAVENDER beat instead
   (the dark one is already spent on the hero-attached "why" band), so the chips
   revert to the light treatment rather than interior.css's purple glass. */
.page-svc-cover .ind-coverage {
  background: var(--color-lavender);
  box-shadow: inset 0 10px 30px rgba(0,0,59,.02), inset 0 -10px 30px rgba(0,0,59,.02);
  border-top: 0;
  border-bottom: 0;
}
.page-svc-cover .ind-coverage .grid-header h2 { color: var(--color-navy); }
/* Re-tint ONLY — the pill shape, the centred flow-wrap, the gap and the glowing
   accent dot all come from the shared .asset-grid in interior.css, so the light
   band is the same object as the dark one and simply reads inverted. Never
   restate layout here or the two drift apart. */
.page-svc-cover .asset-grid li {
  background: var(--color-white);
  border: 1px solid var(--color-lavender);
  color: var(--color-navy);
  backdrop-filter: none;
  box-shadow: 0 1px 2px rgba(0, 0, 59, 0.05), 0 8px 22px rgba(0, 0, 59, 0.05);
  transition: transform 0.25s var(--ease-out), border-color 0.25s var(--ease-out), box-shadow 0.25s var(--ease-out);
}
.page-svc-cover .asset-grid li:hover {
  transform: translateY(-3px);
  border-color: var(--color-cyan-1);
  background: var(--color-white);
  box-shadow: 0 0 0 4px rgba(77, 127, 230, 0.1), 0 8px 22px rgba(0, 0, 59, 0.06);
}

/* ==================== SECTION 2 — Lifecycle ========================== */
/* The hub's flow has four stages, not the five the Industry journey uses. */
.page-services .jflow { grid-template-columns: repeat(4, 1fr); }

.page-services .ind-journey .grid-header { max-width: 820px; }
.page-services .journey-intro {
  font-size: 1.1rem;
  line-height: 1.7;
  margin-top: 1.1rem;
}

/* The services each stage covers. Sits under the stage copy as quiet
   supporting detail — deliberately not a pill or a chip, so it never
   competes with the numeral that carries the sequence. */
.page-services .jflow-svc {
  display: block;
  margin-top: 0.85rem;
  font-size: 0.84rem;
  line-height: 1.5;
}

/* ---- The lifecycle band sits directly under the hero, so it is the LIGHT
   beat: one dark section, then one light section. Everything below re-tints the
   flow for a light ground. Scoped with `+` so this ONLY applies to the band
   touching the hero — a journey/flow band further down a page (the OEM
   type-approval journey, the sub-page methodologies) stays dark, because there
   it is the mid-page dark beat with white sections either side. ---- */
.page-services .hero + .ind-journey {
  background: var(--color-lavender);
  box-shadow: inset 0 10px 30px rgba(0,0,59,.02), inset 0 -10px 30px rgba(0,0,59,.02);
}
.page-services .hero + .ind-journey .grid-header h2 { color: var(--color-navy); }
.page-services .hero + .ind-journey .journey-intro { color: rgba(0, 0, 59, 0.75); }
/* Same ghosting as the dark band, inverted: the numerals stay a faint tint of
   the ground so the stage names carry the reading, not the digits. */
.page-services .hero + .ind-journey .jflow-n { color: rgba(0, 0, 59, 0.14); }
.page-services .hero + .ind-journey .jflow-step:hover .jflow-n { color: rgba(0, 0, 59, 0.28); }
.page-services .hero + .ind-journey .jflow-step h3 { color: var(--color-navy); }
.page-services .hero + .ind-journey .jflow-step p { color: rgba(0, 0, 59, 0.75); }
.page-services .hero + .ind-journey .jflow-svc { color: rgba(0, 0, 59, 0.5); }
.page-services .hero + .ind-journey .jflow-state { color: var(--color-purple); }

/* ================ SECTION 3 — Service card pills ===================== */
/* Scope note: these are the capability pills INSIDE a service card, not the
   dark hero's .hero-pills. Light ground, so they take the lavender/purple
   treatment the About page uses for its market pills rather than the hero's
   translucent purple. */
.page-services .svc-pills {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0 0 1.4rem;
  padding: 0;
}
.page-services .svc-pills li {
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--color-purple);
  background: rgba(73, 41, 154, 0.07);
  border: 1px solid rgba(73, 41, 154, 0.16);
  border-radius: 20px;
  padding: 0.28rem 0.66rem;
  white-space: nowrap;
  /* Homepage-style keyword hover: a small lift + a brighter edge. */
  transition: transform 0.25s cubic-bezier(.16,1,.3,1), border-color 0.25s cubic-bezier(.16,1,.3,1), background 0.25s cubic-bezier(.16,1,.3,1);
}
.page-services .svc-pills li:hover {
  transform: translateY(-2px);
  border-color: rgba(77, 127, 230, 0.55);
  background: rgba(73, 41, 154, 0.11);
}

/* The pills sit between the description and the link, so the link keeps its
   margin-top:auto pinning from interior.css and every card's CTA still lines
   up across the row regardless of how many pills it carries. */
.page-services .ind-caps .card-desc { margin-bottom: 1.1rem; }

/* ============================ Responsive ============================= */
@media (max-width: 1000px) {
  /* Two stages per row reads better than four cramped columns; matches the
     Industry journey's breakpoint behaviour. */
  .page-services .jflow { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
  .page-services .jflow { grid-template-columns: 1fr; }
  .page-services .svc-pills li { white-space: normal; }
}

/* ========== Consistent band rhythm: dark capability grid (section 3) =========
   On the standard service sub-pages (page-svc-sub, excluding the flow pages,
   which carry their own mid-page dark journey band at section 4), the capability
   grid at section 3 becomes the mid-page dark band. This gives every such page
   the same D-L-D-L-W-D rhythm as the services hub. Only the section background
   darkens; the white cards keep their default styling. */
.page-svc-sub:not(.page-svc-flow) .ind-caps {
  background: linear-gradient(160deg, #05052c 0%, var(--color-navy) 60%, #0b0838 100%);
}
.page-svc-sub:not(.page-svc-flow) .ind-caps .grid-header h2 { color: #fff; }
.page-svc-sub:not(.page-svc-flow) .ind-caps .grid-header p { color: rgba(255, 255, 255, 0.75); }

/* ========== Services hub hero: ECU-network animation backdrop ================
   The animated ECU-network + wireframe-car scan (moved here from the platform
   hero) paints on a transparent canvas over the hero gradient. Heading + content
   sit above it. Scoped to the HUB only (not the service sub-pages). On small
   screens the canvas leaves the background and becomes a block between the
   heading and the body copy (heading -> animation -> content). */
.page-services:not(.page-svc-sub) .hero-head { position: relative; z-index: 1; }
.page-services:not(.page-svc-sub) .hero-content { position: relative; z-index: 1; }
/* Fit the heading to the (narrower) text column so long words like
   "Cybersecurity" never break mid-word. */
.page-services:not(.page-svc-sub) .hero h1 { font-size: var(--fs-hero-h1); line-height: var(--lh-hero-h1); overflow-wrap: normal; word-break: normal; }
/* Cursor spotlight (js/hero-spot.js inserts the layer as the hero's first
   child, so it paints below the copy and the graphic — both z-index 1, later in
   the DOM). The hero's own gradient is left to styles.css: this adds nothing to
   the resting background, only a glow that fades in under the pointer, exactly
   like the homepage's dark bands. */
.page-services .hero .spot-layer {
  position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background: radial-gradient(500px circle at var(--mx, 50%) var(--my, 40%), rgba(77, 127, 230, 0.10), transparent 68%);
  opacity: 0; transition: opacity 0.28s cubic-bezier(.16, 1, .3, 1);
}
.page-services .hero.has-spot:hover .spot-layer { opacity: 1; }
/* z-index needed so .hero-anim paints ABOVE the spotlight layer (also z-index 1)
   rather than under it — without it the glow would wash over the graphic. */
.page-services:not(.page-svc-sub) .hero-anim { position: relative; z-index: 1; width: 100%; max-width: 620px; height: clamp(320px, 40vh, 460px); }
/* Feather the edges so the animation dissolves into the hero gradient instead of
   reading as a box. */
.page-services:not(.page-svc-sub) .hero-anim .hero-net { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;
  -webkit-mask-image: radial-gradient(ellipse at center, #000 66%, transparent 100%);
          mask-image: radial-gradient(ellipse at center, #000 66%, transparent 100%); }
/* Desktop: text left, animation right, vertically centered. */
@media (min-width: 901px) {
  .page-services:not(.page-svc-sub) .hero { display: grid; grid-template-columns: minmax(0, 1fr) clamp(380px, 44vw, 600px);
    grid-template-areas: "head figure" "content figure"; column-gap: clamp(24px, 3vw, 48px);
    align-items: center; align-content: start; min-height: 52vh; }
  .page-services:not(.page-svc-sub) .hero-head { grid-area: head; align-self: end; }
  .page-services:not(.page-svc-sub) .hero-content { grid-area: content; align-self: start; }
  /* Center the graphic so any leftover margin is split evenly top and bottom. */
  .page-services:not(.page-svc-sub) .hero-anim { grid-area: figure; align-self: center; }
}
/* Small screens: stack heading -> animation -> content (DOM order). */
@media (max-width: 900px) {
  .page-services:not(.page-svc-sub) .hero { overflow-x: clip; }
  .page-services:not(.page-svc-sub) .hero h1 { max-width: 100%; }
  /* Was a fixed 340px in a 412px viewport, so the figure sat in the middle of
     the column with dead space either side while the car itself was clipped.
     Now it takes the full column and runs taller: the car is width-bound on a
     phone, so every extra pixel of width goes straight into the artwork, and
     the added height gives the attack tags somewhere to stack. */
  .page-services:not(.page-svc-sub) .hero-anim { width: 100%; max-width: 520px; height: clamp(320px, 78vw, 400px); margin: 1.1rem auto 0.4rem; overflow: hidden; }
}

/* ============ Services sub-page hero with a motion figure =================
   Opt-in via .page-svc-anim on <body>, so every other Services and Industries
   hero is untouched. Same two-column arrangement as the platform engine pages:
   copy left, figure right, with the figure vertically centred.

   Used by: UN R155/R156 (r155-hero), consulting (consult-hero), regulatory
   compliance (comply-hero), AIS-189/190 (ais-hero), SDV advisory (sdv-hero) and
   training (train-hero). Distinct from the .hero-story backgrounds above, which
   sit BEHIND full-width copy and are masked back so the text wins — these are
   diagrams whose labels have to stay readable, so they get their own column.

   The gaps are deliberate and match the rest of the site: the hero's own 8%
   side padding is kept, the column gap is the shared clamp(24px, 3vw, 48px),
   and the graphic itself is drawn inset from its canvas edges, so the copy
   never crowds the figure and the figure never touches the band edge. */
@media (min-width: 901px) {
  .page-svc-anim .hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(380px, 46vw, 680px);
    grid-template-areas: "head figure" "content figure";
    column-gap: clamp(24px, 3vw, 48px);
    align-items: center; align-content: center;
  }
  .page-svc-anim .hero-head { grid-area: head; align-self: end; }
  .page-svc-anim .hero-content { grid-area: content; align-self: start; max-width: 60ch; }
  .page-svc-anim .hero-anim { grid-area: figure; align-self: center; }
}
.page-svc-anim .hero-anim {
  position: relative; width: 100%; max-width: 680px;
  /* taller than the platform figures: these graphics stack a road, gates,
     evidence rows and a verdict, so the rows need room to breathe. Sized up a
     step so the drawing reads at a glance rather than sitting small beside the
     copy. Scoped to .page-svc-anim only — the contact page carries no figure
     and is unaffected. */
  height: clamp(520px, 68vh, 660px);
}
/* No mask: the graphic is built from panels and a road, not a centred ring, so
   a radial feather would clip its corners. */
.page-svc-anim .hero-scan {
  position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;
}
/* The copy column is roughly half the width it had as a full-bleed hero, so the
   heading must be allowed to wrap ("Automotive Cybersecurity Compliance, Across
   Every Mandate") rather than break long compound words. It runs at the shared
   site-wide hero scale (--fs-hero-h1, css/styles.css); only the wrapping
   behaviour is page-specific. */
.page-svc-anim .hero h1 { font-size: var(--fs-hero-h1); line-height: var(--lh-hero-h1);
  overflow-wrap: normal; word-break: normal; }
.page-svc-anim .hero .sub-headline { max-width: 52ch; font-size: var(--fs-hero-lede); }
/* Stacked: heading -> figure -> copy, matching the engine pages. */
@media (max-width: 900px) {
  .page-svc-anim .hero { min-height: auto; overflow-x: clip; }
  .page-svc-anim .hero h1 { max-width: 100%; }
  .page-svc-anim .hero-content { max-width: 100%; }
  .page-svc-anim .hero-anim {
    width: 460px; max-width: 94vw; height: 480px; margin: 1.2rem auto 0.4rem;
  }
}
