/* ==========================================================================
   Poytaxt Group — "Grammage"
   A spec-sheet system: paper white ground, mill blue structure, machine
   yellow used once per element as a marker. Every figure on the site is set
   in mono with tabular numerals so columns of data line up like a datasheet.
   ========================================================================== */

/* --- Tokens ------------------------------------------------------------- */

:root {
  /* Surfaces */
  --paper: #f5f7f6;
  --paper-2: #ffffff;
  --paper-3: #ebefed;

  /* Ink */
  --ink: #0d1418;
  --ink-2: #41525a;
  --ink-3: #6e7e85;

  /* Structure */
  --navy: #072d4c;
  --navy-2: #0b3e68;
  --mill: #0b4f8f;
  --wet: #2f86c9;

  /* Marker */
  --yellow: #ffc400;

  /* Rules */
  --rule: #dadfdd;
  --rule-2: #c3ccc9;
  --rule-dark: rgba(255, 255, 255, 0.16);

  /* Type */
  --display: 'Wix Madefor Display', 'IBM Plex Sans', system-ui, sans-serif;
  --body: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --step--2: 0.6875rem;
  --step--1: 0.8125rem;
  --step-0: 1.0625rem;
  --step-1: 1.1875rem;
  --step-2: clamp(1.375rem, 1.2rem + 0.7vw, 1.75rem);
  --step-3: clamp(1.625rem, 1.3rem + 1.5vw, 2.375rem);
  --step-4: clamp(2rem, 1.5rem + 2.4vw, 3.25rem);
  --step-5: clamp(2.5rem, 1.4rem + 5vw, 5rem);

  /* Space */
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
  --section-y: clamp(4rem, 8vw, 7.5rem);
  --wrap: 1240px;
  --header-h: 68px;
  --util-h: 44px;

  --radius: 4px;
  --radius-lg: 8px;

  --shadow-sm: 0 1px 2px rgba(13, 20, 24, 0.06), 0 2px 8px rgba(13, 20, 24, 0.04);
  --shadow-md: 0 2px 4px rgba(13, 20, 24, 0.05), 0 12px 32px rgba(13, 20, 24, 0.08);

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* --- Reset -------------------------------------------------------------- */

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

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--step-0);
  line-height: 1.6;
  font-feature-settings: 'kern' 1;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img,
svg,
video,
iframe {
  display: block;
  max-width: 100%;
}

img,
video {
  height: auto;
}

button,
input,
textarea,
select {
  font: inherit;
  color: inherit;
}

ul,
ol {
  list-style: none;
  padding: 0;
}

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

:focus-visible {
  outline: 2px solid var(--wet);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection {
  background: var(--yellow);
  color: var(--ink);
}

/* --- Primitives --------------------------------------------------------- */

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

.section {
  padding-block: var(--section-y);
  scroll-margin-top: calc(var(--header-h) + 8px);
}

.section--tight {
  padding-block: clamp(3rem, 6vw, 5rem);
}

.section--dark {
  background: var(--navy);
  color: #fff;
}

.section--paper {
  background: var(--paper-2);
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--ink);
  color: #fff;
  padding: 0.75rem 1.25rem;
  font-family: var(--mono);
  font-size: var(--step--1);
}

.skip:focus {
  left: 0.5rem;
  top: 0.5rem;
}

