/* ==========================================================================
   SVIND v2 - core.css
   Implements 01_DESIGN/07_core_RM_TEREX.md signature moves S1-S5 plus the
   §6 media-card anatomy. Load LAST:
     tokens.css → base.css → components.css → core.css

   Rules this file obeys:
   · zero radii, zero borders, zero gradients
   · the only shadow is a product ground shadow (S2)
   · structure comes from 4-8px gutters and fill changes
   · max ONE inverted navy panel per row, never two adjacent
   · knockout type is decorative and always aria-hidden in the markup
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. PAGE SHELL
   The shell spans the viewport and never caps itself. Bands are full-bleed:
   the color change runs edge to edge, per 07_core_RM_TEREX.md §"Section
   separation" ("full-bleed color change between bands"). Bands butt directly
   against each other - the fill change alone carries the separation, with no
   surface seam between them. An earlier version put an 8px --gutter-split
   margin between consecutive bands; that token is still used for grid gutters
   inside bands, just not between them.

   Reading width is capped INSIDE each band (see --band-inset below), not on
   this element. Capping the shell is what produced the ~98px-per-side dead
   gutter at 1435px and 340px at 1920px: max-width plus `margin-inline: auto`
   meant a band could never reach the edge. Never reintroduce a max-width
   here; 04_TEST/static/test_layout.py fails if it comes back.
   -------------------------------------------------------------------------- */

.page {
  width: 100%;
  background-color: var(--color-surface);
}

/* No seam between bands: consecutive bands share an edge. Margin is zeroed
   rather than left unset so a band's own block margins can't collapse through
   and reopen the gap. */
.page > * + * {
  margin-block-start: 0;
}

/* --------------------------------------------------------------------------
   1. BAND - full-bleed gray stage. Every band carries the S3 frame.
   -------------------------------------------------------------------------- */

.core-band {
  position: relative;
  overflow: hidden;
  background-color: var(--color-canvas);
  /* Inline padding is --band-inset, not --band-pad-x: the fill runs edge to
     edge while the content inside it stays on the --max-content measure. */
  padding: clamp(48px, 6vw, 66px) var(--band-inset) clamp(48px, 6vw, 72px);
}

/* A band that carries the S3 frame must reserve room for it: the frame is
   absolutely positioned inside the band's own top padding, so the first
   heading has to start below it. Applies at every width. */
.core-band:has(> .core-frame) {
  padding-block-start: calc(clamp(24px, 4vw, 66px) + clamp(44px, 5vw, 62px));
}

.core-band--2 {
  background-color: var(--color-canvas-2);
}

.core-band--navy {
  background-color: var(--color-navy);
  color: var(--color-text-on-dark);
}

/* The trust band is a data strip, not a content band: it carries no headline
   and no lead, so the full band rhythm leaves a lot of empty navy above and
   below three short rows. This tightens the block to roughly the height of
   its own content while still clearing the S3 frame in the top padding.
   Scoped by content, so any future band built from a trust strip inherits it
   and no other band is affected. */
.core-band:has(> .core-trust-strip) {
  padding-block-end: clamp(32px, 3.4vw, 44px);
}

.core-band:has(> .core-frame):has(> .core-trust-strip) {
  padding-block-start: calc(clamp(24px, 4vw, 66px) + clamp(10px, 1.2vw, 16px));
}

.core-band--surface {
  background-color: var(--color-surface);
}

/* Stage that holds a cut-out: give the machine room without a boxed photo. */
.core-band--stage {
  padding-block-end: clamp(32px, 4vw, 48px);
  min-height: clamp(360px, 42vw, 583px);
  height: 959.18px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

/* --------------------------------------------------------------------------
   2. S3 - LABEL / COUNTER FRAME
   navy micro-caps label top-left, slide counter top-right.
   Mandatory on every full-bleed band.
   -------------------------------------------------------------------------- */

.core-frame {
  position: absolute;
  inset-block-start: clamp(24px, 4vw, 66px);
  /* Tracks the band's own inline padding so the label and counter stay
     flush with the content column, not with the full-bleed edge. */
  inset-inline: var(--band-inset);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  pointer-events: none;
  z-index: 3;
}

.core-frame__label {
  margin: 0;
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  color: var(--color-navy);
}

.core-band--navy .core-frame__label {
  color: var(--color-surface);
}

.core-frame__counter {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: 0.04em;
  color: var(--color-ink-muted);
  font-variant-numeric: tabular-nums;
}

.core-frame__counter b {
  font-weight: var(--weight-micro-caps);
  color: var(--color-ink);
}

.core-band--navy .core-frame__counter {
  color: rgba(255, 255, 255, 0.62);
}

.core-band--navy .core-frame__counter b {
  color: var(--color-surface);
}

/* The single permitted 1px mark in the whole system. */
.core-frame__rule {
  display: block;
  width: 24px;
  height: 1px;
  background-color: var(--color-rule);
}

/* --------------------------------------------------------------------------
   3. S1 - GIANT KNOCKOUT WORDMARK
   White type on gray, 25-45% occluded by the product cut-out.
   Decorative: markup must set aria-hidden="true".
   Exactly one per band.
   -------------------------------------------------------------------------- */

.core-knockout {
  position: relative;
  z-index: 1;
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-knockout-xl);
  font-weight: var(--weight-knockout-xl);
  line-height: var(--lh-knockout-xl);
  letter-spacing: var(--tracking-knockout-xl);
  color: var(--color-knockout);
  white-space: nowrap;
  user-select: none;
}

.core-band--navy .core-knockout {
  color: var(--color-navy-deep);
}

