/* ==========================================================================
   Base — typography and layout primitives that sit on top of Bootstrap.
   Bootstrap supplies the reset, grid, spacing and utilities; everything here
   is either brand typography or a device Bootstrap has no equivalent for.
   ========================================================================== */

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 24px);
}

body {
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* The UA gives figure `margin: 1em 40px`; Bootstrap keeps a bottom margin.
   Left in place it silently offsets absolutely positioned figures. */
figure { margin: 0; }

/* Every image on the site carries width/height attributes so the browser can
   reserve the right space before it loads. Those attributes are also
   presentational hints, so an image with a fluid CSS width but no CSS height
   gets the attribute height applied literally — and is squashed or stretched
   to whatever number the markup happens to carry. `height: auto` hands the
   proportions back to the picture; any component that genuinely wants a fixed
   height (a cover crop, the header logo) sets one and wins on specificity. */
img {
  max-width: 100%;
  height: auto;
}

h1, h2, h3, h4, h5,
.h1, .h2, .h3, .h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

h1, .h1 { font-size: var(--t-hero); font-stretch: 118%; }
h2, .h2 { font-size: var(--t-h2); font-stretch: 112%; }
h3, .h3 { font-size: var(--t-h3); font-stretch: 106%; letter-spacing: -0.012em; }
h4, .h4 { font-size: var(--t-h4); font-stretch: 104%; letter-spacing: -0.008em; }

p { text-wrap: pretty; }

::selection { background: var(--accent); color: #fff; }

/* ---- Section rhythm ---------------------------------------------------- */

.section { padding-block: var(--section-y); position: relative; }
.section--tight { padding-block: clamp(3rem, 5.5vw, 5rem); }
.section--flush-top { padding-top: 0; }

.section--sunk { background: var(--resin-deep); }
.section--paper { background: var(--paper); }

.section--ink { background: var(--ink); color: #dfe6e3; }
.section--ink h2,
.section--ink h3 { color: #fff; }

.section--deep {
  background: linear-gradient(155deg, var(--deep) 0%, var(--deep-2) 100%);
  color: #cfe1dc;
}
.section--deep h2,
.section--deep h3 { color: #fff; }

/* ---- The rib rail ------------------------------------------------------
   A left rail carrying a vertical section label. It is the flute motif
   applied as page structure: it marks where a section starts the way a rib
   marks the wall of a sheet. Shown from xl up, where there is room. */

.rail { width: var(--rib-gutter); flex: 0 0 var(--rib-gutter); }

.rail__label {
  position: sticky;
  top: calc(var(--header-h) + 40px);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-family: var(--font-data);
  font-size: var(--t-micro);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}
.rail__label::after {
  content: "";
  display: block;
  width: 1px;
  height: 64px;
  margin: 14px auto 0;
  background: linear-gradient(to bottom, var(--flute), transparent);
}
.section--ink .rail__label,
.section--deep .rail__label { color: rgba(255, 255, 255, 0.62); }
.section--ink .rail__label::after,
.section--deep .rail__label::after {
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0.4), transparent);
}

/* ---- Section heading block --------------------------------------------- */

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-data);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent-dk);
  margin-bottom: 1rem;
}
.eyebrow::before {
  content: "";
  width: 26px;
  height: 8px;
  /* three ribs — a miniature of the sheet section */
  background-image: repeating-linear-gradient(90deg, currentColor 0 2px, transparent 2px 8px);
  opacity: 0.85;
}
.section--ink .eyebrow,
.section--deep .eyebrow { color: #f08a5d; }

.section-head { max-width: 62ch; margin-bottom: clamp(2.25rem, 4vw, 3.5rem); }
.section-head--wide { max-width: 80ch; }
.section-head p {
  font-size: var(--t-lead);
  color: var(--ink-2);
  margin-top: 1rem;
  margin-bottom: 0;
  line-height: 1.55;
}
.section--ink .section-head p,
.section--deep .section-head p { color: rgba(255, 255, 255, 0.72); }

.lead { font-size: var(--t-lead); color: var(--ink-2); line-height: 1.55; }
.section--ink .lead,
.section--deep .lead { color: rgba(255, 255, 255, 0.76); }

/* ---- Divider: a cut sheet edge ----------------------------------------- */

.edge-rule {
  height: 9px;
  border-top: 1px solid var(--flute);
  border-bottom: 1px solid var(--flute);
  background-image: repeating-linear-gradient(90deg, var(--flute) 0 1px, transparent 1px 10px);
  opacity: 0.85;
}

/* ---- Utilities ---------------------------------------------------------- */

.data {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* Spacing, colour and ratio steps the pages need that Bootstrap's scale
   doesn't have. Like Bootstrap's own utilities they are !important, so a
   one-off adjustment always wins over the component it sits on. */
.text-ink-2 { color: var(--ink-2) !important; }
.text-on-dark-muted { color: rgba(255, 255, 255, 0.72) !important; }

.mt-copy { margin-top: 0.9rem !important; }
.mt-para { margin-top: 1.1rem !important; }
.mt-text { margin-top: 1.2rem !important; }
.mt-lead { margin-top: 1.25rem !important; }
.mt-tick { margin-top: 1.4rem !important; }
.mt-list { margin-top: 1.75rem !important; }
.mt-section { margin-top: clamp(1.75rem, 3vw, 2.5rem) !important; }
.mt-stat { margin-top: clamp(2rem, 4vw, 3rem) !important; }
.mt-stat-lg { margin-top: clamp(2.5rem, 5vw, 4rem) !important; }

.mb-tight { margin-bottom: 0.6rem !important; }
.mb-thumbs { margin-bottom: 0.85rem !important; }
.mb-text { margin-bottom: 1.2rem !important; }
.mb-lead { margin-bottom: 1.25rem !important; }
.mb-section { margin-bottom: clamp(1.75rem, 3vw, 2.5rem) !important; }
.mb-row { margin-bottom: clamp(3rem, 6vw, 5rem) !important; }

.aspect-16-10 { aspect-ratio: 16 / 10 !important; }
.aspect-1-1 { aspect-ratio: 1 / 1 !important; }

.skip-link {
  position: absolute;
  left: 1rem;
  top: -100px;
  z-index: 2000;
  background: var(--ink);
  color: #fff;
  padding: 0.7rem 1.1rem;
  border-radius: var(--radius);
  transition: top var(--dur-1) var(--ease);
}
.skip-link:focus { top: 1rem; color: #fff; }

/* ---- Reveal on scroll --------------------------------------------------- */

.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity var(--dur-3) var(--ease-out),
    transform var(--dur-3) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.reveal.is-in { opacity: 1; transform: none; }

/* ---- Motion, once a block has arrived -----------------------------------
   Everything below is decoration on top of the reveal: it only ever runs
   after `is-in` is set, and it is skipped entirely for visitors who ask for
   reduced motion. Nothing here is load-bearing — if it never runs, the page
   still reads exactly the same. */

/* ---- Split headlines -----------------------------------------------------
   motion.js rebuilds a headline as one masked span per word. Until it says
   go, the words sit below their mask; `is-written` is the failsafe that puts
   them back with no transition at all. */

.is-split .word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  /* the mask has to clear descenders and the ® mark */
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
.is-split .word__in {
  display: inline-block;
  transform: translateY(112%);
}
.is-split.is-writing .word__in {
  transform: none;
  transition: transform 900ms var(--ease-out);
  transition-delay: calc(var(--w, 0) * 55ms);
}
.is-split.is-written .word__in {
  transform: none !important;
  transition: none !important;
}

/* ---- Parallax ------------------------------------------------------------
   The drift is applied inline by motion.js; the extra height is what keeps a
   moved photograph from showing a gap at either edge. */

/* The photograph keeps its top edge on the header line and carries its
   slack below, so the drift can only ever pull it upward — start it above
   the line instead and it shows through the strip the header sits on. */
.page-head__bg.is-parallax { top: var(--header-h); height: calc(100% - var(--header-h) + 12%); }
/* The scale is the slack the drift moves inside, so it is declared here
   rather than written by the first frame — the crop must never be short
   of cover, even for the moment before the script runs. */
.media-frame img.is-parallax { transform: scale(1.08); will-change: transform; }

/* A split headline runs its own entrance; the banner's CSS fade would be a
   second one on top of it. */
.page-head--media h1.is-split { animation: none; }

@media (prefers-reduced-motion: no-preference) {
  /* The eyebrow's three ribs draw themselves in, the way the section rule
     does on the page headers. */
  .reveal.is-in .eyebrow::before {
    animation: rib-grow 520ms var(--ease-out) 140ms both;
  }

  /* A photograph fades up rather than snapping in with its text block. */
  .reveal.is-in .media-frame img {
    animation: media-settle 800ms var(--ease) both;
  }

  /* Interior page banners: breadcrumb, title and summary arrive in order,
     over a photograph that settles out of a slow push. These run on load
     rather than on scroll — the header is above the fold on every page. */
  .page-head--media .breadcrumb { animation: head-in 700ms var(--ease-out) 60ms both; }
  .page-head--media h1 { animation: head-in 700ms var(--ease-out) 150ms both; }
  .page-head--media p { animation: head-in 700ms var(--ease-out) 240ms both; }
  .page-head__bg { animation: head-settle 1500ms var(--ease-out) both; }
}

@keyframes rib-grow {
  from { width: 0; opacity: 0; }
  to   { width: 26px; opacity: 0.85; }
}
@keyframes media-settle {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes head-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
@keyframes head-settle {
  from { transform: scale(1.06); }
  to   { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