/* Mono micro-label. The recurring voice of the whole system. */
.micro {
  font-family: var(--mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.section--dark .micro {
  color: rgba(255, 255, 255, 0.62);
}

/* Section header: yellow tick, mono eyebrow, display title, lede. */
.head {
  max-width: 60ch;
  margin-bottom: clamp(2rem, 4vw, 3.25rem);
}

.head__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  margin-bottom: 1.125rem;
}

.head__eyebrow::before {
  content: '';
  width: 1.75rem;
  height: 3px;
  background: var(--yellow);
  flex: none;
}

.head__title {
  font-family: var(--display);
  font-size: var(--step-3);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.025em;
  text-wrap: balance;
}

.head__text {
  margin-top: 1rem;
  color: var(--ink-2);
  max-width: 56ch;
}

.section--dark .head__text {
  color: rgba(255, 255, 255, 0.76);
}

/* --- Buttons ------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  padding: 0.9375rem 1.5rem;
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease),
    border-color 0.2s var(--ease), transform 0.2s var(--ease);
  text-align: center;
}

.btn:active {
  transform: translateY(1px);
}

.btn--primary {
  background: var(--mill);
  color: #fff;
}

.btn--primary:hover {
  background: var(--navy-2);
}

/* The single loudest element on the page: the one that starts an enquiry. */
.btn--accent {
  background: var(--yellow);
  color: var(--ink);
}

.btn--accent:hover {
  background: #ffd23f;
}

.btn--ghost {
  border-color: var(--rule-2);
  color: var(--ink);
  background: transparent;
}

.btn--ghost:hover {
  border-color: var(--ink);
  background: var(--ink);
  color: #fff;
}

.btn--on-dark {
  border-color: rgba(255, 255, 255, 0.32);
  color: #fff;
  background: transparent;
}

.btn--on-dark:hover {
  background: #fff;
  color: var(--ink);
  border-color: #fff;
}

.btn--block {
  width: 100%;
}

/* ==========================================================================
   Header
   ========================================================================== */

/* The utility bar folds away once you start reading, and it does so by
   scrolling off the top: the whole header sticks --util-h *above* the viewport,
   so .bar comes to rest flush at y=0 with the utility bar just out of frame.

   This used to be a max-height transition on .util instead. That collapsed 44px
   of in-flow height above the viewport, which made Chrome's scroll anchoring
   subtract the same 44px from scrollY to hold the visible content still — which
   dropped scrollY back under the 24px threshold in JS/app.js, which re-expanded
   the bar, which pushed scrollY back over the threshold. Every offset in
   (24, 68] oscillated forever at frame rate and tore the page apart. Folding via
   the sticky offset costs no layout at all, so there is nothing for anchoring to
   react to. Keep it that way: nothing on this header may change document height
   on scroll. */
.header {
  position: sticky;
  top: calc(-1 * var(--util-h));
  z-index: 50;
  background: var(--paper-2);
  border-bottom: 1px solid var(--rule);
}

/* Once the utility bar is out of frame the bar floats over the page, so lift it.
   A shadow is compositor-only — unlike the height it replaced, it cannot feed
   back into scroll position. */
.header.is-scrolled {
  box-shadow: var(--shadow-sm);
}

/* Utility bar: phones, email, enquiry. */
.util {
  background: var(--navy);
  color: rgba(255, 255, 255, 0.78);
}

/* --util-h is the header's sticky offset, so this height is load-bearing:
   change one and change the other. */
.util__inner {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: var(--util-h);
}

.util__link {
  font-family: var(--mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.375rem 0.5rem;
  color: inherit;
  transition: color 0.2s var(--ease);
  white-space: nowrap;
}

.util__link:hover {
  color: #fff;
}

/* An address is not a label — it keeps its own casing. */
.util__link--email {
  text-transform: none;
  letter-spacing: 0.03em;
  font-size: var(--step--1);
}

.util__spacer {
  flex: 1;
}

.util__cta {
  background: var(--yellow);
  color: var(--ink);
  font-weight: 600;
  padding: 0.5rem 1rem;
  border-radius: var(--radius);
}

.util__cta:hover {
  background: #ffd23f;
  color: var(--ink);
}

/* Contacts dropdown */
.drop {
  position: relative;
}

.drop__toggle {
  background: none;
  border: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.drop__toggle::after {
  content: '';
  width: 0.4rem;
  height: 0.4rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-2px);
  transition: transform 0.2s var(--ease);
}

.drop__toggle[aria-expanded='true']::after {
  transform: rotate(-135deg) translateY(-2px);
}

.drop__menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 17rem;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: 0.375rem;
  display: none;
  z-index: 60;
}

.drop__menu[data-open='true'] {
  display: block;
}

.drop__item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.625rem 0.75rem;
  border-radius: 2px;
  color: var(--ink);
  transition: background-color 0.15s var(--ease);
}

.drop__item:hover {
  background: var(--paper-3);
}