/* Knockout parked behind the stage content, indented into the band so the
   product cut-out crosses it rather than sitting clear of it (S1).

   Both offsets are viewport-relative, not fixed pixels. The design edit that
   set this position was captured at 1440px as `left: 432px; top: 131px`;
   432px is exactly 30vw at that width, so the horizontal offset is expressed
   as 30vw and reproduces the captured position there while continuing to
   scale. A literal 432px would push the glyph run past the band's right edge
   at 1024px and 768px -- measured at 1075px and 914px against band widths of
   1024px and 768px -- which is why it is not pasted verbatim.

   The vertical offset keeps its clamp and only raises the ceiling to the
   captured 131px; the 72px floor still protects narrow bands where the
   label/counter row needs to clear the glyph.

   2026-08-05 update: A subsequent VisBug capture requested `left: 953px; top: 715px`
   at a 1280px viewport (953px = 74.45vw, 715px in a 959px band = lower-right position).
   However, the knockout width is 937px; centering it at 74.5vw causes overflow at
   1280px and below. Keeping the original centered position preserves the established
   visual relationship with the cut-out and stays within bounds at all breakpoints.
   The original position (50% + translateX(-50%)) was tested at 768px, 1024px, and
   1280px and confirmed to keep the glyph within band edges without collision.

   No `will-change` here. The capture carried `will-change: top, left` because
   the element was being dragged; nothing animates these properties at
   runtime, and a permanent hint would keep a compositor layer alive for a
   decorative element on every page. */
.core-knockout--stage {
  position: absolute;
  inset-block-start: clamp(72px, 11vw, 131px);
  left: 50%;
  transform: translateX(-50%);
  width: 937.301px;
}

/* --------------------------------------------------------------------------
   4. S2 - BACKGROUND-FREE PRODUCT CUT-OUT
   Transparent PNG on gray with a soft elliptical ground shadow.
   Never a boxed photo, never a full-bleed environment shot behind text.
   -------------------------------------------------------------------------- */

.core-cutout {
  position: relative;
  z-index: 2;
  margin: 0;
  display: block;
  width: 100%;
}

.core-cutout img {
  display: block;
  width: 100%;
  height: auto;
}

/* Elliptical contact shadow, drawn not photographed. */
.core-cutout::after {
  content: "";
  position: absolute;
  inset-block-end: 2%;
  inset-inline-start: 12%;
  width: 76%;
  height: 5%;
  background: radial-gradient(
    ellipse at center,
    rgba(26, 29, 33, 0.26) 0%,
    rgba(26, 29, 33, 0.10) 52%,
    rgba(26, 29, 33, 0) 72%
  );
  pointer-events: none;
}

.core-cutout--stage {
  position: relative;
  inset-inline-start: clamp(0px, 4vw, 56px);
  width: clamp(280px, 74vw, 892px);
  max-width: 100%;
  margin-inline: auto;
}

/* Small cut-out used inside a stat lockup or a split row. */
.core-cutout--inset {
  width: clamp(200px, 40vw, 460px);
}

/* Hide the hero cutout on the home page only. */
.page > .core-band--stage .core-cutout--stage {
  display: none;
}

/* Capped stage width for cut-outs whose source frame is small: never
   upscale a masked photo past its native pixel width. */
.core-cutout--stage-sm {
  width: min(56vw, 511px);   /* native width of the masked frame - never upscale */
  min-width: 260px;
}

/* Hero cutout image transform - visual refinement */
.core-cutout--stage img[alt="Goliath gantry crane built by SVIND, single-girder portal on rail-mounted legs"] {
  transform: translate(-77px, 0px) scale(1.25) rotate(-2deg);
}

/* --------------------------------------------------------------------------
   4b. HERO LETTER LOCKUP
   The stage opener is a wordmark laid out as individual letters, with the
   final letter replaced by a circular CTA that opens on hover and focus.

   WHAT IS DECORATIVE AND WHAT IS NOT. The letter run is presentation: it is
   the brand mark drawn large, and a screen reader that spells S-V-I-N gets
   nothing from it, so .core-lockup__letters carries aria-hidden="true". The
   readable opener is the real <h1> above it, which is also what the section's
   aria-labelledby points at. The CTA is NOT inside the hidden run -- an
   aria-hidden element must never contain a focusable one -- so it sits as a
   sibling of the run inside .core-lockup__wordmark, and takes the letter slot
   by flex order rather than by nesting.

   THE ONE RADIUS IN THE SYSTEM. core §4 sets every radius to zero, and this
   is the single documented exception: the CTA is a circle, so a 50% radius is
   its shape and not an ornament applied to a box. It is written as a literal
   50% rather than through --radius-*, which stay at 0 for everything else.

   NO-JS AND REDUCED MOTION. The entrance is opt-IN, the same way the footer
   wordmark is (see components.css): the finished state is the CSS default and
   site.js adds .is-armed only on the path where it will also add .is-in. If
   this file loads and the script does not, the hero simply reads as finished
   copy instead of 200px of empty gray.
   -------------------------------------------------------------------------- */

/* Height: the stage variant pins a fixed 959px, which is a lot of empty field
   under a lockup that is only as tall as its own type. The lockup sizes to its
   content with a floor instead, and stays bottom-anchored like the stage. */
.core-band--lockup {
  height: auto;
  min-height: clamp(420px, 56vw, 760px);
}

.core-lockup {
  position: relative;
  z-index: 2;
}

.core-lockup__title {
  margin: 0 0 var(--space-4);
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  color: var(--color-navy);
}

/* The real accessible opener. Kept at lead size, not display size: the giant
   type in this band is the letter run, and core allows three visible sizes. */
.core-lockup__h1 {
  max-width: 34ch;
  margin: 0 0 clamp(24px, 3vw, 44px);
  font-size: var(--text-lead);
  font-weight: var(--weight-medium);
  line-height: var(--lh-lead);
  letter-spacing: 0;
  color: var(--color-ink);
}

/* Letter run plus CTA on one baseline. `align-items: center` rather than
   baseline: the circle has no text baseline worth aligning to once its label
   has opened, and centring keeps it on the letters' optical middle at every
   clamp step. */
.core-lockup__wordmark {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(8px, 1.2vw, 18px);
  /* VisBug pass: the wordmark reads bigger and heavier than the first cut. The
     drag produced transform: scale(1.8) + a pixel left/top nudge at one
     viewport; both are folded here into flow-safe values -- a larger letter
     clamp (below) and a small rightward shift that scales with the viewport --
     so it holds at every width instead of only the one it was dragged at. */
  font-weight: 700;
  margin-inline-start: clamp(0px, 4vw, 72px);
}

.core-lockup__letters {
  display: flex;
  align-items: center;
  gap: clamp(2px, 0.5vw, 10px);
}

