/* ============================================================
   FIBRE CONVERTERS — "PRESS PROOF"
   Generated by Frontend Wireframe Engine, Phase 4
   DNA Hash: 48d82110775e
   Do not edit by hand. Regenerate via the engine.

   typography  technical-mono-forward
   components  terminal-monospace (structure only; colour from brand lock)
   layout      alternating-full-contained
   hero        full-bleed-text-overlay
   button      fill-slide-left
   imagery     photography-documentary
   animation   micro-interaction-rich
   spacing     baseline-grid-strict (24px)
   color       high-contrast-accessible (brand-locked, palette_intent: logo)
   navigation  sub-nav-bar
   texture     halftone-print
   ============================================================ */

:root {
  /* ---- Typography ---- */
  --font-heading: "Martian Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --font-body: "Inter", system-ui, -apple-system, sans-serif;
  --font-mono: "Martian Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --scale-ratio: 1.25;
  --heading-weight: 700;
  --heading-case: uppercase;
  --heading-letterspacing: 0em;
  --heading-line-height: 1.14;
  --body-size: 16px;
  --body-weight: 400;
  --body-line-height: 1.65;
  --body-letterspacing: 0em;
  --max-line-length: 72ch;

  /* ---- Colour: brand-locked to the logo extraction ----
     #0da5b4 is 2.98:1 on white and CANNOT carry text. It is a GROUND with ink
     knocked in (6.26:1). --teal-deep carries teal-coloured text on paper. */
  --color-brand-primary: #0da5b4;
  --color-brand-secondary: #076b76;
  --color-accent: #37af4a;

  --color-bg-base: #ffffff;
  --color-bg-elevated: #f4f6f6;
  --color-bg-card: #ffffff;
  --color-bg-invert: #111315;

  --color-text-primary: #111315;
  --color-text-secondary: #4a5457;
  --color-text-on-invert: #ffffff;
  --color-text-muted-invert: #c3cbcd;   /* 11.3:1 on ink. Was #a8b3b6 at 8.68:1 */

  --color-border: #d5dbdc;
  --color-border-invert: #2c3235;
  --color-focus-ring: #111315;

  /* ---- Spacing: strict 24px baseline ----
     Section padding is deliberately ASYMMETRIC. A uniform 144px top and bottom
     put roughly 290px of dead ground between every two bands, which read as a
     gap rather than as breathing room, most visibly where a dark band hands off
     to a white one. Top is now 3 baseline units and bottom 4, so content sits
     high in its band and the handoff tightens. Every value is still a multiple
     of 24. */
  --spacing-base: 24px;
  --spacing-section: 144px;          /* retained for reference, no longer applied */
  --spacing-section-top: 72px;       /* 3 units */
  --spacing-section-bottom: 96px;    /* 4 units */
  --spacing-section-top-mobile: 48px;    /* 2 units */
  --spacing-section-bottom-mobile: 72px; /* 3 units */
  --spacing-content-desktop: 72px;
  --spacing-content-mobile: 24px;
  --spacing-paragraph: 24px;
  --spacing-component: 48px;

  /* ---- Components: terminal-monospace structure, brand colour ---- */
  --radius: 0px;
  --radius-DEFAULT: 0px;
  --border: 1px solid var(--color-border);
  --card-padding: 24px;

  /* ---- Layout ---- */
  --layout-max-width: 1400px;
  --layout-contained-width: 1080px;
  --layout-whitespace-ratio: 0.40;

  /* ---- Motion: animation-craft floor tokens ---- */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
  --transition-speed: 180ms;
  --transition-easing: var(--ease-out);
  --entrance-duration: 520ms;
  --stagger-delay: 60ms;
  --control-speed: 160ms;

  /* ---- Reference strings ---- */
  --texture-type: "halftone-print";
  --nav-type: "sub-nav-bar";
  --hero-archetype: "full-bleed-text-overlay";
  --btn-archetype: "fill-slide-left";
}

/* ============================================================
   BASE
   ============================================================ */

html { scroll-behavior: smooth; }

body {
  background-color: var(--color-bg-base);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: var(--body-size);
  font-weight: var(--body-weight);
  line-height: var(--body-line-height);
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--color-brand-primary); color: var(--color-text-primary); }

:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 3px;
}
.on-invert :focus-visible { outline-color: var(--color-brand-primary); }

/* ============================================================
   TYPE SCALE
   Martian Mono is a wide face. The scale is deliberately restrained so
   headlines hold 2 lines maximum at every breakpoint.
   ============================================================ */

/* Keeps a multi-word process name from splitting across a line break, so
   "Die Cutting" never leaves "Die" orphaned at the end of a line. Applied to
   the unit, not the whole headline, so the headline still wraps responsively. */
.nb { white-space: nowrap; }

.t-display {
  font-family: var(--font-heading);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0em;
  line-height: 1.06;
  font-size: clamp(1.95rem, 5.1vw, 4rem);
}
.t-h2 {
  font-family: var(--font-heading);
  font-weight: 700;
  text-transform: uppercase;
  line-height: 1.16;
  font-size: clamp(1.35rem, 2.9vw, 2.15rem);
}
.t-h3 {
  font-family: var(--font-heading);
  font-weight: 600;
  text-transform: uppercase;
  line-height: 1.24;
  font-size: clamp(1.02rem, 1.65vw, 1.22rem);
}
.t-h4 {
  font-family: var(--font-heading);
  font-weight: 600;
  text-transform: uppercase;
  line-height: 1.3;
  font-size: 0.94rem;
}

/* The spec/data role. Martian Mono doing what a monospace exists to do:
   columns of figures that line up because every glyph is the same width. */
.t-data {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  letter-spacing: 0em;
}
.t-label {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-secondary);
}
.on-invert .t-label { color: var(--color-text-muted-invert); }