.drop__num {
  font-family: var(--mono);
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.drop__name {
  font-size: var(--step--1);
  color: var(--ink-3);
}

/* Main bar */
.bar {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: var(--header-h);
}

.bar__logo {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex: none;
}

.bar__logo img {
  width: 44px;
  height: 44px;
  object-fit: contain;
}

.bar__wordmark {
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.0625rem;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.bar__wordmark span {
  display: block;
  font-family: var(--mono);
  font-size: 0.5625rem;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 2px;
}

.bar__nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.bar__link {
  position: relative;
  padding: 0.5rem 0.75rem;
  font-size: var(--step--1);
  font-weight: 500;
  color: var(--ink-2);
  transition: color 0.2s var(--ease);
}

.bar__link::after {
  content: '';
  position: absolute;
  left: 0.75rem;
  right: 0.75rem;
  bottom: 0.125rem;
  height: 2px;
  background: var(--yellow);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.25s var(--ease);
}

.bar__link:hover {
  color: var(--ink);
}

.bar__link:hover::after {
  transform: scaleX(1);
}

.lang {
  display: flex;
  align-items: center;
  border: 1px solid var(--rule-2);
  border-radius: var(--radius);
  overflow: hidden;
  margin-left: 0.5rem;
  flex: none;
}

.lang a,
.lang span {
  font-family: var(--mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.08em;
  padding: 0.375rem 0.5625rem;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

.lang [aria-current='true'] {
  background: var(--ink);
  color: #fff;
}

.lang a:not([aria-current='true']):hover {
  background: var(--paper-3);
}

/* Mobile menu button */
.burger {
  display: none;
  width: 44px;
  height: 44px;
  border: 1px solid var(--rule-2);
  border-radius: var(--radius);
  background: none;
  cursor: pointer;
  padding: 0;
  margin-left: auto;
  position: relative;
}

.burger span,
.burger::before,
.burger::after {
  content: '';
  position: absolute;
  left: 11px;
  right: 11px;
  height: 1.5px;
  background: var(--ink);
  transition: transform 0.25s var(--ease), opacity 0.2s var(--ease);
}

.burger::before {
  top: 15px;
}

.burger span {
  top: 21px;
}

.burger::after {
  bottom: 15px;
}

.burger[aria-expanded='true']::before {
  transform: translateY(6px) rotate(45deg);
}

.burger[aria-expanded='true'] span {
  opacity: 0;
}

.burger[aria-expanded='true']::after {
  transform: translateY(-6px) rotate(-45deg);
}

/* Mobile drawer */
.drawer {
  display: none;
  border-top: 1px solid var(--rule);
  background: var(--paper-2);
  padding: 1rem var(--gutter) 1.5rem;
  max-height: calc(100dvh - var(--header-h));
  overflow-y: auto;
}

.drawer[data-open='true'] {
  display: block;
}

.drawer__link {
  display: block;
  padding: 0.875rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: var(--step-1);
  font-weight: 500;
}

.drawer__group {
  margin-top: 1.5rem;
}

.drawer__group .micro {
  display: block;
  margin-bottom: 0.75rem;
}

.drawer__phone {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 0;
  font-family: var(--mono);
  font-size: var(--step--1);
}

.drawer__phone span:last-child {
  color: var(--ink-3);
  font-family: var(--body);
}

.drawer .btn {
  margin-top: 1.25rem;
}

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  position: relative;
  isolation: isolate;
  background: var(--navy);
  color: #fff;
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.hero__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 1.6s var(--ease);
}

.hero__media img.is-active {
  opacity: 1;
}

/* Mill blue wash so white type always clears AA over any of the four photos. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
      104deg,
      rgba(7, 45, 76, 0.94) 0%,
      rgba(7, 45, 76, 0.86) 42%,
      rgba(7, 45, 76, 0.62) 100%
    ),
    linear-gradient(to top, rgba(4, 24, 41, 0.9), transparent 55%);
}

.hero__inner {
  padding-block: clamp(4rem, 11vw, 8.5rem) clamp(3rem, 6vw, 4.5rem);
  max-width: 60rem;
}

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  color: rgba(255, 255, 255, 0.72);
  margin-bottom: 1.5rem;
}

.hero__eyebrow::before {
  content: '';
  width: 2.25rem;
  height: 3px;
  background: var(--yellow);
  flex: none;
}

.hero__title {
  font-family: var(--display);
  font-size: var(--step-5);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.04em;
}

.hero__text {
  margin-top: 1.5rem;
  max-width: 46ch;
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.3125rem);
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.86);
}

.hero__actions {
  margin-top: 2.25rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

/* Grade band: the nine grades actually in the portfolio, running as a strip
   along the foot of the hero — the paper equivalent of a price ticker. */
.grades {
  position: relative;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(4, 24, 41, 0.55);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  overflow: hidden;
}

.grades__label {
  flex: none;
  padding: 0.875rem var(--gutter);
  border-right: 1px solid rgba(255, 255, 255, 0.16);
  background: var(--yellow);
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
}

.grades__viewport {
  overflow: hidden;
  flex: 1;
}

.grades__track {
  display: flex;
  width: max-content;
  animation: ticker 46s linear infinite;
}

.grades__track li {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  padding: 0.875rem 1.25rem;
  font-family: var(--mono);
  font-size: var(--step--2);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.8);
  white-space: nowrap;
}

.grades__track li::after {
  content: '';
  width: 4px;
  height: 4px;
  background: var(--yellow);
  flex: none;
}

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

/* An infinite animation is composited for as long as it runs, and this one runs
   over a backdrop-filter — so left alone it re-blurs the hero photo every frame
   from anywhere on the page, footer included. JS/app.js parks it off screen. */
.grades.is-paused .grades__track,
.grades:hover .grades__track {
  animation-play-state: paused;
}

/* ==========================================================================
   Ledger — the recurring data table
   ========================================================================== */

.ledger {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: 1px solid var(--rule);
  border-left: 1px solid var(--rule);
}

.ledger__cell {
  position: relative;
  padding: clamp(1.25rem, 2.5vw, 1.875rem) clamp(1rem, 2vw, 1.5rem);
  border-right: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.ledger__cell::before {
  content: '';
  position: absolute;
  top: -1px;
  left: -1px;
  width: 2rem;
  height: 3px;
  background: var(--yellow);
}

.ledger__value {
  font-family: var(--mono);
  font-size: var(--step-4);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.ledger__label {
  margin-top: 0.75rem;
  font-size: var(--step--1);
  line-height: 1.45;
  color: var(--ink-2);
}

.ledger__sub {
  font-size: var(--step--1);
  line-height: 1.45;
  color: var(--ink-3);
}

/* Ledger on a dark ground */
.ledger--dark {
  border-color: var(--rule-dark);
}

.ledger--dark .ledger__cell {
  border-color: var(--rule-dark);
}

.ledger--dark .ledger__value {
  color: #fff;
}

.ledger--dark .ledger__label {
  color: rgba(255, 255, 255, 0.82);
}

.ledger--dark .ledger__sub {
  color: rgba(255, 255, 255, 0.58);
}

/* ==========================================================================
   About
   ========================================================================== */

.about__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}

.about__prose p + p {
  margin-top: 1.125rem;
}

.about__prose p {
  color: var(--ink-2);
  max-width: 46ch;
}

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

/* Figures band over the warehouse photograph */
.band {
  position: relative;
  isolation: isolate;
  background: var(--navy) url('../IMG/bg.jpg') center / cover no-repeat;
  color: #fff;
  padding-block: clamp(3rem, 6vw, 5rem);
}

.band::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgba(7, 45, 76, 0.93), rgba(4, 24, 41, 0.95));
}

.band__label {
  display: block;
  margin-bottom: 1.5rem;
}

/* ==========================================================================
   Timeline — the spine carries the chronology, the bars carry the growth
   ========================================================================== */

/* A legend, not a second eyebrow: the swatch matches the bar so the reader
   knows what the widths below are measuring. */
.tl__legend {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
  color: var(--ink-3);
}

.tl__legend::before {
  content: '';
  width: 1.75rem;
  height: 0.5rem;
  background: var(--mill);
}

.tl {
  /* The node sits at the vertical centre of the year, and the spine is trimmed
     to the first and last node. Sharing one value keeps them from drifting. */
  --tl-pad: clamp(1.5rem, 3vw, 2.5rem);
  --tl-node-y: calc(var(--tl-pad) + clamp(0.875rem, 0.7rem + 0.55vw, 1.25rem));
}

.tl__entry {
  position: relative;
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr);
  gap: clamp(1.25rem, 3vw, 2.5rem);
  padding-block: var(--tl-pad);
  padding-left: clamp(1.5rem, 3vw, 2.25rem);
}