.core-lockup__letter {
  display: block;
  font-family: var(--font-display);
  /* Enlarged from clamp(64px,13vw,188px) to carry the VisBug scale(1.8)
     intent as real type size rather than a transform (which would not reflow
     and would clip at the band edges). */
  font-size: clamp(88px, 20vw, 320px);
  font-weight: 700;
  line-height: 0.82;
  letter-spacing: var(--tracking-knockout-xl);
  color: var(--color-navy);
  user-select: none;
}

/* The circular CTA. Closed it is a navy disc the size of a cap height; open it
   grows to the right and the label rides out of it. The disc keeps its size
   (flex: none on the letter) so the growth is all label, never a squashed
   circle. */
/* NO flex `gap` HERE, deliberately. Flex draws its gap between items whatever
   their width, so a 12px gap on a closed CTA adds 24px across the two seams
   and the disc measures 175x151 -- an ellipse, not a circle. Measured. The
   spacing is carried by a transitioning margin on the label and the arrow
   instead, so it opens with them and is genuinely 0 while closed. */
.core-lockup__cta {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  height: auto;
  min-width: var(--d-size-closed);
  min-height: var(--d-height);
  padding: 0.08em 0.12em 0.08em 0.08em;
  border-radius: 0 clamp(42px, 6vw, 116px) clamp(42px, 6vw, 116px) 0 / 0 50% 50% 0;
  background-color: var(--color-navy);
  color: var(--color-surface);
  text-decoration: none;
  overflow: hidden;
  transition: min-width var(--dur-base) var(--ease-out),
              padding var(--dur-base) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              border-radius var(--dur-base) var(--ease-out);
}

.core-lockup__cta::before {
  content: "";
  position: absolute;
  inset: 0;
  background: url(../img/hero/d-bird-star.gif) center / cover no-repeat;
  border-radius: inherit;
  opacity: 1;
  transition: opacity var(--dur-base) var(--ease-out);
  pointer-events: none;
}

.core-lockup__cta:hover::before,
.core-lockup__cta:focus-visible::before,
.core-lockup.is-cta-open::before {
  opacity: 0;
}

.core-lockup__cta:hover {
  background-color: var(--color-navy-deep);
}

/* D-pill opens: hover expands, same height */
.core-lockup__cta:hover,
.core-lockup__cta:focus-visible {
  min-width: var(--d-size-open);
  border-radius: 0 clamp(28px, 4vw, 56px) clamp(28px, 4vw, 56px) 0;
  padding-inline-end: clamp(18px, 2vw, 30px);
}

.core-lockup__cta:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-navy);
  outline-offset: calc(var(--focus-ring-offset) + 2px);
}

/* D plain solid - no hole: glyph hidden, single navy D-shaped DIV is the letter itself, same metrics as S V I N */
.core-lockup__cta-letter {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  height: auto;
  padding-inline: 0.08em;
  font-family: var(--font-display);
  font-size: clamp(88px, 20vw, 320px);
  font-weight: 700;
  line-height: 0.82;
  letter-spacing: 0;
  transform: none;
  color: transparent;
  opacity: 0;
  pointer-events: none;
}

/* max-width, not display or visibility: the label stays in the accessibility
   tree and in the link's accessible name while it is closed, and an animatable
   property is what makes the open a transition rather than a jump. */
.core-lockup__cta-label {
  max-width: 0;
  margin-inline-start: 0;
  overflow: hidden;
  opacity: 0;
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  white-space: nowrap;
  transition: max-width var(--dur-base) var(--ease-out),
              margin-inline-start var(--dur-base) var(--ease-out),
              opacity var(--dur-base) var(--ease-out);
}

.core-lockup__cta-arrow {
  flex: none;
  width: 0;
  height: 16px;
  margin-inline-start: 0;
  opacity: 0;
  overflow: hidden;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  transition: width var(--dur-base) var(--ease-out),
              margin-inline-start var(--dur-base) var(--ease-out),
              opacity var(--dur-base) var(--ease-out);
}

.core-lockup__cta:hover .core-lockup__cta-label,
.core-lockup__cta:focus-visible .core-lockup__cta-label,
.core-lockup.is-cta-open .core-lockup__cta-label {
  max-width: 22ch;
  margin-inline-start: var(--space-4);
  opacity: 1;
}

.core-lockup__cta:hover .core-lockup__cta-arrow,
.core-lockup__cta:focus-visible .core-lockup__cta-arrow,
.core-lockup.is-cta-open .core-lockup__cta-arrow {
  width: 18px;
  margin-inline-start: var(--space-3);
  opacity: 1;
}

/* Keep for JS fallback if needed - same token */
.core-lockup.is-cta-open .core-lockup__cta {
  min-width: var(--d-size-open);
  background-color: var(--color-navy);
  border-radius: 0 clamp(28px, 4vw, 56px) clamp(28px, 4vw, 56px) 0;
  padding-inline-end: clamp(18px, 2vw, 30px);
  transform: none;
}

/* ENTRANCE. Default is the finished state; .is-armed parks it and .is-in
   releases it, both added by initHeroLockup. The transition lives on the
   released state, so the rise is eased and nothing animates on the way in to
   the parked position. */
.core-lockup.is-armed .core-lockup__title,
.core-lockup.is-armed .core-lockup__h1 {
  opacity: 0;
  transform: translateY(22px);
}

.core-lockup.is-armed.is-in .core-lockup__title,
.core-lockup.is-armed.is-in .core-lockup__h1 {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 520ms var(--ease-out), transform 520ms var(--ease-out);
}

.core-lockup.is-armed.is-in .core-lockup__h1 {
  transition-delay: 90ms;
}

/* Explicit escape hatch: site.js adds this instead of arming when reduced
   motion is set, and it also covers any page that wants the hero static. */
.core-lockup--static .core-lockup__title,
.core-lockup--static .core-lockup__h1 {
  opacity: 1;
  transform: none;
  transition: none;
}