/* ---- Dark-ground text guard ----
   These utilities resolve to dark values meant for a paper ground. Used inside
   an inverted band they measured 2.39:1 and 2.99:1 against the ink, which is
   unreadable and well under the 4.5:1 floor. Rather than hunt every instance by
   hand, the inverted context re-points them, so the failure cannot recur as new
   sections are added. */
.on-invert .text-ink-soft,
.on-invert .text-ink { color: var(--color-text-muted-invert) !important; }
.on-invert .text-teal-deep { color: var(--color-brand-primary) !important; }

.t-lead {
  font-size: clamp(1.02rem, 1.5vw, 1.16rem);
  line-height: 1.6;
  color: var(--color-text-secondary);
  max-width: 62ch;
}
.on-invert .t-lead {
  color: var(--color-text-muted-invert);
  font-size: clamp(1.06rem, 1.55vw, 1.2rem);
  line-height: 1.66;
}

.t-body { max-width: var(--max-line-length); }

/* ============================================================
   LAYOUT ARCHETYPE: alternating-full-contained
   Distinguishing feature 1: the width alternation is strict and immediately
   noticeable. .band-full is edge to edge; .band-contained is 1080px.
   Distinguishing feature 3: the width change IS the separation. No dividers
   are emitted between bands.
   ============================================================ */

.band-full {
  width: 100%;
  padding-top: var(--spacing-section-top-mobile);
  padding-bottom: var(--spacing-section-bottom-mobile);
  padding-inline: var(--spacing-content-mobile);
  position: relative;
}
/* The gutter is expressed as width, not padding, so it can never reach zero.
   The previous rule zeroed padding-inline at 1024px while capping max-width at
   1080px, which meant that between 1024px and 1080px of viewport the content
   ran edge to edge with no gutter at all and text touched the screen. */
.band-contained {
  width: min(100% - (var(--spacing-content-mobile) * 2), var(--layout-contained-width));
  margin-inline: auto;
  padding-top: var(--spacing-section-top-mobile);
  padding-bottom: var(--spacing-section-bottom-mobile);
  padding-inline: 0;
}
@media (min-width: 1024px) {
  .band-full {
    padding-top: var(--spacing-section-top);
    padding-bottom: var(--spacing-section-bottom);
    padding-inline: var(--spacing-content-desktop);
  }
  .band-contained {
    width: min(100% - 96px, var(--layout-contained-width));
    padding-top: var(--spacing-section-top);
    padding-bottom: var(--spacing-section-bottom);
    padding-inline: 0;
  }
}
/* Distinguishing feature 2: full-bleed bands carry imagery or a strong ground;
   contained bands stay white or the cool off-white. */
.band-full--ink { background: var(--color-bg-invert); color: var(--color-text-on-invert); }
.band-full--teal { background: var(--color-brand-primary); color: var(--color-text-primary); }
.band-contained--alt { background: var(--color-bg-elevated); }

.band-inner { max-width: var(--layout-max-width); margin-inline: auto; }

/* Grid and flex children default to min-width:auto, which lets a long word push
   a track wider than its container and produce horizontal scroll. */
.band-inner [class*="grid-cols"] > *,
.band-contained [class*="grid-cols"] > * { min-width: 0; }

/* Distinguishing feature 4: contained bands read intimate, full bands expansive.
   The measure is capped inside contained bands only. */
.band-contained .t-body { max-width: 68ch; }

/* ============================================================
   TEXTURE: halftone-print
   Deployed as PROCESS halftone, not pop art. Low-opacity dot screens in the
   two ink channels. The data file's warm #faf8f5 ground is overridden to a
   true neutral: this client rejected a warm background outright in a prior
   engagement. No misregistration offset is used anywhere; on a precision
   manufacturer a misregistered element reads as a defect, not as craft.
   ============================================================ */

.halftone {
  position: relative;
  isolation: isolate;
}
.halftone::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(circle, currentColor 1px, transparent 1px);
  background-size: 8px 8px;
  opacity: 0.10;
  pointer-events: none;
}
.halftone--teal::before { color: var(--color-brand-primary); opacity: 0.22; }
.halftone--green::before { color: var(--color-accent); opacity: 0.20; }
.halftone--fine::before { background-size: 5px 5px; }
.halftone--coarse::before { background-size: 12px 12px; }

/* Ink coverage ramp. Dot size encodes density, which is how a halftone
   actually carries tone: 10 percent coverage through to solid. */
.ink-ramp { display: flex; gap: 2px; align-items: flex-end; }
.ink-ramp span {
  display: block;
  width: 22px; height: 22px;
  background-image: radial-gradient(circle, var(--color-brand-primary) var(--dot), transparent var(--dot));
  background-size: 6px 6px;
  border: 1px solid var(--color-border);
}
.on-invert .ink-ramp span { border-color: var(--color-border-invert); }

/* Registration marks. Crosshairs, never a bar: a short horizontal rule beside
   a label reproduces the em-dash tell without using the character. */
.reg-mark {
  position: absolute;
  width: 14px; height: 14px;
  opacity: 0.55;
  pointer-events: none;
}
.reg-mark::before, .reg-mark::after {
  content: "";
  position: absolute;
  background: currentColor;
}
.reg-mark::before { left: 50%; top: 0; width: 1px; height: 100%; transform: translateX(-50%); }
.reg-mark::after { top: 50%; left: 0; height: 1px; width: 100%; transform: translateY(-50%); }
.reg-mark--tl { top: 16px; left: 16px; }
.reg-mark--tr { top: 16px; right: 16px; }
.reg-mark--br { bottom: 16px; right: 16px; }

/* ============================================================
   COMPONENTS: terminal-monospace structure
   Zero radius, hairline borders, uppercase mono controls, full invert on
   active. Colour is brand-locked, so this renders as ink on paper rather
   than as the data file's green-on-black CRT.
   ============================================================ */