/* Specificity has to beat `.reveal`, which sets the `transition` shorthand
   later in this file and would otherwise reset the delay to zero. */
.tl__entry.reveal {
  transition-delay: calc(var(--i, 0) * 60ms);
}

/* The spine. It starts at the first node and stops at the last rather than
   running past either end. */
.tl__entry::after {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--rule);
}

.tl__entry:first-child::after {
  top: var(--tl-node-y);
}

.tl__entry:last-child::after {
  bottom: auto;
  height: var(--tl-node-y);
}

/* The node: the same yellow marker bar the rest of the site uses, laid across
   the spine so it points at the year. */
.tl__entry::before {
  content: '';
  position: absolute;
  z-index: 1;
  left: 0;
  top: var(--tl-node-y);
  width: clamp(0.75rem, 2vw, 1.125rem);
  height: 3px;
  background: var(--yellow);
}

.tl__year {
  font-family: var(--mono);
  font-size: clamp(1.75rem, 1.4rem + 1.2vw, 2.5rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--mill);
}

.tl__body {
  display: grid;
  gap: 1.125rem;
  align-content: start;
}

/* --- Capacity bar ----------------------------------------------------- */

.tl__cap {
  display: grid;
  gap: 0.5rem;
}

/* Both sit on the same bottom edge so the label never crowds the bar. */
.tl__cap-value,
.tl__held {
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
  min-height: 1.5rem;
  line-height: 1;
}

