﻿/* ==========================================================================
   VDPL Next — Base
   Reset, document defaults, typography, layout primitives, a11y utilities.
   Consumes tokens.css. Declares no raw colour values.

   Specificity policy for the whole theme:
     - single class selectors only
     - no element selectors outside this file
     - no !important except in the reduced-motion and print blocks
   Spacing between siblings is owned by the parent's `gap`, never by
   per-element margins — that is what stops sections fighting each other.
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Sticky header must not cover the target of an in-page anchor. */
  scroll-padding-top: 88px;
}

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-ink);
  font-family: var(--f-sans);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  letter-spacing: var(--t-body-ls);
  font-weight: var(--w-regular);
  /* No -webkit-font-smoothing: antialiased here. It only affects macOS, where
     it thins every stroke - the opposite of crisp. Left to the platform. */
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; }
li { list-style: none; }

img, picture, svg, video, canvas {
  display: block;
  max-width: 100%;
  height: auto;
}
svg { flex-shrink: 0; }

a { color: inherit; text-decoration: none; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
}
button { background: none; border: 0; padding: 0; cursor: pointer; }
textarea { resize: vertical; }

table { border-collapse: collapse; width: 100%; }

/* ---- Focus --------------------------------------------------------------
   WCAG 2.2 · 2.4.11 Focus Not Obscured / 2.4.13 Focus Appearance.
   Never remove this. Offset keeps the ring clear of the element's own edge
   so it stays visible against same-colour surfaces. */
:focus { outline: none; }
:focus-visible {
  outline: 3px solid var(--c-accent);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}

/* ---- Selection ---------------------------------------------------------- */
::selection {
  background: var(--c-accent);
  color: var(--c-accent-ink);
}

/* ==========================================================================
   Typography
   ========================================================================== */

.t-d1 {
  font-size: var(--t-d1); line-height: 1.03; letter-spacing: var(--t-d1-ls);
  font-weight: var(--w-bold); text-wrap: balance;
}
.t-d2 {
  font-size: var(--t-d2); line-height: var(--lh-tight); letter-spacing: var(--t-d2-ls);
  font-weight: var(--w-bold); text-wrap: balance;
}
.t-d3 {
  font-size: var(--t-d3); line-height: 1.12; letter-spacing: var(--t-d3-ls);
  font-weight: var(--w-bold); text-wrap: balance;
}
.t-d4 {
  font-size: var(--t-d4); line-height: var(--lh-snug); letter-spacing: var(--t-d4-ls);
  font-weight: var(--w-semi); text-wrap: balance;
}
.t-lead {
  font-size: var(--t-lead); line-height: 1.5; letter-spacing: var(--t-lead-ls);
  color: var(--c-ink-2); max-width: 60ch; text-wrap: pretty;
}
.t-body { color: var(--c-ink-2); max-width: var(--measure); text-wrap: pretty; }
.t-sm   { font-size: var(--t-sm); letter-spacing: -.005em; }
.t-muted{ color: var(--c-ink-3); }

/* Section eyebrow. Used only where it names a real category — not as
   decoration above every heading. */
.t-eyebrow {
  font-size: var(--t-xs);
  font-weight: var(--w-bold);
  letter-spacing: var(--t-label-ls);
  text-transform: uppercase;
  color: var(--c-accent-text);
}

/* Any digits that align in a column or animate in a counter. */
.t-num { font-variant-numeric: tabular-nums; }
.t-mono { font-family: var(--f-mono); font-size: .9em; letter-spacing: 0; }

/* ==========================================================================
   Layout primitives
   ========================================================================== */

.l-wrap {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.l-narrow { max-width: var(--container-narrow); margin-inline: auto; }

/* Section owns its own vertical rhythm. Nothing inside a section adds
   top-level margin — this is the rule that keeps the page rhythm intact. */
.l-section { padding-block: var(--section); }
.l-section-sm { padding-block: calc(var(--section) * .58); }

/* 12-column grid. Children opt in with .l-col-{n}; below 900px everything
   collapses to a single column unless a component says otherwise. */
.l-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--s-8);
}
@media (max-width: 900px) {
  .l-grid { grid-template-columns: minmax(0, 1fr); }
  .l-grid > [class*="l-col-"] { grid-column: auto !important; }
}

.l-col-3  { grid-column: span 3; }
.l-col-4  { grid-column: span 4; }
.l-col-5  { grid-column: span 5; }
.l-col-6  { grid-column: span 6; }
.l-col-7  { grid-column: span 7; }
.l-col-8  { grid-column: span 8; }
.l-col-12 { grid-column: span 12; }

/* Auto-fit card rails. --min is set per component, not per breakpoint.

   --max is opt-in and unset by default (falls back to 1fr, unbounded) so
   every existing rail is unaffected. Set it on a rail whose item count is
   small and variable - a sector's related-work cards might be one, two or
   four - because auto-fit collapses unused tracks and hands their space to
   whatever IS there: two cards in a row that could hold five stretch to fill
   it, and a card built for a 16:10 cover becomes an 800px-wide one. Found on
   /industries/healthcare/, which has exactly two related cases. */
.l-rail {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--min, 280px), 100%), var(--max, 1fr)));
  gap: var(--s-6);
}

.l-stack { display: flex; flex-direction: column; gap: var(--s-6); }
.l-stack-sm { display: flex; flex-direction: column; gap: var(--s-3); }
/* 40px, down from 48px. This is the gap between a section header and the grid
   it introduces, and it repeats on every section — 8px here is 64px of page. */