.panel {
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: 0;
  padding: var(--card-padding);
}
.on-invert .panel {
  background: rgba(255,255,255,0.028);
  border-color: #3a4245;
}
.on-invert .panel p,
.on-invert .panel li { color: var(--color-text-muted-invert); }

/* The spec row. A tabular readout, not a card. */
.spec-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  align-items: baseline;
  padding-block: 12px;
  border-bottom: 1px solid var(--color-border);
}
.on-invert .spec-row { border-bottom-color: var(--color-border-invert); }
.spec-row:last-child { border-bottom: 0; }
.spec-row dt { color: var(--color-text-secondary); font-size: 0.9rem; }
.on-invert .spec-row dt { color: var(--color-text-muted-invert); }
.spec-row dt, .spec-row dd { min-width: 0; overflow-wrap: anywhere; }
.spec-row dd {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 0.9rem;
  text-align: right;
}

/* ---- Buttons: fill-slide-left ----
   The hover fills from the left edge. Ink laid down across a sheet. */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 14px 26px;
  border: 1px solid var(--color-text-primary);
  border-radius: 0;
  background: transparent;
  color: var(--color-text-primary);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1;
  overflow: hidden;
  cursor: pointer;
  isolation: isolate;
  transition: color var(--control-speed) var(--ease-out),
              transform var(--control-speed) var(--ease-out);
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--color-text-primary);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 260ms var(--ease-out);
}
.btn--primary {
  background: var(--color-text-primary);
  color: var(--color-bg-base);
}
.btn--primary::before { background: var(--color-brand-primary); }
.btn--primary:hover { color: var(--color-text-primary); }

.btn--onteal { border-color: var(--color-text-primary); }
.btn--onteal::before { background: var(--color-text-primary); }
.btn--onteal:hover { color: var(--color-brand-primary); }

.btn--invert { border-color: var(--color-bg-base); color: var(--color-bg-base); }
.btn--invert::before { background: var(--color-brand-primary); }
.btn--invert:hover { color: var(--color-text-primary); }

@media (hover: hover) and (pointer: fine) {
  .btn:hover::before { transform: scaleX(1); }
  .btn:not(.btn--primary):not(.btn--invert):not(.btn--onteal):hover { color: var(--color-bg-base); }
}
/* Asymmetric timing: the press is immediate, the release eases back. */
.btn:active { transform: scale(0.97); transition-duration: 90ms; }

/* Text link with an arrow that travels. */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-brand-secondary);
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
}
.on-invert .link-arrow { color: var(--color-brand-primary); }
.link-arrow svg { transition: transform var(--control-speed) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .link-arrow:hover { border-bottom-color: currentColor; }
  .link-arrow:hover svg { transform: translateX(6px); }
}

/* ============================================================
   NAVIGATION: sub-nav-bar
   Primary bar, plus a secondary bar carrying the process spine. The spine
   is the brief's central structural requirement: extrusion, laminating and
   die cutting used as navigation so the site demonstrates the sequence
   instead of describing it.
   ============================================================ */

.nav-primary {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--color-bg-base);
  border-bottom: 1px solid var(--color-border);
  transition: transform 320ms var(--ease-out), box-shadow 220ms var(--ease-out);
  will-change: transform;
}
/* Reading down, the header leaves so a full-bleed band gets the whole screen.
   Any upward scroll brings it straight back, so the quote CTA is never more
   than one flick away. */
.nav-primary.is-hidden { transform: translateY(-100%); }
.nav-primary.is-stuck { box-shadow: 0 1px 0 rgba(17,19,21,0.10); }
@media (prefers-reduced-motion: reduce) {
  .nav-primary { transition: none; }
  .nav-primary.is-hidden { transform: none; }
}
.nav-sub {
  position: sticky;
  top: 64px;
  z-index: 49;
  background: var(--color-bg-elevated);
  border-bottom: 1px solid var(--color-border);
}
@media (min-width: 1024px) { .nav-sub { top: 72px; } }

.nav-link {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-primary);
  padding-block: 8px;
  border-bottom: 2px solid transparent;
  transition: border-color var(--control-speed) var(--ease-out),
              color var(--control-speed) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .nav-link:hover { border-bottom-color: var(--color-brand-primary); }
}
.nav-link[aria-current="page"] {
  border-bottom-color: var(--color-text-primary);
  font-weight: 700;
}

.subnav-step {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  white-space: nowrap;
  padding-block: 11px;
  border-bottom: 2px solid transparent;
  color: var(--color-text-secondary);
  transition: color var(--control-speed) var(--ease-out),
              border-color var(--control-speed) var(--ease-out);
}
.subnav-step .idx { color: var(--color-brand-secondary); font-weight: 700; }
@media (hover: hover) and (pointer: fine) {
  .subnav-step:hover { color: var(--color-text-primary); border-bottom-color: var(--color-brand-primary); }
}
.subnav-step[aria-current="true"] { color: var(--color-text-primary); border-bottom-color: var(--color-brand-primary); }

/* ---- Capabilities dropdown ----
   Real child pages, not anchors. Anchors do not rank; pages do. Opens on hover
   for pointer users and on focus or click for everyone else, so it is reachable
   by keyboard and by touch. */