.tl__cap-value {
  font-family: var(--mono);
  font-size: clamp(1.125rem, 1rem + 0.5vw, 1.5rem);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  /* Thousands are separated by a space; a full mono space is too wide. */
  word-spacing: -0.22em;
  color: var(--ink);
}

.tl__cap-unit {
  font-family: var(--body);
  font-size: var(--step--2);
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  word-spacing: normal;
  color: var(--ink-3);
}

.tl__held {
  font-family: var(--mono);
  font-size: var(--step--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.tl__bar {
  height: 0.5rem;
  background: var(--paper-3);
  overflow: hidden;
}

/* Years with no stated supply figure keep the slot but show an empty track,
   so the gap reads as absent data rather than a missing element. */
.tl__bar--empty {
  background: none;
  border: 1px dashed var(--rule-2);
}

.tl__bar-fill {
  display: block;
  width: var(--w, 0%);
  height: 100%;
  background: var(--mill);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.9s var(--ease);
  /* Each bar draws just after its own row has landed. */
  transition-delay: calc(var(--i, 0) * 60ms + 180ms);
}

.tl__entry.is-in .tl__bar-fill {
  transform: scaleX(1);
}

.tl__rows {
  display: grid;
  gap: 1rem;
}

.tl__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 1.5rem;
  align-items: baseline;
  padding-bottom: 0.875rem;
  border-bottom: 1px dashed var(--rule);
}

.tl__row:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.tl__text {
  color: var(--ink-2);
  font-size: var(--step--1);
  line-height: 1.5;
}

.tl__figure {
  font-family: var(--mono);
  font-size: var(--step-1);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  /* Thousands are separated by a space; a full mono space is too wide. */
  word-spacing: -0.22em;
  white-space: nowrap;
  text-align: right;
  color: var(--ink);
}

.tl__unit {
  display: block;
  font-size: var(--step--2);
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.tl__staff {
  /* The body is a grid, which would otherwise stretch the pill edge to edge. */
  justify-self: start;
  display: inline-flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding: 0.5rem 0.75rem;
  background: var(--paper-3);
  border-radius: var(--radius);
  font-size: var(--step--1);
  color: var(--ink-2);
}

.tl__staff b {
  font-family: var(--mono);
  font-weight: 600;
  color: var(--ink);
}

/* ==========================================================================
   Cards — products and services
   ========================================================================== */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(clamp(15rem, 27vw, 21rem), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}

.card {
  display: flex;
  flex-direction: column;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease),
    transform 0.25s var(--ease);
}

.card:hover {
  border-color: var(--rule-2);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.card__media {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--paper-3);
  overflow: hidden;
}

.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s var(--ease);
}

.card:hover .card__media img {
  transform: scale(1.03);
}

.card__index {
  position: absolute;
  top: 0;
  left: 0;
  background: var(--paper-2);
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.08em;
  padding: 0.375rem 0.625rem;
  border-bottom-right-radius: var(--radius);
}

.card__body {
  padding: 1.125rem 1.25rem 1.375rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  flex: 1;
}

.card__title {
  font-family: var(--display);
  font-size: var(--step-1);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.015em;
}

.card__note {
  font-size: var(--step--1);
  color: var(--ink-3);
  line-height: 1.45;
}