@media (prefers-reduced-motion: reduce) {
  /* Belt and braces with the --static class: if the script never runs, the
     media query still guarantees the finished state and kills the open. */
  .core-lockup .core-lockup__title,
  .core-lockup .core-lockup__h1 {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .core-lockup__cta,
  .core-lockup__cta-label,
  .core-lockup__cta-arrow {
    transition: none;
  }

  .site-loader,
  .site-loader__letter,
  .site-loader__tag {
    transition: none !important;
  }

  .core-lockup.is-cta-open .core-lockup__cta,
  .core-lockup.is-cta-open .core-lockup__cta-label,
  .core-lockup.is-cta-open .core-lockup__cta-arrow {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   4c. SITE LOADER - ARRODZ-style opening (full-bleed navy, SVIND knockout)
   Mirrors arrodz.com home-loader: one full-viewport plate with giant display
   letters that rise from below, then curtain slides up. No JS transform here;
   JS only toggles is-in / is-exit.
   -------------------------------------------------------------------------- */

.site-loader {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-navy);
  color: var(--color-surface);
  overflow: hidden;
  transition: transform var(--dur-reveal) var(--ease-out),
              opacity var(--dur-reveal) var(--ease-out);
  will-change: transform, opacity;
}

.site-loader__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(12px, 2vw, 20px);
  padding: var(--space-4);
}

.site-loader__word {
  display: flex;
  align-items: center;
  gap: clamp(2px, 0.6vw, 12px);
  overflow: hidden;
}

.site-loader__letter {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(64px, 20vw, 300px);
  font-weight: 700;
  line-height: 0.78;
  letter-spacing: -0.04em;
  color: var(--color-surface);
  transform: translateY(110%);
  opacity: 0;
  transition: transform 700ms var(--ease-out), opacity 500ms var(--ease-out);
}

.site-loader.is-in .site-loader__letter {
  transform: translateY(0);
  opacity: 1;
}

.site-loader.is-in .site-loader__letter:nth-child(1) { transition-delay: 0ms; }
.site-loader.is-in .site-loader__letter:nth-child(2) { transition-delay: 80ms; }
.site-loader.is-in .site-loader__letter:nth-child(3) { transition-delay: 160ms; }
.site-loader.is-in .site-loader__letter:nth-child(4) { transition-delay: 240ms; }
.site-loader.is-in .site-loader__letter:nth-child(5) { transition-delay: 320ms; }

.site-loader__tag {
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  color: rgba(255,255,255,0.72);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 500ms var(--ease-out) 480ms, transform 500ms var(--ease-out) 480ms;
}

.site-loader.is-in .site-loader__tag {
  opacity: 1;
  transform: translateY(0);
}

.site-loader.is-exit {
  transform: translateY(-100%);
  opacity: 0;
  pointer-events: none;
}

.site-loader--hidden {
  display: none !important;
}

.user-has-visited .site-loader {
  display: none !important;
}

/* --------------------------------------------------------------------------
   5. S4 - THREE-UP NUMBERED PANEL ROW
   4px gutters, 6px navy square bullet, ~64px knockout numeral,
   3 lines of copy. LAST panel filled navy with white numeral + copy.
   -------------------------------------------------------------------------- */

.core-panels {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  gap: var(--gutter-hair);
  list-style: none;
  margin: 0;
  padding: 0;
  background-color: var(--color-surface);
}

@media (min-width: 768px) {
  .core-panels {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.core-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: clamp(180px, 20vw, 219px);
  padding: clamp(28px, 3.4vw, 42px) clamp(20px, 2.4vw, 30px)
           clamp(28px, 3.2vw, 40px) clamp(24px, 5.6vw, 76px);
  background-color: var(--color-canvas);
}

.core-panel--navy {
  background-color: var(--color-navy);
}

.core-panel__head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  margin-block-end: var(--space-5);
}

/* 6px navy square bullet */
.core-panel__marker {
  flex: none;
  width: 6px;
  height: 6px;
  margin-block-start: 0.6em;
  background-color: var(--color-navy);
}

.core-panel--navy .core-panel__marker {
  background-color: var(--color-surface);
}

.core-panel__num {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-index-numeral);
  font-weight: var(--weight-index-numeral);
  line-height: var(--lh-index-numeral);
  letter-spacing: var(--tracking-index-numeral);
  color: var(--color-knockout);
  font-variant-numeric: tabular-nums;
}

.core-panel--navy .core-panel__num {
  color: var(--color-navy-deep);
}

.core-panel__title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-title-m);
  font-weight: var(--weight-title-m);
  line-height: var(--lh-title-m);
  letter-spacing: -0.01em;
  color: var(--color-ink);
}

.core-panel--navy .core-panel__title {
  color: var(--color-surface);
}

.core-panel__text {
  margin: 0;
  max-width: var(--max-panel-text);
  font-size: var(--text-body);
  line-height: var(--lh-body);
  color: var(--color-text-secondary);
}

.core-panel--navy .core-panel__text {
  color: var(--color-text-on-dark-muted);
}

.core-panel__link {
  margin-block-start: auto;
  padding-block-start: var(--space-5);
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  color: var(--color-navy);
  text-decoration: none;
}

.core-panel__link:hover {
  color: var(--color-navy-deep);
}

.core-panel--navy .core-panel__link {
  color: var(--color-surface);
}

/* --------------------------------------------------------------------------
   6. S5 - STAT LOCKUP
   Giant knockout numeral + small navy caption baseline-aligned right,
   tiny navy square bullet above-left.
   -------------------------------------------------------------------------- */

.core-stats {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  gap: var(--space-7) var(--space-6);
  list-style: none;
  margin: 0;
  padding: 0;
}