.has-drop { position: relative; }
.drop {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(6px);
  min-width: 290px;
  /* Centred under its trigger, so at the narrowest desktop width it could run
     past the viewport edge. Clamped to the viewport with a gutter to spare. */
  max-width: min(360px, calc(100vw - 32px));
  background: var(--color-bg-base);
  border: 1px solid var(--color-text-primary);
  padding: 8px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 180ms var(--ease-out), transform 180ms var(--ease-out);
  z-index: 60;
}
.has-drop:focus-within > .drop,
.has-drop[data-open="true"] > .drop {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}
@media (hover: hover) and (pointer: fine) {
  .has-drop:hover > .drop {
    opacity: 1; visibility: visible; pointer-events: auto;
    transform: translateX(-50%) translateY(0);
  }
}
.drop a {
  display: block;
  padding: 12px 14px;
  border-bottom: 1px solid var(--color-border);
  transition: background-color 140ms var(--ease-out);
}
.drop a:last-child { border-bottom: 0; }
.drop a:hover { background: var(--color-bg-elevated); }
.drop__idx {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--color-brand-secondary);
}
.drop__name {
  font-family: var(--font-heading);
  font-size: 0.84rem;
  font-weight: 600;
  text-transform: uppercase;
  display: block;
  margin-top: 3px;
}
.drop__desc {
  display: block;
  font-size: 0.8rem;
  color: var(--color-text-secondary);
  margin-top: 3px;
  line-height: 1.45;
}
.nav-caret { transition: transform 180ms var(--ease-out); }
.has-drop[data-open="true"] .nav-caret,
.has-drop:hover .nav-caret { transform: rotate(180deg); }

/* Mobile menu sub-list */
.mobile-menu .submenu a {
  font-size: 0.95rem;
  font-family: var(--font-body);
  font-weight: 500;
  text-transform: none;
  padding-block: 12px;
  padding-left: 18px;
  border-bottom: 1px solid var(--color-border-invert);
  color: var(--color-text-muted-invert);
}

/* ---- Mobile menu: full viewport overlay ---- */
.mobile-menu {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  z-index: 100;
  display: none;
  flex-direction: column;
  overflow-y: auto;
  background: var(--color-bg-invert);
  color: var(--color-text-on-invert);
  padding: 24px;
  padding-top: max(24px, env(safe-area-inset-top));
  padding-bottom: max(24px, env(safe-area-inset-bottom));
}
.mobile-menu.is-open { display: flex; }
.mobile-menu a {
  font-family: var(--font-heading);
  font-size: 1.3rem;
  font-weight: 700;
  text-transform: uppercase;
  padding-block: 16px;
  border-bottom: 1px solid var(--color-border-invert);
  display: block;
}
.menu-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-on-invert);
  border: 1px solid var(--color-border-invert);
}

/* ============================================================
   HERO: full-bleed-text-overlay
   Text sits in the bottom-left quadrant. Never dead centre.
   ============================================================ */

.hero {
  position: relative;
  min-height: 82vh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--color-bg-invert);
  isolation: isolate;
}
/* Both the poster image and the injected video must be absolutely positioned
   and stacked on top of each other. Left in normal flow the video lands BELOW
   the poster, outside the clipped hero, and never appears. */
.hero__media { position: absolute; inset: 0; z-index: -2; overflow: hidden; }
.hero__media img, .hero__media video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.hero__media img { z-index: 0; }
/* The homepage hero runs the client's black and white plant cutdown, so the
   poster is desaturated to match. Keeps the fade-in seamless, and keeps the
   mobile fallback (no video) tonally consistent with the proof band. */
.hero__media--mono img { filter: grayscale(1) contrast(1.06); }
.hero__media video { z-index: 1; }
.hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to top, rgba(17,19,21,0.92) 0%, rgba(17,19,21,0.72) 38%, rgba(17,19,21,0.34) 100%);
}
/* The halftone screen sits over the footage, tying the photography to the
   print system without touching the photograph's own colour. */
.hero__screen {
  position: absolute; inset: 0; z-index: -1;
  background-image: radial-gradient(circle, rgba(13,165,180,0.5) 1px, transparent 1px);
  background-size: 7px 7px;
  opacity: 0.30;
  mix-blend-mode: screen;
}
.hero__content {
  position: relative;
  width: 100%;
  max-width: var(--layout-max-width);
  margin-inline: auto;
  padding: 0 var(--spacing-content-mobile) 48px;
}
@media (min-width: 1024px) {
  .hero__content { padding: 0 var(--spacing-content-desktop) 96px; max-width: min(1400px, 100%); }
  .hero { min-height: 88vh; }
}

/* ============================================================
   PROCESS SPINE
   A genuine ordered sequence, which is why these carry numbers. Numbers are
   NOT used as kickers anywhere else on the site.
   ============================================================ */

.stage {
  position: relative;
  display: block;
  border: 1px solid var(--color-border-invert);
  background: transparent;
  overflow: hidden;
  transition: border-color 240ms var(--ease-out);
}
.stage__media { position: relative; aspect-ratio: 3 / 2; overflow: hidden; }
.stage__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 480ms var(--ease-out);
}
/* SIGNATURE MOMENT (animation-craft rule 10).
   Hovering a stage raises its ink coverage: the halftone screen over the
   photograph tightens from a coarse 9px cell to a dense 5px cell, the way
   more ink is laid down to deepen a tone on press. One interaction, built
   once, not scattered across the page. */
.stage__screen {
  position: absolute; inset: 0;
  background-image: radial-gradient(circle, rgba(13,165,180,0.85) 1px, transparent 1px);
  background-size: 9px 9px;
  opacity: 0.34;
  mix-blend-mode: screen;
  transition: background-size 420ms var(--ease-out), opacity 420ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .stage:hover { border-color: var(--color-brand-primary); }
  .stage:hover .stage__screen { background-size: 5px 5px; opacity: 0.52; }
  .stage:hover .stage__media img { transform: scale(1.03); }
}
.stage__idx {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-brand-primary);
}

/* ---- Industry rows: a ruled index, deliberately not a card grid ---- */
.ind-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 16px;
  align-items: center;
  padding-block: 18px;
  border-top: 1px solid var(--color-border);
  transition: background-color var(--control-speed) var(--ease-out);
}
@media (min-width: 768px) {
  .ind-row { grid-template-columns: 88px 200px 1fr auto; gap: 24px; }
}
.ind-row:last-child { border-bottom: 1px solid var(--color-border); }
@media (hover: hover) and (pointer: fine) {
  .ind-row:hover { background: var(--color-bg-elevated); }
}
.ind-row__thumb {
  width: 88px; height: 56px; object-fit: cover;
  border: 1px solid var(--color-border);
}