/* Spec strip: grammage / format / mill. Renders only when data exists. */
.card__spec {
  margin-top: auto;
  padding-top: 0.875rem;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: var(--step--2);
  letter-spacing: 0.06em;
  color: var(--ink-3);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.card__spec span::after {
  content: ' ·';
  color: var(--rule-2);
}

.card__spec span:last-child::after {
  content: '';
}

/* ==========================================================================
   Video
   ========================================================================== */

.video {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--ink);
  border: 1px solid var(--rule);
}

.video video {
  width: 100%;
  aspect-ratio: 16 / 7;
  object-fit: cover;
}

.video__tag {
  position: absolute;
  left: 1rem;
  bottom: 1rem;
  background: rgba(4, 24, 41, 0.78);
  backdrop-filter: blur(6px);
  color: #fff;
  padding: 0.5rem 0.875rem;
  border-radius: var(--radius);
  font-family: var(--mono);
  font-size: var(--step--2);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* ==========================================================================
   Partners
   ========================================================================== */

.partners {
  overflow: hidden;
  border-block: 1px solid var(--rule);
  padding-block: 1.75rem;
  background: var(--paper-2);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.partners__track {
  display: flex;
  align-items: center;
  gap: clamp(2rem, 5vw, 4rem);
  width: max-content;
  /* Tuned to the number of logos in the wall — a shorter track needs a
     shorter duration to keep the same apparent speed. */
  animation: ticker 38s linear infinite;
}

/* Same deal as .grades above — an infinite animation under a mask-image. */
.partners.is-paused .partners__track,
.partners:hover .partners__track {
  animation-play-state: paused;
}

.partners__track img {
  height: clamp(2.25rem, 5vw, 3.25rem);
  width: auto;
  object-fit: contain;
  filter: grayscale(1);
  opacity: 0.62;
  transition: filter 0.3s var(--ease), opacity 0.3s var(--ease);
}

.partners__track img:hover {
  filter: grayscale(0);
  opacity: 1;
}

/* ==========================================================================
   Advantages
   ========================================================================== */

.adv {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}

.adv__item {
  position: relative;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 3vw, 2rem);
  display: flex;
  flex-direction: column;
  gap: 1.125rem;
  overflow: hidden;
}

/* The accent sits on the card edge rather than behind the icon — these are
   multicoloured stock icons and a yellow tile fights them. */
.adv__item::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 2.5rem;
  height: 3px;
  background: var(--yellow);
}

.adv__icon {
  width: 3.25rem;
  height: 3.25rem;
  display: grid;
  place-items: center;
  background: var(--paper-3);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  flex: none;
}

.adv__icon img {
  width: 1.75rem;
  height: 1.75rem;
  object-fit: contain;
}

.adv__text {
  font-family: var(--display);
  font-size: var(--step-1);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.015em;
}

/* ==========================================================================
   Cycles
   ========================================================================== */

.tabs {
  display: inline-flex;
  border: 1px solid var(--rule-2);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: clamp(1.75rem, 3vw, 2.5rem);
  flex-wrap: wrap;
  background: var(--paper-2);
}