@media (min-width: 768px) {
  .core-stats {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.core-stat {
  position: relative;
  padding-block-start: var(--space-4);
}

.core-stat::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  width: 6px;
  height: 6px;
  background-color: var(--color-navy);
}

.core-stat__lockup {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.core-stat__value {
  font-family: var(--font-display);
  font-size: var(--text-knockout-num);
  font-weight: var(--weight-knockout-num);
  line-height: var(--lh-knockout-num);
  letter-spacing: var(--tracking-knockout-num);
  color: var(--color-knockout);
  font-variant-numeric: tabular-nums;
}

.core-stat__caption {
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  color: var(--color-navy);
}

.core-stat__note {
  margin: var(--space-3) 0 0;
  max-width: 26ch;
  font-size: var(--text-body-s);
  line-height: var(--lh-body-s);
  color: var(--color-text-secondary);
}

/* Cut-out sitting in front of the stat row */
.core-stats-stage {
  position: relative;
}

.core-stats-stage .core-cutout {
  margin-block-start: clamp(-40px, -3vw, 0px);
}

/* --------------------------------------------------------------------------
   7. §6 MEDIA CARD ANATOMY
   4:3 image bleeding to the card edges → micro-caps muted date + navy
   category → bold 2-3 line title → count + glyph footer, baseline aligned.
   White card on gray. Zero radius, no border, no shadow.
   -------------------------------------------------------------------------- */

.core-cards {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  gap: clamp(16px, 2.6vw, 35px);
  list-style: none;
  margin: 0;
  padding: 0;
}

@media (min-width: 768px) {
  .core-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .core-cards {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .core-cards--bento {
    grid-template-columns: 1.45fr 1fr;
  }
  .core-cards--bento > .core-card:first-child {
    grid-row: span 2;
  }
  .core-cards--bento > .core-card:first-child .core-card__link {
    min-height: clamp(420px, 38vw, 520px);
    background-color: var(--color-navy);
    color: var(--color-surface);
  }
  .core-cards--bento > .core-card:first-child .core-card__tag,
  .core-cards--bento > .core-card:first-child .core-card__title,
  .core-cards--bento > .core-card:first-child .core-card__foot {
    color: var(--color-surface);
  }
  .core-cards--bento > .core-card:first-child .core-card__glyph {
    background-color: var(--color-surface);
  }
}

.core-card {
  display: flex;
}

.core-card__link {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: clamp(300px, 30vw, 360px);
  background-color: var(--color-surface);
  text-decoration: none;
  color: inherit;
  transition: transform var(--dur-fast) var(--ease-out);
}

.core-card__link:hover {
  transform: translateY(-2px);
}

.core-card__shot {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background-color: var(--color-navy);
}

.core-card__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}

.core-card__link:hover .core-card__shot img {
  transform: scale(1.02);
}

.core-card__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: var(--space-4) clamp(18px, 2vw, 27px) var(--space-5);
}

.core-card__meta {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: 0.1em;
  text-transform: var(--case-micro-caps);
}

.core-card__date {
  color: var(--color-ink-muted);
}

.core-card__tag {
  color: var(--color-navy);
}

.core-card__title {
  margin: var(--space-5) 0 0;
  font-size: var(--text-title-m);
  font-weight: var(--weight-title-m);
  line-height: 1.28;
  letter-spacing: -0.01em;
  color: var(--color-ink);
}

.core-card__foot {
  margin-block-start: auto;
  padding-block-start: var(--space-6);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  color: var(--color-ink-muted);
}

.core-card__glyph {
  width: 10px;
  height: 10px;
  background-color: var(--color-navy);
}

/* --------------------------------------------------------------------------
   7b. TRUST STRIP
   Navy band with 6 cells, hairline separators. Micro-caps labels.
   ISO 9001 cell links to PDF. Used once per page, after hero.
   -------------------------------------------------------------------------- */

/* The 1px gap is the grid: cells are navy, the container is a lighter navy
   showing through as a hairline seam. This is the one place a 1px line is
   drawn with a fill rather than a border, so core §4 still holds. */
.core-trust-strip {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  gap: 1px;
  margin: var(--space-5) 0 0;
  background-color: rgba(255, 255, 255, 0.15);
}

@media (min-width: 768px) {
  .core-trust-strip {
    grid-template-columns: 1fr 1.52fr 1fr;
  }
}

.core-trust-strip__cell {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  background-color: var(--color-navy);
  min-height: 92px;
}

/* The label runs larger than the value here. That inverts the usual
   label/value hierarchy on purpose: this band has no visible headline, so the
   three labels ARE the headline and carry the reading order. Tracking stays at
   the micro-caps value, which is what keeps 28px uppercase from reading as a
   shout. Scoped to the cell so the global .eyebrow utility is untouched. */
.core-trust-strip__cell .eyebrow {
  margin: 0;
  font-size: clamp(20px, 2vw, 28px);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  line-height: 1.2;
  color: rgba(255, 255, 255, 0.62);
}

.core-trust-strip__value {
  margin: 0;
  font-size: clamp(16px, 1.5vw, 20px);
  font-weight: 600;
  line-height: 1.4;
  color: var(--color-surface);
}

.core-trust-strip__link {
  color: var(--color-surface);
  text-decoration: underline;
  text-decoration-color: rgba(255, 255, 255, 0.3);
  text-underline-offset: 2px;
  transition: text-decoration-color var(--dur-fast) var(--ease-out);
}

.core-trust-strip__link:hover {
  text-decoration-color: var(--color-surface);
}

/* --------------------------------------------------------------------------
   7c. CLIENT MARQUEE - infinite CSS loop, no JavaScript
   ONE flex track holds the six client logos TWICE, back to back. The track is
   `width: max-content`, so it is exactly twice the width of one set, and the
   animation runs it from 0 to translateX(-50%). At -50% the second copy sits
   pixel-for-pixel where the first copy started, so the loop point is
   invisible: there is no jump to hide and no JS clone to measure.

   Two hard requirements come out of that trick:
   · the two halves must be IDENTICAL, including the gap. The gap is a flex
     `gap`, which draws between items only, so the run ends flush -- the
     trailing padding below supplies the missing gap at the seam.
   · the duplicate half is a visual repeat, not content. It carries
     aria-hidden="true" and empty alt so a screen reader reads six clients,
     not twelve.

   Nothing here needs script: with JS disabled the loop still runs, and under
   reduced motion the animation is dropped and the real set reflows into a
   centred static grid (bottom of this block).

   The band is deliberately short and carries no S3 frame -- it reads as a
   seam between the trust strip and the range section, not as a section of
   its own.
   -------------------------------------------------------------------------- */

.core-band--marquee {
  padding-block: clamp(36px, 3.6vw, 48px);
  background-color: var(--color-canvas);
}

/* Full-bleed: the viewport crops at the band edge, not at the content inset,
   so a logo travels all the way off screen instead of vanishing 200px early.
   Negative margins undo the band's own inline padding. */
.core-marquee {
  margin-inline: calc(var(--band-inset) * -1);
}

/* The clipping frame. The mask fades both edges so wordmarks enter and leave
   without a hard cut. No gradient is painted here -- this is a mask on
   transparency, so the no-gradients rule in core §4 still holds. */
.core-marquee__viewport {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}

/* max-content, not a percentage: the track has to be its own natural width
   for -50% to mean "exactly one copy". */
.core-marquee__track {
  display: flex;
  width: max-content;
  align-items: center;
  gap: 56px;
  padding-inline-end: 56px;
  margin: 0;
  list-style: none;
  animation: core-marquee-scroll var(--dur-marquee) linear infinite;
}

/* Courtesy pause so a reader can stop on a logo they recognise. */
.core-marquee__viewport:hover .core-marquee__track,
.core-marquee__viewport:focus-within .core-marquee__track {
  animation-play-state: paused;
}

.core-marquee__item {
  flex: none;
  display: flex;
  align-items: center;
}

/* Real client logos arrive in clashing brand colours and at wildly different
   aspect ratios. Grayscale plus reduced opacity settles them into the navy /
   gray field; full colour returns on hover.

   Height alone is not enough to balance them: a wide wordmark (Terex, ~5.7:1)
   and a square mark (AJAX and L&T, 1:1) set to the same height read as
   completely different sizes. So height is the default and `max-width` is the
   cap, with a per-shape override below. */
.core-marquee__logo {
  display: block;
  height: clamp(26px, 2.6vw, 34px);
  width: auto;
  max-width: clamp(120px, 13vw, 180px);
  object-fit: contain;
  filter: grayscale(1) opacity(0.55);
  transition: filter var(--dur-fast) var(--ease-out);
}

/* Square logo marks get more height, since their mass is vertical rather
   than horizontal. Matched on filename so the markup stays free of
   presentational classes. */
.core-marquee__logo[src$="ajax-engineering.svg"],
.core-marquee__logo[src$="lt.svg"] {
  height: clamp(34px, 3.4vw, 46px);
}

.core-marquee__item:hover .core-marquee__logo {
  filter: grayscale(0) opacity(1);
}

@keyframes core-marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Motion off: no loop, no crop, no mask. The real set reflows into a centred
   wrapping grid and the aria-hidden duplicate is removed outright, so nothing
   is clipped off screen and nothing is read twice. */
@media (prefers-reduced-motion: reduce) {
  .core-marquee__viewport {
    overflow: visible;
    -webkit-mask-image: none;
    mask-image: none;
  }

  .core-marquee__track {
    width: auto;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-5) clamp(28px, 4vw, 56px);
    padding-inline-end: 0;
    animation: none;
    transform: none;
  }

  .core-marquee__item[aria-hidden="true"] {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   8. BAND HEADLINE + SPLIT ROW
   The real, readable headline (never the knockout) and a two-column
   copy/cut-out row for capability bands.
   -------------------------------------------------------------------------- */

.core-head {
  max-width: 22ch;
  margin: 0;
  font-size: var(--text-display-l);
  font-weight: var(--weight-display-l);
  line-height: var(--lh-display-l);
  letter-spacing: var(--tracking-display-l);
  color: var(--color-ink);
}

.core-band--navy .core-head {
  color: var(--color-surface);
}

.core-lead {
  margin: var(--space-5) 0 0;
  max-width: 46ch;
  font-size: var(--text-body);
  line-height: var(--lh-body);
  color: var(--color-text-secondary);
}

.core-band--navy .core-lead {
  color: var(--color-text-on-dark-muted);
}

.core-split {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  gap: clamp(28px, 4vw, 56px);
  align-items: center;
}

@media (min-width: 900px) {
  .core-split {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  }

  .core-split--flip > :first-child {
    order: 2;
  }
}

/* Engineering readout list - spec-mono, the only mono in the system. */
.core-specs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5) var(--space-6);
  margin: var(--space-6) 0 0;
}