/* ---- Image crop helper ----
   cand-saw.png carries a baked-in grey letterbox on its left edge. Cropping
   from the right removes exactly that band rather than shipping the artefact. */
.crop-right { object-fit: cover; object-position: 100% 38%; transform: scale(1.06); }

/* ============================================================
   JOB DOCKET
   In a converting plant the job ticket travels with the sheet: what came in,
   what has to leave. Built as a docket torn from a book, with real perforation
   edges and a punched tear line between the two halves, on the ink ground the
   rest of the system already uses. Teal appears only as punctuation here: a
   large flat teal panel was tried and rejected, and this brand's colour works
   harder as an accent against ink than as a field.
   ============================================================ */
.docket {
  position: relative;
  background: var(--color-bg-invert);
  color: var(--color-text-on-invert);
  border: 1px solid var(--color-border-invert);
  overflow: hidden;
}
/* Punched holes along the top and bottom edges, the way a docket tears out of
   a book. Paper-coloured discs sitting on the ink read as holes punched
   through it. */
.docket::before,
.docket::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: 14px;
  background-image: radial-gradient(circle, var(--color-bg-base) 3.5px, transparent 3.6px);
  background-size: 22px 22px;
  background-position: center;
  opacity: 0.9;
  pointer-events: none;
}
.docket::before { top: -7px; }
.docket::after { bottom: -7px; }

.docket__grid { display: grid; }
@media (min-width: 900px) {
  .docket__grid { grid-template-columns: 1fr auto 1fr; }
}
.docket__col { padding: 34px 30px; }

/* The tear line between what goes in and what comes out. Vertical on desktop,
   horizontal once the docket stacks. */
.docket__tear {
  position: relative;
  background-image: radial-gradient(circle, rgba(255,255,255,0.55) 1.6px, transparent 1.7px);
  background-size: 10px 10px;
  min-height: 14px;
}
@media (min-width: 900px) {
  .docket__tear {
    width: 14px;
    background-size: 10px 10px;
  }
}

.docket__stamp {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--color-brand-primary);
  border: 1px solid var(--color-brand-primary);
  padding: 5px 9px;
}
.docket__list {
  margin-top: 18px;
  font-family: var(--font-mono);
  font-size: 0.86rem;
  font-weight: 500;
  line-height: 1.6;
}
.docket__list li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding-block: 9px;
  border-bottom: 1px solid var(--color-border-invert);
}
.docket__list li:last-child { border-bottom: 0; }
/* Coverage marks: the ink ramp again, one dot heavier per step down the list. */
.docket__list li::before {
  content: "";
  flex: none;
  margin-top: 6px;
  width: 9px; height: 9px;
  background: var(--color-brand-primary);
  opacity: var(--cov, 1);
}
.docket__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 22px 30px;
  border-top: 1px solid var(--color-border-invert);
}

/* ============================================================
   CAPTION OVER IMAGE
   Any copy sitting on a photograph gets its own scrim. Photographs are not a
   controlled background: a caption that lands on a bright chrome roller is
   unreadable no matter what the palette says. The hero and the proof band
   already carried scrims; this covers every remaining caption so the rule is
   site wide rather than per section.
   ============================================================ */
.fig-cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 2;
  padding: 22px 24px;
  color: #fff;
  background: linear-gradient(to top,
    rgba(17,19,21,0.94) 0%,
    rgba(17,19,21,0.78) 42%,
    rgba(17,19,21,0.34) 72%,
    rgba(17,19,21,0) 100%);
}
@media (min-width: 1024px) { .fig-cap { padding: 30px 40px; } }
.fig-cap .t-label { color: rgba(255,255,255,0.86) !important; }

/* ============================================================
   ROSTER
   A numbered ledger of customer names on a photographic ground. Reads as a
   record rather than as a logo wall, which matters when the names are set as
   type because no third-party marks are reproduced.
   ============================================================ */