.tabs__btn {
  border: 0;
  background: none;
  cursor: pointer;
  padding: 0.8125rem 1.25rem;
  font-family: var(--mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

.tabs__btn + .tabs__btn {
  border-left: 1px solid var(--rule-2);
}

.tabs__btn:hover {
  background: var(--paper-3);
}

.tabs__btn[aria-selected='true'] {
  background: var(--mill);
  color: #fff;
}

.tabpanel[hidden] {
  display: none;
}

/* Column count comes from the number of steps, so a row never ends in a
   dead cell. Overridden at the narrow breakpoints below. */
.steps {
  display: grid;
  grid-template-columns: repeat(var(--cols, 4), minmax(0, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.step {
  background: var(--paper-2);
  padding: clamp(1.125rem, 2.5vw, 1.625rem);
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
}

.step__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.step__n {
  font-family: var(--mono);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--mill);
}

.step__icon {
  width: 2.25rem;
  height: 2.25rem;
  object-fit: contain;
  opacity: 0.85;
}

.step__text {
  font-size: var(--step--1);
  line-height: 1.45;
  font-weight: 500;
}

.branch {
  margin-block: 1rem;
}

.branch__label {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
}

.branch__label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--rule);
}

.branch .steps {
  border-color: var(--rule-2);
}

.branch .step {
  background: var(--paper-3);
}

/* ==========================================================================
   News
   ========================================================================== */

.news {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}

.post {
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: 100%;
}

.post__media {
  position: relative;
  aspect-ratio: 3 / 2;
  background: var(--paper-3);
}

.post__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.post__date {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  background: var(--yellow);
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.08em;
  padding: 0.25rem 0.5rem;
  border-radius: 2px;
}

.post__body {
  padding: 1.25rem 1.375rem 1.5rem;
  display: grid;
  gap: 0.75rem;
}

.post__title {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
}

.post__text p {
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--ink-2);
}

.post__text p + p {
  margin-top: 0.75rem;
}

/* Featured post: the one with no photograph, so it carries the mill blue. */
.post--featured {
  background: var(--navy);
  border-color: var(--navy);
  color: #fff;
}

.post--featured .post__body {
  padding: clamp(1.5rem, 3vw, 2rem);
}

.post--featured .post__text p {
  color: rgba(255, 255, 255, 0.8);
}

/* When it is the only post, the block spans the whole grid — cap the measure
   so the lines stay readable. */
.post--featured .post__text {
  max-width: 68ch;
}

.post__list {
  display: grid;
  gap: 0.5rem;
  margin-top: 0.25rem;
}

.post__list li {
  position: relative;
  padding-left: 1.125rem;
  font-size: var(--step--1);
  color: rgba(255, 255, 255, 0.8);
}

.post__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 0.4375rem;
  height: 1.5px;
  background: var(--yellow);
}

.post__author {
  margin-top: 0.5rem;
  padding-top: 0.875rem;
  border-top: 1px solid var(--rule-dark);
}

/* ==========================================================================
   Form
   ========================================================================== */

.formwrap {
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 4vw, 3rem);
  box-shadow: var(--shadow-sm);
}

.form__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1rem, 2.5vw, 1.75rem);
}

.field {
  display: grid;
  gap: 0.4375rem;
}

.field + .field {
  margin-top: 1rem;
}