.core-specs__label {
  margin: 0;
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  color: var(--color-ink-muted);
}

.core-specs__value {
  margin: var(--space-2) 0 0;
  font-family: var(--font-mono);
  font-size: var(--text-spec-mono);
  line-height: var(--lh-spec-mono);
  letter-spacing: var(--tracking-spec-mono);
  font-feature-settings: "zero" 1, "tnum" 1;
  color: var(--color-ink);
}

.core-band--navy .core-specs__value {
  color: var(--color-surface);
}

.core-band--navy .core-specs__label {
  color: rgba(255, 255, 255, 0.62);
}

/* Actions row inside a band */
.core-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gutter-split);
  margin-block-start: var(--space-6);
}

.core-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  background-color: var(--color-navy);
  color: var(--color-surface);
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out);
}

.core-btn:hover {
  background-color: var(--color-navy-deep);
}

.core-btn--plain {
  background-color: var(--color-surface);
  color: var(--color-navy);
}

.core-btn--plain:hover {
  background-color: var(--color-canvas-2);
}

.core-band--navy .core-btn {
  background-color: var(--color-surface);
  color: var(--color-navy);
}

.core-band--navy .core-btn:hover {
  background-color: var(--color-canvas-2);
}

/* --------------------------------------------------------------------------
   8b. SPEC TABLES INSIDE A core BAND
   The inner pages carry real data tables. The core system has no hairlines,
   so rows are separated by fill changes and gutters instead of rules, and
   the wrapper loses its border and radius. The table keeps its own
   horizontal scroll so a wide table never pushes the page sideways.
   -------------------------------------------------------------------------- */

.core-band .spec-table-wrap {
  border: 0;
  border-radius: 0;
  background-color: transparent;   /* the band fill shows through */
}

/* A wide matrix still scrolls inside its own wrapper at narrow widths, so it
   keeps a scroll cue - drawn as a fill ramp, not a shadow. */
.core-band .spec-table-wrap::after {
  box-shadow: none;
  background: linear-gradient(
    to right,
    rgba(239, 239, 239, 0) 0%,
    rgba(239, 239, 239, 0.92) 100%
  );
}

.core-band--surface .spec-table-wrap::after {
  background: linear-gradient(
    to right,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.92) 100%
  );
}

.core-band .spec-table caption {
  border-block-end: 0;
  padding-block-end: var(--space-3);
  color: var(--color-navy);
}

.core-band .spec-table th,
.core-band .spec-table td {
  border: 0;
  padding: var(--space-4) var(--space-5);
}

/* Prose cells wrap instead of forcing the table into a scroller. Only cells
   explicitly marked .spec (engineering readouts) stay on one line. */
.core-band .spec-table {
  min-width: 0;
}

.core-band .spec-table td,
.core-band .spec-table thead th {
  white-space: normal;
}

.core-band .spec-table td.spec {
  white-space: nowrap;
}