.roster {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 40px;
  counter-reset: none;
}
@media (min-width: 900px) { .roster { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.roster li {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding-block: 14px;
  border-bottom: 1px solid rgba(255,255,255,0.18);
}
.roster__n {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--color-brand-primary);
  flex: none;
}
.roster li { min-width: 0; }
.roster__name {
  overflow-wrap: anywhere;
  font-family: var(--font-mono);
  font-size: 0.92rem;
  font-weight: 600;
  color: #fff;
}

/* ============================================================
   STORY RHYTHM
   A long About passage set as three equal paragraphs reads as a wall. These
   two devices break it: the places the component hides, pulled out as a ruled
   strip, and the one line worth slowing down for, set as a pull quote.
   ============================================================ */
.places {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border-top: 1px solid var(--color-border);
}
@media (min-width: 768px) { .places { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.places div {
  padding: 18px 16px 20px;
  border-bottom: 1px solid var(--color-border);
  border-right: 1px solid var(--color-border);
}
.places div:nth-child(2n) { border-right: 0; }
@media (min-width: 768px) {
  .places div { border-bottom: 0; border-right: 1px solid var(--color-border); }
  .places div:nth-child(2n) { border-right: 1px solid var(--color-border); }
  .places div:last-child { border-right: 0; }
}
.places__mark {
  display: block;
  width: 10px; height: 10px;
  background: var(--color-brand-primary);
  margin-bottom: 12px;
}
.places__txt {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 600;
  text-transform: uppercase;
  line-height: 1.5;
}

.pull {
  position: relative;
  margin: 0;
  padding: 26px 0 0;
  border-top: 3px solid var(--color-text-primary);
}
.pull::before {
  content: "";
  position: absolute;
  top: -3px; left: 0;
  width: 96px; height: 3px;
  background: var(--color-brand-primary);
}
.pull p {
  font-family: var(--font-heading);
  font-weight: 700;
  text-transform: uppercase;
  line-height: 1.28;
  font-size: clamp(1.05rem, 2.1vw, 1.5rem);
  color: var(--color-text-primary);
}

/* ============================================================
   DATA PLATE
   The About record was a plain definition list. On a machine, the record lives
   on a stamped plate riveted to the frame, so that is what this is: brushed
   ground, an inset hairline frame, four rivets, and the values struck into it.
   The rivets are the one place a radius appears in a zero-radius system, and
   they earn it by being physical objects rather than UI.
   ============================================================ */
.plate {
  position: relative;
  background:
    repeating-linear-gradient(180deg, rgba(255,255,255,0.028) 0 1px, transparent 1px 3px),
    linear-gradient(160deg, #1b1f21 0%, #101214 60%, #15181a 100%);
  border: 1px solid #333a3d;
  padding: 30px 26px;
  color: #fff;
  overflow: hidden;
}
.plate::before {
  content: "";
  position: absolute;
  inset: 11px;
  border: 1px solid rgba(13,165,180,0.42);
  pointer-events: none;
}
.plate__rivet {
  position: absolute;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 32%, #7d888c 0%, #4a5457 45%, #20262a 100%);
  box-shadow: 0 1px 0 rgba(0,0,0,0.6);
}
.plate__rivet--tl { top: 20px; left: 20px; }
.plate__rivet--tr { top: 20px; right: 20px; }
.plate__rivet--bl { bottom: 20px; left: 20px; }
.plate__rivet--br { bottom: 20px; right: 20px; }

.plate__inner { position: relative; padding: 16px 14px; }
.plate__head {
  display: flex; justify-content: space-between; gap: 16px;
  font-family: var(--font-mono);
  font-size: 0.6rem; font-weight: 700; letter-spacing: 0.14em;
  color: var(--color-brand-primary);
}
.plate__est {
  font-family: var(--font-mono);
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.22em;
  color: rgba(255,255,255,0.55);
  margin-top: 26px;
}
.plate__year {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  line-height: 0.96;
  font-size: clamp(3rem, 11vw, 5rem);
  /* Struck into the plate rather than printed on it. */
  color: #f2f5f6;
  text-shadow: 0 1px 0 rgba(0,0,0,0.85), 0 -1px 0 rgba(255,255,255,0.10);
  margin-top: 2px;
}
.plate__rule { height: 1px; background: rgba(255,255,255,0.16); margin: 26px 0 22px; }
.plate__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.plate__fig {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: clamp(1.5rem, 5vw, 2.1rem);
  line-height: 1;
  color: #fff;
}
.plate__cap {
  font-family: var(--font-mono);
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.72);
  margin-top: 8px;
  line-height: 1.45;
}
.plate__foot {
  display: flex; justify-content: space-between; gap: 12px;
  margin-top: 26px;
  font-family: var(--font-mono);
  font-size: 0.58rem; font-weight: 600; letter-spacing: 0.1em;
  color: rgba(255,255,255,0.66);   /* 8.2:1 on the plate ground */
}

/* ============================================================
   PRESS SHEET MOSAIC
   The seven industries laid out the way parts are nested on a sheet: unequal
   sizes, tight-packed, no wasted ground. Deliberately not a card grid, and
   deliberately not the ruled index used elsewhere.
   ============================================================ */

.sheet {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
  background: var(--color-border);
  border: 1px solid var(--color-border);
  padding: 6px;
}
@media (min-width: 768px) {
  .sheet {
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 150px;
  }
  .sheet__cell--xl { grid-column: span 2; grid-row: span 2; }
  .sheet__cell--w  { grid-column: span 2; }
}

.sheet__cell {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--color-bg-invert);
  min-height: 150px;
}
.sheet__cell img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.55) contrast(1.06);
  transition: filter 420ms var(--ease-out), transform 520ms var(--ease-out);
}
/* The same signature as the process stages: ink coverage rises on approach. */
.sheet__cell::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle, rgba(13,165,180,0.9) 1px, transparent 1px);
  background-size: 10px 10px;
  opacity: 0.42;
  mix-blend-mode: screen;
  transition: background-size 420ms var(--ease-out), opacity 420ms var(--ease-out);
  pointer-events: none;
}
.sheet__label {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  padding: 14px;
  background: linear-gradient(to top, rgba(17,19,21,0.88), rgba(17,19,21,0));
  color: #fff;
}
.sheet__idx {
  position: absolute;
  top: 10px;
  left: 12px;
  z-index: 2;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--color-brand-primary);
}
@media (hover: hover) and (pointer: fine) {
  .sheet__cell:hover img { filter: saturate(1) contrast(1.02); transform: scale(1.04); }
  .sheet__cell:hover::after { background-size: 5px 5px; opacity: 0.6; }
}

/* ============================================================
   PROOF BAND
   The credibility moment. A flat colour field left the figures floating in
   empty ground, so the ground became a photograph: racked roll stock, the raw
   material every one of those seventy five years passed through. Shot
   monochrome, which no competitor in the measured set uses anywhere, and
   screened back into the teal ink channel so the brand still owns the surface.
   ============================================================ */