.field > span {
  font-family: var(--mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.field input,
.field textarea {
  width: 100%;
  background: var(--paper);
  border: 1px solid var(--rule-2);
  border-radius: var(--radius);
  padding: 0.8125rem 0.9375rem;
  font-size: var(--step-0);
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.field input:hover,
.field textarea:hover {
  border-color: var(--ink-3);
}

.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--mill);
  background: var(--paper-2);
  box-shadow: 0 0 0 3px rgba(47, 134, 201, 0.18);
}

.field textarea {
  min-height: 9.5rem;
  resize: vertical;
}

.field--right {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.field--right .field {
  flex: 1;
}

.field--right .field textarea {
  height: 100%;
}

/* Honeypot. Off-screen rather than display:none so bots still find it. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.formnote {
  margin-top: 1rem;
  font-size: var(--step--1);
  min-height: 1.5rem;
}

.formnote[data-state='ok'] {
  color: #0a7f4f;
}

.formnote[data-state='error'] {
  color: #b3261e;
}

.formnote:empty {
  min-height: 0;
}

/* ==========================================================================
   Footer
   ========================================================================== */

.footer {
  background: var(--ink);
  color: rgba(255, 255, 255, 0.72);
  padding-block: clamp(3rem, 6vw, 4.5rem) 0;
}

.footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

.footer__title {
  font-family: var(--display);
  font-size: var(--step-3);
  font-weight: 800;
  letter-spacing: -0.03em;
  color: #fff;
  line-height: 1;
}

.footer__text {
  margin-top: 1rem;
  max-width: 42ch;
  font-size: var(--step--1);
  line-height: 1.6;
}

.footer__cols {
  margin-top: 2rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 2rem;
}

.footer__col .micro {
  display: block;
  margin-bottom: 0.875rem;
  color: rgba(255, 255, 255, 0.5);
}

.footer__col li + li {
  margin-top: 0.625rem;
}

.footer__col a,
.footer__col span {
  font-size: var(--step--1);
  transition: color 0.2s var(--ease);
}

.footer__col a:hover {
  color: #fff;
}

.footer__map {
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: #14202a;
}

/* No filter here. A CSS filter over an embed forces the browser to re-rasterise
   and re-filter the iframe's contents on every repaint the map makes of its own
   accord — tile fades, attribution, hover — which is constant work parked in the
   footer. If the desaturated look is wanted back, it has to come from something
   static drawn over the map, not a filter on the map itself. */
.footer__map iframe {
  width: 100%;
  height: clamp(15rem, 34vw, 24rem);
  border: 0;
}

.footer .btn {
  margin-top: 1.75rem;
}

.footer__bar {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  padding-block: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: space-between;
  align-items: center;
}

/* ==========================================================================
   Dialog
   ========================================================================== */

.modal {
  /* The `* { margin: 0 }` reset above strips the UA's `dialog { margin: auto }`,
     which is what centres a modal dialog. Put it back. */
  margin: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: 0;
  width: min(30rem, calc(100vw - 2rem));
  background: var(--paper-2);
  color: var(--ink);
  box-shadow: 0 24px 64px rgba(4, 24, 41, 0.28);
}

.modal::backdrop {
  background: rgba(4, 24, 41, 0.55);
  backdrop-filter: blur(3px);
}

.modal__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.5rem 1.5rem 0;
}

.modal__title {
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1.1;
}

.modal__close {
  flex: none;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: none;
  cursor: pointer;
  font-size: 1.125rem;
  line-height: 1;
  color: var(--ink-2);
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

.modal__close:hover {
  background: var(--ink);
  color: #fff;
}

.modal__body {
  padding: 1rem 1.5rem 1.5rem;
}

.modal__text {
  font-size: var(--step--1);
  color: var(--ink-2);
  margin-bottom: 1.25rem;
}

/* ==========================================================================
   404
   ========================================================================== */

.nf {
  min-height: 70vh;
  display: grid;
  place-content: center;
  text-align: center;
  gap: 1rem;
}

.nf__code {
  font-family: var(--mono);
  font-size: clamp(3.5rem, 12vw, 7rem);
  font-weight: 600;
  letter-spacing: -0.04em;
  color: var(--mill);
  line-height: 1;
}

.nf__title {
  font-family: var(--display);
  font-size: var(--step-3);
  font-weight: 800;
  letter-spacing: -0.025em;
}

.nf .btn {
  justify-self: center;
  margin-top: 0.5rem;
}

/* ==========================================================================
   Motion
   ========================================================================== */

.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}

.reveal.is-in {
  opacity: 1;
  transform: none;
}

/* ==========================================================================
   Breakpoints
   ========================================================================== */

@media (max-width: 1024px) {
  .about__grid {
    grid-template-columns: minmax(0, 1fr);
  }

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

@media (max-width: 900px) {
  :root {
    --header-h: 60px;
  }

  .bar__nav,
  .lang {
    display: none;
  }

  .burger {
    display: block;
  }

  .util__link--email {
    display: none;
  }

  .ledger,
  .about__ledger {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* The year moves above the body, but the spine and its nodes stay put. */
  .tl__entry {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.875rem;
  }

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

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

@media (max-width: 620px) {
  .util__inner {
    gap: 0;
  }

  .util__cta {
    padding: 0.4375rem 0.75rem;
  }

  .drop__menu {
    position: fixed;
    left: var(--gutter);
    right: var(--gutter);
    top: 52px;
    min-width: 0;
  }

  .hero__title {
    letter-spacing: -0.03em;
  }

  .hero__actions .btn {
    flex: 1 1 100%;
  }

  .grades__label {
    padding-inline: 0.875rem;
  }

  .tl__row {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.5rem;
  }

  .tl__figure {
    text-align: left;
  }

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

  /* Wrapped tabs read as a broken row; stack them into a proper list. */
  .tabs {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    width: 100%;
  }

  .tabs__btn + .tabs__btn {
    border-left: 0;
    border-top: 1px solid var(--rule-2);
  }

  .footer__bar {
    justify-content: flex-start;
  }
}

@media (max-width: 420px) {
  .ledger,
  .about__ledger {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .reveal {
    opacity: 1;
    transform: none;
  }

  /* The bars are drawn at full width straight away, and nothing waits on the
     stagger — the global duration override alone would still honour the delay. */
  .tl__bar-fill {
    transform: none;
  }

  .tl__entry.reveal,
  .tl__bar-fill {
    transition-delay: 0s;
  }

  .grades__track,
  .partners__track {
    animation: none;
    flex-wrap: wrap;
    width: 100%;
  }

  .hero__media img {
    transition: none;
  }
}

@media print {
  .header,
  .grades,
  .footer__map,
  .modal {
    display: none;
  }
}