.l-stack-lg { display: flex; flex-direction: column; gap: var(--s-10); }
.l-row { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }

/* Section header: eyebrow + heading + lead, consistent everywhere. */
/* Section header.

   The cap is in rem, not ch. `ch` resolves against this element's own font
   size (17px), not against the display heading inside it, so `max-width: 44ch`
   caps the box at roughly 370px and forces a 56px H1 to wrap after one or two
   words. The running text inside gets its own measure instead, which is the
   only place a character-based unit is the right tool. */
.l-head {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  max-width: 46rem;
}
.l-head > p { max-width: 58ch; }
.l-head--center { align-items: center; text-align: center; margin-inline: auto; }
.l-head--center .t-lead { text-align: center; }

/* Wide content must scroll inside itself, never widen the page. */
.l-scroll-x { overflow-x: auto; overscroll-behavior-x: contain; }

/* ==========================================================================
   Accessibility utilities
   ========================================================================== */

.a-sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Skip link — first focusable element in the document. */
.a-skip {
  position: absolute; top: var(--s-2); left: var(--s-2);
  z-index: var(--z-toast);
  padding: var(--s-3) var(--s-5);
  background: var(--c-accent); color: var(--c-accent-ink);
  border-radius: var(--r-sm); font-weight: var(--w-semi);
  transform: translateY(-200%);
  transition: transform var(--dur) var(--ease);
}
.a-skip:focus-visible { transform: none; }

/* ==========================================================================
   Scroll reveal
   Opacity + transform only, so it never triggers layout. Elements are
   visible by default and hidden by script — if JS fails, content still
   renders. The `.js` class is set on <html> by the inline head script.
   ========================================================================== */

.js .a-rv {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity var(--dur-slow) var(--ease-out),
              transform var(--dur-slow) var(--ease-out);
}
.js .a-rv.is-in { opacity: 1; transform: none; }

/* Staggered children within one reveal group. */
.js .a-rv-group > * { transition-delay: calc(var(--i, 0) * 70ms); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto !important; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .js .a-rv { opacity: 1 !important; transform: none !important; }
}

/* Users who ask for more contrast get flat surfaces and hard borders. */
@media (prefers-contrast: more) {
  :root { --c-line: rgba(17, 24, 39, .38); --c-ink-2: #1F2633; --c-ink-3: #444C5C; }
}

@media print {
  .a-skip, .c-header, .c-footer, .c-dock { display: none !important; }
  body { background: #fff !important; color: #000 !important; }
  .l-section { padding-block: var(--s-8) !important; }
}

/* ==========================================================================
   Phones
   Display type is set for a 1600px canvas. On a 375px screen the same weights
   and tracking read as a poster rather than as an app: heavy, tight, shouting.
   Native mobile interfaces use lighter headings and looser tracking, and that
   is most of what makes an interface feel like an app rather than a website
   someone shrank.
   ========================================================================== */

@media (max-width: 760px) {
  .t-d1, .t-d2, .t-d3 { font-weight: var(--w-semi); }
  .t-d4 { font-weight: var(--w-medium); }

  /* Tracking that sharpens 72px type closes up 34px type. */
  .t-d1 { letter-spacing: -.026em; line-height: 1.08; }
  .t-d2 { letter-spacing: -.022em; line-height: 1.12; }
  .t-d3 { letter-spacing: -.018em; line-height: 1.16; }

  /* Only the leading is adjusted here. The sizes used to be re-declared at
     this breakpoint, which meant the scale said one thing and the phone said
     another — --t-lead resolved to 18 while this forced 17. Every size in the
     scale is a clamp with a vw term, so it already narrows on a small screen;
     restating it just creates a second source of truth. */
  body { line-height: 1.6; }
  .t-lead { line-height: 1.55; }

  .s-prose { line-height: 1.7; }
  .s-prose h2 { font-weight: var(--w-semi); }
}

/* ==========================================================================
   Article column

   An article is one column of running text, so the container should be that
   column - not a 1180px box with a 730px measure sitting at the left of it
   and a wide gap on the right. Everything in the article shares this width:
   the masthead, the cover image and the prose all line up.

   Landing pages keep .l-narrow, where a wide box holding narrower content is
   the point.
   ========================================================================== */

.l-article {
  width: 100%;
  max-width: calc(var(--measure) + var(--gutter) * 2);
  margin-inline: auto;
}

/* The prose is already at its measure, so it fills this container exactly.
   Left in place so a wider element inside an article - a table, a code block
   - still knows where the text edge is. */
.l-article .s-prose { max-width: none; }

/* ==========================================================================
   Section seams

   Every section owns padding on both sides, so two in a row produce double.
   Where the ground changes - a tinted section against a plain one - that full
   gap is doing a job: it separates two clearly different bands. Where the
   ground is the same, the seam is invisible and the doubled padding is just a
   hole in the page.

   So: same ground, collapse. Different ground, leave it alone.

   Since the alternation became automatic (see .c-main > section:nth-of-type
   in components.css) every adjacent pair differs by definition, so the only
   same-ground seams left are the two sections that opt out of the tint. The
   masthead is always first and has no section above it, which leaves one
   case: the closing CTA sitting on an even count, untinted, directly below an
   untinted odd section.
   ========================================================================== */
.c-main > section:nth-of-type(odd) + .h-cta {
  padding-top: calc(var(--section) * .35);
}

/* The first section after the header should not carry a full section's worth
   of air above it - the header already provides separation. */
main > section:first-child { padding-top: calc(var(--section) * .55); }