.proof {
  position: relative;
  isolation: isolate;
  background: var(--color-bg-invert);
  overflow: hidden;
}
.proof__media { position: absolute; inset: 0; z-index: -3; }
.proof__media img { width: 100%; height: 100%; object-fit: cover; }
.proof__scrim {
  position: absolute; inset: 0; z-index: -2;
  background:
    linear-gradient(105deg, rgba(17,19,21,0.95) 0%, rgba(17,19,21,0.86) 45%, rgba(17,19,21,0.62) 100%);
}
.proof__screen {
  position: absolute; inset: 0; z-index: -1;
  background-image: radial-gradient(circle, rgba(13,165,180,0.85) 1px, transparent 1px);
  background-size: 7px 7px;
  opacity: 0.34;
  mix-blend-mode: screen;
}
/* The figures are the eye-catch: set far larger than anything else on the page
   and knocked out of the photograph. */
.proof__figure {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  line-height: 0.96;
  /* Martian Mono is a very wide face and "84x75" is five glyphs. At 7vw it
     overran a quarter-width column and collided with the next figure. Capped so
     the longest value still clears the narrowest column it ever occupies. */
  font-size: clamp(1.9rem, 5vw, 4rem);
  color: #fff;
  white-space: nowrap;
}
.proof__stat {
  padding-top: 20px;
  border-top: 2px solid var(--color-brand-primary);
  min-width: 0;
}

/* ============================================================
   COLOPHON ROSTER
   A wrapped run of names set as one continuous line, the way a press
   colophon or a masthead runs. Replaces a boxed list floating in empty
   ground, which is what the teal band was doing wrong.
   ============================================================ */
.colophon {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: clamp(0.95rem, 1.8vw, 1.3rem);
  line-height: 1.75;
  color: var(--color-text-primary);
}
.colophon span:not(:last-child)::after {
  content: "\00B7";
  padding-inline: 0.55em;
  color: var(--color-text-primary);
  opacity: 0.45;
}

/* Oversized tabular figures used on the teal proof band. */
.figure-xl {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  line-height: 0.96;
  font-size: clamp(1.8rem, 4.4vw, 3.1rem);
  white-space: nowrap;
}

/* ============================================================
   CUTAWAY STRIP
   Five end products butted edge to edge with ONE continuous teal seam running
   straight through all of them. The seam is the component: the same board line
   passing through a car, a cabinet, a carton, a pallet load and a wall. This is
   the section's whole argument made structural rather than written out.
   ============================================================ */
.cutaway { position: relative; }
.cutaway__strip {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.cutaway__frame { position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: var(--color-bg-invert); }
.cutaway__frame img {
  width: 100%; height: 100%; object-fit: cover;
  filter: saturate(0.7);
  transition: transform 520ms var(--ease-out), filter 380ms var(--ease-out);
}
/* On mobile the strip wraps, so a single line cannot run through it. Each
   frame carries its own seam instead, at the same height within the frame. */
.cutaway__frame::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  bottom: 26%;
  height: 4px;
  background: var(--color-brand-primary);
  z-index: 2;
}
.cutaway__seam { display: none; }

@media (min-width: 768px) {
  .cutaway__strip { grid-template-columns: repeat(5, 1fr); gap: 10px; }
  .cutaway__frame::after { display: none; }
  /* The seam runs dead straight across the whole strip and bridges the gaps
     between frames. The gaps are what make it read as one continuous line
     passing THROUGH five separate products rather than five matching stripes. */
  .cutaway__seam {
    display: block;
    position: absolute;
    left: 0; right: 0;
    top: 74%;
    height: 4px;
    background: var(--color-brand-primary);
    z-index: 3;
    pointer-events: none;
  }
  /* A chip riding on the seam names the device, so the line is legible as an
     idea instead of reading as decoration. */
  .cutaway__seam::after {
    content: "THE SAME BOARD";
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    background: var(--color-brand-primary);
    color: var(--color-text-primary);
    font-family: var(--font-mono);
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    padding: 6px 12px;
    white-space: nowrap;
  }
}
@media (hover: hover) and (pointer: fine) {
  .cutaway__frame:hover img { transform: scale(1.05); filter: saturate(1); }
}
.cutaway__caption { padding-top: 12px; }