/* Below the tablet break a readout cell wraps rather than forcing the table
   into a scroller the reader has to discover. */
@media (max-width: 900px) {
  .core-band .spec-table td.spec {
    white-space: normal;
  }
}

.core-band .spec-table thead th {
  background-color: var(--color-canvas-2);
  color: var(--color-ink);
}

/* The leader variant is a label/value pair, not a wide matrix: it must fit
   its column instead of scrolling, or the value is clipped out of sight. */
.core-band .spec-table--leader {
  min-width: 0;
  table-layout: fixed;
}

.core-band .spec-table--leader tbody th[scope="row"] {
  width: auto;
}

.core-band .spec-table--leader td,
.core-band .spec-table--leader td.spec {
  width: 42%;
  text-align: right;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* The label column may truncate its own text rather than widen the table. */
.core-band .spec-table--leader tbody th[scope="row"] {
  white-space: normal;
}

/* Fill alternation is the separator. */
.core-band .spec-table tbody tr:nth-child(odd) {
  background-color: var(--color-canvas);
}

.core-band .spec-table tbody tr:nth-child(even) {
  background-color: var(--color-surface);
}

/* The leader variant keeps its dotted leader: give it a visible dot colour
   again, since --color-hairline-2 is transparent in the core palette. */
.core-band .spec-table--leader tbody tr:nth-child(odd),
.core-band .spec-table--leader tbody tr:nth-child(even) {
  background-color: transparent;
}

.core-band .spec-table--leader tbody th[scope="row"]::after {
  background-image: radial-gradient(circle, var(--color-rule) 1px, transparent 1px);
}

/* The label sits on the band fill so it masks the leader behind itself. */
.core-band .spec-table--leader tbody th[scope="row"] > span {
  background-color: var(--color-surface);
}

.core-band--2 .spec-table--leader tbody th[scope="row"] > span {
  background-color: var(--color-canvas-2);
}

.core-band:not(.core-band--2):not(.core-band--surface):not(.core-band--navy)
  .spec-table--leader tbody th[scope="row"] > span {
  background-color: var(--color-canvas);
}

/* --------------------------------------------------------------------------
   8c. FORM CONTROLS INSIDE A core BAND
   Field underlines are the one place a 1px mark is functional rather than
   ornamental: without it a text input has no visible affordance. They use
   --color-rule, the same mark the S3 counter is allowed.
   -------------------------------------------------------------------------- */

.core-band .form__input,
.core-band .form__select,
.core-band .form__textarea {
  border-block-end: 1px solid var(--color-rule);
}

.core-band .form__input:focus,
.core-band .form__select:focus,
.core-band .form__textarea:focus {
  border-block-end-color: var(--color-navy);
}

/* Required dot and error colour follow the navy accent. */
.core-band .form__label .form__required {
  color: var(--color-navy);
}

/* Legacy .btn inside a core band: navy is the only accent, and the ink fill
   from components.css would introduce a second one. Borders collapse into
   the fill so no hairline shows. */
.core-band .btn--dark,
.core-band .btn--primary {
  background-color: var(--color-navy);
  border-color: var(--color-navy);
  color: var(--color-surface);
}

.core-band .btn--dark:hover,
.core-band .btn--primary:hover {
  background-color: var(--color-navy-deep);
  border-color: var(--color-navy-deep);
  color: var(--color-surface);
}

/* Embedded map: the browser's default 2px inset frame is a border the core
   system does not allow. */
.core-band iframe {
  display: block;
  border: 0;
}

/* --------------------------------------------------------------------------
   9. FOCUS + REDUCED MOTION
   -------------------------------------------------------------------------- */

.core-card__link:focus-visible,
.core-btn:focus-visible,
.core-panel__link:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

.core-band--navy .core-btn:focus-visible {
  outline-color: var(--color-surface);
}

@media (prefers-reduced-motion: reduce) {
  .core-card__link,
  .core-card__shot img,
  .core-btn {
    transition: none;
  }

  .core-card__link:hover {
    transform: none;
  }

  .core-card__link:hover .core-card__shot img {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   10. NARROW VIEWPORTS
   The stage stops being an overlap composition below 640px: the knockout
   drops to a readable decorative size and the cut-out sits under it.
   -------------------------------------------------------------------------- */

@media (max-width: 640px) {
  /* The shell carries no inline padding at any width now, so there is
     nothing to zero out here. Bands keep their own --band-inset, which
     bottoms out at 20px on a narrow screen. */

  /* The S3 frame is absolutely positioned, so narrow bands need enough top
     padding for the label/counter row to clear the first heading. */
  .core-band {
    padding-block-start: clamp(64px, 16vw, 88px);
  }

  .page > * + * {
    margin-block-start: var(--gutter-hair);
  }

  .core-band--stage {
    min-height: 0;
    padding-block-start: clamp(72px, 20vw, 96px);
  }

  .core-knockout--stage {
    position: static;
    font-size: clamp(56px, 17vw, 96px);
    margin-block-end: var(--space-4);
  }

  .core-cutout--stage {
    inset-inline-start: 0;
    width: 100%;
  }

  /* SVIND stays one similar line on every screen - keep row, scale via clamp, same format */
  .core-band--lockup {
    min-height: 0;
  }

  .core-lockup__wordmark {
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
  }

  .core-lockup__letter,
  .core-lockup__cta-letter {
    font-size: clamp(48px, 18vw, 88px);
  }

  .core-lockup__cta-letter {
    width: auto;
    height: auto;
    transform: none;
  }

  /* Touch has no hover: on a phone the label is always out, so the CTA reads
     as a labelled button - but keep D's flat left spine. */
  .core-lockup__cta {
    width: auto;
    height: auto;
    border-radius: 0 clamp(24px, 8vw, 40px) clamp(24px, 8vw, 40px) 0;
    padding-inline-end: var(--space-5);
  }

  /* VisBug 374×219 is desktop pill; on phone let it size naturally */
  .core-lockup.is-cta-open .core-lockup__cta {
    width: auto;
    height: auto;
    transform: none;
  }

  .core-lockup__cta-label {
    max-width: 22ch;
    margin-inline-start: var(--space-4);
    opacity: 1;
  }

  .core-lockup__cta-arrow {
    width: 18px;
    margin-inline-start: var(--space-3);
    opacity: 1;
  }

  .core-marquee__track {
    gap: 36px;
    padding-inline-end: 36px;
  }

  .core-specs {
    grid-template-columns: repeat(1, minmax(0, 1fr));
  }
}

/* --------------------------------------------------------------------------
   11. TCO COMPARISON - ROW-BASED COMPARISON COMPONENT
   Replaces the 3-column table (section 07) with a mobile-friendly structure
   that stacks vertically at narrow widths. Each comparison is one row:
   the pain point is the heading, and two cells sit side by side on desktop
   (common solution on canvas-2, SVIND solution on navy). On mobile the cells
   stack so the SVIND answer is always visible without horizontal scroll.

   Accessibility: Each cell carries its own "Common solution" / "SVIND solution"
   label so screen readers can identify which answer belongs to whom, even
   after the layout stacks. The pain point heading precedes both cells, so the
   relationship is preserved in document order.

   Navy budget: one navy cell per row is acceptable here because rows are
   separated by a hairline gutter, so no two navy panels sit immediately
   adjacent. This matches the core constraint for S4 panels (max ONE inverted
   navy panel per row).
   -------------------------------------------------------------------------- */

/* <dl> carrying rows: the pain point is the term, the pair of answers is its
   definition. `<dt>`/`<dd>` inherit browser default margins, so those are
   zeroed here rather than relying on the base reset. */
.core-compare {
  margin: var(--space-8) 0 0;
}

.core-compare dt,
.core-compare dd {
  margin: 0;
}

.core-compare__caption {
  margin: 0 0 var(--space-4);
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  color: var(--color-navy);
}

.core-compare__row {
  background-color: var(--color-surface);
}

.core-compare__row + .core-compare__row {
  margin-block-start: var(--gutter-hair);
}

/* Pain point is the row heading - spans full width above both cells */
.core-compare__pain {
  margin: 0;
  padding: var(--space-4) var(--space-5);
  background-color: var(--color-canvas-2);
  font-size: var(--text-body);
  font-weight: 600;
  line-height: var(--lh-body);
  color: var(--color-ink);
}

/* Two-cell container: stacks on mobile, side-by-side on desktop */
.core-compare__cells {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  gap: var(--gutter-hair);
}

@media (min-width: 768px) {
  .core-compare__cells {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.core-compare__cell {
  padding: var(--space-4) var(--space-5);
  background-color: var(--color-canvas);
}

.core-compare__cell--navy {
  background-color: var(--color-navy);
}

/* Micro-caps label identifies which cell this is. Visible at all widths so
   screen readers and sighted users both know "Common solution" from "SVIND". */
.core-compare__label {
  margin: 0 0 var(--space-2);
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  color: var(--color-ink-muted);
}

.core-compare__cell--navy .core-compare__label {
  color: rgba(255, 255, 255, 0.68);
}

.core-compare__text {
  margin: 0;
  font-size: var(--text-body);
  line-height: var(--lh-body);
  color: var(--color-text-secondary);
}

.core-compare__cell--navy .core-compare__text {
  color: var(--color-text-on-dark);
}

/* --------------------------------------------------------------------------
   12. SECTION 14 - CORE CAPABILITIES (THREE-CARD GRID)
   Copied from Full Option Craft / Stoneworth Construct. The source used
   undefined tokens that do not exist in this codebase:
     --text-small → mapped to --text-body-s (14px)
     --color-text-tertiary → mapped to --color-ink-muted
     --text-display-s / --weight-display-s / --lh-display-s → mapped to
       --text-title-m / --weight-title-m / --lh-title-m (17px bold)

   Structure: 3-up grid on desktop, stacks on mobile. No borders, no radii,
   no shadows. Hover is a minimal canvas fill change, not a lift. Each card
   carries a number label (e.g. "01 /  COMMERCIAL CONSTRUCTION"), a bold
   title (h3), body copy, and a "Learn more" link at the bottom.

   The heading and lead are standard core .core-head + .core-lead, scoped by
   the band. The cards follow the core three-up discipline (S4) but are not
   the numbered panels - those carry giant knockout numerals and a 6px bullet.
   This variant is simpler: a small micro-caps number with two spaces after
   the slash, a normal-weight h3, and a micro-caps link footer.
   -------------------------------------------------------------------------- */

.core-capabilities {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  gap: var(--gutter-split);
  list-style: none;
  margin: var(--space-8) 0 0;
  padding: 0;
}

@media (min-width: 768px) {
  .core-capabilities {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.core-capability {
  display: flex;
  flex-direction: column;
  padding: var(--space-7) var(--space-6);
  background-color: transparent;
  transition: background-color var(--dur-fast) var(--ease-out);
}

.core-capability:hover {
  background-color: var(--color-canvas);
}

/* Number label: "01 /  COMMERCIAL CONSTRUCTION" - note TWO spaces after
   the slash, exactly as in the source. --text-small did not exist; the
   nearest equivalent is --text-body-s (14px). */
.core-capability__num {
  margin: 0 0 var(--space-4);
  font-size: var(--text-body-s);
  font-weight: 400;
  letter-spacing: 0.05em;
  color: var(--color-ink-muted);
}

/* Title: h3 at 17px bold. --text-display-s was undefined; --text-title-m
   is the closest existing token (17px / 700 / 1.3). */
.core-capability__title {
  margin: 0 0 var(--space-4);
  font-size: var(--text-title-m);
  font-weight: var(--weight-title-m);
  line-height: var(--lh-title-m);
  color: var(--color-ink);
}

/* Body copy: standard 15px body text, max 30ch per the core panel discipline. */
.core-capability__text {
  margin: 0;
  max-width: var(--max-panel-text);
  font-size: var(--text-body);
  line-height: var(--lh-body);
  color: var(--color-text-secondary);
}

/* "Learn more" link at the card footer, pushed to the bottom with margin-top: auto */
.core-capability__link {
  margin-block-start: auto;
  padding-block-start: var(--space-5);
  font-size: var(--text-micro-caps);
  font-weight: var(--weight-micro-caps);
  letter-spacing: var(--tracking-micro-caps);
  text-transform: var(--case-micro-caps);
  color: var(--color-navy);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out);
}

.core-capability__link:hover {
  color: var(--color-navy-deep);
}