/* ---- Forms ---- */
.field {
  width: 100%;
  background: var(--color-bg-base);
  border: 1px solid var(--color-border);
  border-radius: 0;
  padding: 12px 14px;
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--color-text-primary);
  transition: border-color var(--control-speed) var(--ease-out);
}
.field:focus {
  border-color: var(--color-text-primary);
  outline: 3px solid var(--color-brand-primary);
  outline-offset: 1px;
}
.field::placeholder { color: #7d8689; }

/* ============================================================
   SPEC STRIP
   The published specification is the one thing no measured competitor offers,
   and it was sitting in a narrow right-hand column with dead ground beside it.
   Promoted to a full-width strip across the top of the section: label over
   value, hairline separated, tabular figures. The prose then runs underneath at
   a readable measure instead of fighting the table for the same row.
   ============================================================ */
.specstrip {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--color-border);
  background: var(--color-border);
  gap: 1px;
}
@media (min-width: 768px) { .specstrip { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .specstrip--five { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.on-invert .specstrip { border-color: var(--color-border-invert); background: var(--color-border-invert); }

.specstrip__cell {
  background: var(--color-bg-base);
  padding: 22px 20px;
  min-width: 0;
  overflow-wrap: anywhere;
}
.on-invert .specstrip__cell { background: var(--color-bg-invert); }
.specstrip__k {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
}
.on-invert .specstrip__k { color: var(--color-text-muted-invert); }
.specstrip__v {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: clamp(1.02rem, 1.9vw, 1.32rem);
  line-height: 1.25;
  margin-top: 12px;
  color: var(--color-text-primary);
}
.on-invert .specstrip__v { color: #fff; }
/* A short teal rule under each value, so the strip reads as struck entries
   rather than as a plain table. */
.specstrip__cell::after {
  content: "";
  display: block;
  width: 26px; height: 3px;
  background: var(--color-brand-primary);
  margin-top: 16px;
}

/* ---- Applications, as a ruled index rather than a floating bordered box ---- */
.usedfor { border-top: 1px solid var(--color-border); }
.on-invert .usedfor { border-top-color: var(--color-border-invert); }
.usedfor li {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding-block: 15px;
  border-bottom: 1px solid var(--color-border);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--color-text-secondary);
}
.on-invert .usedfor li { border-bottom-color: var(--color-border-invert); color: var(--color-text-muted-invert); }
.usedfor li::before {
  content: "";
  flex: none;
  margin-top: 8px;
  width: 9px; height: 9px;
  background: var(--color-brand-primary);
}

/* ============================================================
   Q&A REGISTER
   The FAQ was thin full-width rows with a small plus and an answer floating
   loose underneath. Rebuilt as a numbered technical register: every question is
   a struck entry with an index, a real toggle, and an answer that sits in its
   own tinted block indented under the question it belongs to. Open state is
   unmistakable, which is what a long FAQ actually needs.
   ============================================================ */
.qa-list { border-top: 2px solid var(--color-text-primary); }
.on-invert .qa-list { border-top-color: var(--color-brand-primary); }

.qa {
  border-bottom: 1px solid var(--color-border);
  transition: background-color 200ms var(--ease-out);
}
.on-invert .qa { border-bottom-color: var(--color-border-invert); }
.qa[open] { background: var(--color-bg-elevated); }
.on-invert .qa[open] { background: rgba(255,255,255,0.04); }

.qa__q {
  cursor: pointer;
  list-style: none;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 22px 20px 22px 16px;
}
@media (min-width: 768px) { .qa__q { gap: 26px; padding: 26px 26px 26px 22px; } }
.qa__q::-webkit-details-marker { display: none; }

.qa__idx {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-brand-secondary);
  padding-top: 2px;
}
.on-invert .qa__idx { color: var(--color-brand-primary); }
.qa[open] .qa__idx { color: var(--color-text-primary); }
.on-invert .qa[open] .qa__idx { color: var(--color-brand-primary); }

.qa__text {
  min-width: 0;
  overflow-wrap: anywhere;
  font-family: var(--font-heading);
  font-weight: 600;
  text-transform: uppercase;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--color-text-primary);
}
.on-invert .qa__text { color: #fff; }
@media (min-width: 768px) { .qa__text { font-size: 0.94rem; } }

/* A real control rather than a stray glyph: a bordered square that inverts to
   solid when the entry is open, which is the component personality's own
   active-state idiom. */
.qa__toggle {
  position: relative;
  flex: none;
  width: 34px; height: 34px;
  border: 1px solid var(--color-text-primary);
  transition: background-color 200ms var(--ease-out), border-color 200ms var(--ease-out);
}
.on-invert .qa__toggle { border-color: rgba(255,255,255,0.55); }
.qa__toggle::before,
.qa__toggle::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  background: var(--color-text-primary);
  transition: transform 260ms var(--ease-out), background-color 200ms var(--ease-out);
}
.on-invert .qa__toggle::before,
.on-invert .qa__toggle::after { background: #fff; }
.qa__toggle::before { width: 13px; height: 2px; transform: translate(-50%, -50%); }
.qa__toggle::after  { width: 2px; height: 13px; transform: translate(-50%, -50%); }
.qa[open] .qa__toggle { background: var(--color-text-primary); border-color: var(--color-text-primary); }
.on-invert .qa[open] .qa__toggle { background: var(--color-brand-primary); border-color: var(--color-brand-primary); }
.qa[open] .qa__toggle::before { background: var(--color-bg-base); }
.qa[open] .qa__toggle::after  { transform: translate(-50%, -50%) scaleY(0); }
.on-invert .qa[open] .qa__toggle::before { background: var(--color-text-primary); }

@media (hover: hover) and (pointer: fine) {
  .qa:not([open]) .qa__q:hover { background: var(--color-bg-elevated); }
  .on-invert .qa:not([open]) .qa__q:hover { background: rgba(255,255,255,0.03); }
  .qa__q:hover .qa__toggle { border-color: var(--color-brand-primary); }
}

/* The answer is indented to the question's own text column, so it reads as
   belonging to that entry rather than to the list. */
.qa__a {
  padding: 0 26px 28px 16px;
  font-size: 1rem;
  line-height: 1.7;
  color: var(--color-text-secondary);
  max-width: 74ch;
}
.on-invert .qa__a { color: var(--color-text-muted-invert); }
@media (min-width: 768px) { .qa__a { padding-left: 74px; padding-right: 60px; } }

.qa-count {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--color-text-secondary);
}
.on-invert .qa-count { color: var(--color-text-muted-invert); }

/* ============================================================
   ENTRANCE
   micro-interaction-rich: short, restrained, and never above the fold.
   Elements are visible by default and only hidden once JS confirms it will
   reveal them, so a font reflow or a script failure can never leave a blank
   page. A prior build shipped exactly that defect.
   ============================================================ */
[data-animate] { opacity: 1; transform: none; }
.js-reveal [data-animate]:not(.is-in) {
  opacity: 0;
  transform: translateY(14px);
}
.js-reveal [data-animate] {
  transition: opacity var(--entrance-duration) var(--ease-out),
              transform var(--entrance-duration) var(--ease-out);
}
.js-reveal [data-animate].is-in { opacity: 1; transform: none; }

/* ============================================================
   REDUCED MOTION
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  [data-parallax], [class*="parallax"], .zoom-element, .scroll-rotate {
    animation: none !important;
    animation-timeline: none !important;
    transform: none !important;
  }
  .js-reveal [data-animate]:not(.is-in) { opacity: 1; transform: none; }
  .stage__screen, .stage__media img { transition: none !important; }
}

/* ============================================================
   PRINT
   ============================================================ */
@media print {
  .nav-primary, .nav-sub, .mobile-menu { display: none; }
  .band-full, .band-contained { padding-block: 24px; }
}
