/* ============================================================
   Pages — homepage sections + internal page layouts.
   ============================================================ */

/* ----------------------------------------------------------------
   Background layer for content sections.
   Sections sit above the fixed video; give them an opaque bg
   so they cover the video as the user scrolls past the hero.
   ---------------------------------------------------------------- */

main {
  position: relative;
  z-index: var(--z-content);
}

/* ================================================================
   THE GLASS CANVAS — every page is one sheet of water.
   The hero region (home's full hero, internal 60vh page-heroes) is
   COMPLETELY clear: crisp, untinted, unblurred ocean. At the hero's
   bottom edge a short fade strip (main::before) eases the water into
   the frosted pane (body::after) that runs to the end of the page —
   one tint + one blur surface, so there are no per-section seams by
   construction. Sections themselves are fully transparent; they are
   just typography floating on the shared pane. Card-Glass tiles
   float on top for specific content blocks.

   Built as two stacked pseudo-elements instead of a masked backdrop-
   filter because Safari does not reliably mask backdrop output: the
   fade strip is pure tint gradient (no blur), and the blur begins
   only where the tint has already reached full strength — an 84%-
   tinted backdrop makes the blur's hard starting edge imperceptible.
   ================================================================ */
/* ==================================================================
   THE GLASS PAGE

   The ocean is behind the WHOLE page again, with the content floating
   on one continuous frosted pane rather than sitting on solid ground.

   WHY THIS WORKS NOW AND DID NOT BEFORE. Three earlier attempts left a
   visible band across the page and were reverted. The band was blamed
   on this pane's leading edge, and that was wrong — the real culprits
   were found later: .hero-overlay, which was defined THREE times and
   painted a radial pool plus a gradient reaching 70% black at the
   hero's foot, and a 428px text scrim reaching 68% black behind the
   hero copy. Both are gone. What is left is a single hard edge exactly
   at the bottom of the hero, which is a section boundary — the same
   place any page meets its first section — and reads as the top of a
   surface rather than as a smear across the water.

   So: ONE pane. No mask, no fade, no gradient. Nothing to interpolate
   is nothing to band. Every attempt to soften this edge has made it
   worse; if it ever needs adjusting, move it, do not blur it.

   TUNING. The three knobs below are the whole control surface —
   change these, not the rules underneath.
   ================================================================== */
:root {
  /* MORE TRANSPARENT, MORE TINTED. Those pull against each other inside
     a single alpha, so they are separated here into three knobs.

     Alpha comes DOWN (0.62 -> 0.54) so more water survives. The tint
     COLOUR goes deeper and bluer — from near-black #0a0f1a to #071428 —
     so the glass reads as tinted ocean rather than as grey veiling.
     And the blur goes UP (26 -> 32px), which is what pays for the lower
     alpha: heavier blur flattens the sun-glints, dropping the footage's
     peak luminance, so text keeps its contrast over a thinner tint.

     Measured on canvas at 32px blur, pearl-on-composite:

         alpha   median   95th pct   99th pct
         0.50    11.4     4.31       3.02
         0.54    11.7     4.58       3.24
         0.62    12.6     5.12       3.66

     0.54 is the lowest alpha that still clears 4.5:1 across 95% of the
     frame at this blur — the same bar the previous 0.62 met at 26px.
     More water, same legibility, because the blur did the work instead
     of the tint.

     Push toward 0.70 for more page and safer copy; toward 0.46 for more
     water, knowing body text drops under AA over the brightest frames. */
  --glass-page-tint:     0.54;
  --glass-page-colour:   8, 20, 40;
  --glass-page-blur:     32px;
  /* Lifts the colour the blur would otherwise wash out. Raised with the
     blur, since a heavier blur desaturates more. */
  --glass-page-saturate: 160%;
}

body {
  /* The pane begins at the hero's foot — a section boundary, not a
     point partway down the footage. It is FULLY on by that line: it
     starts --frost-feather earlier and ramps in, so the handover from
     the hero scrim is a gradient rather than an edge. */
  --frost-feather: 110px;
  --frost-start: max(100vh, 560px);
  --frost-start: max(100svh, 560px);
  /* Containing block for the pane below, so its `bottom: 0` means the
     end of the DOCUMENT. Without this the pane resolves against the
     initial containing block and stops one viewport down. */
  position: relative;
}
body:not(.page-home) {
  --frost-start: max(60vh, 480px);
  --frost-start: max(60svh, 480px);
}

/* THE PAGE PANE — one surface, from the hero's foot to the last pixel
   of the footer.

   It hangs off body, not main, and that is the whole point. It used to
   be main::after, which stopped at main's bottom edge and left the
   footer to frost itself separately. Two adjacent backdrop-filters do
   not join: each one blurs only the backdrop inside its own box and
   clamps at its edges, so the boundary showed up as a hard horizontal
   seam with the footer reading as a separate darker slab. Identical
   tint and blur values on both did not help — the discontinuity is in
   the sampling, not the colour.

   One element spanning both means one blur, one tint, and nothing to
   line up. The footer now paints no ground of its own at all. */
body::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--frost-start) - var(--frost-feather));
  bottom: 0;
  background: rgba(var(--glass-page-colour), var(--glass-page-tint));
  -webkit-backdrop-filter: blur(var(--glass-page-blur)) saturate(var(--glass-page-saturate));
  backdrop-filter: blur(var(--glass-page-blur)) saturate(var(--glass-page-saturate));
  /* THE PANE RAMPS IN ABOVE ITS OWN START LINE, NOT BELOW IT.

     The pane used to begin on ONE ROW: the tint stepped on and a 32px
     blur switched on at the same pixel, drawing a hard line the full
     width of the page exactly where the hero band ends. Measured 13.7
     mean luminance step on products, 35.1 on quality.

     The first fix made it worse (19 and 90.8) by masking the pane's top
     edge in place: that put the pane at ZERO opacity precisely where the
     hero scrim had just ended, so the video showed through untinted for
     the length of the feather. The discontinuity did not go away, it
     inverted and grew.

     So the pane now STARTS a feather-length early and is at full
     strength by the time it reaches --frost-start. The hero scrim above
     fades to nothing over the same span. One hands over to the other
     across 110px instead of on a single row, and because it is a mask
     the blur ramps in with the tint rather than snapping on behind it. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 var(--frost-feather));
  mask-image: linear-gradient(180deg, transparent 0, #000 var(--frost-feather));
  pointer-events: none;
  z-index: 0;
}

/* Sections float ON the pane, so they must not paint their own ground —
   an opaque section would punch a hole straight through the glass. */
.page-home main > section,
body:not(.page-home) main > section {
  position: relative;
  z-index: 1;
  background: transparent;
}

/* The cards, tiles and panels keep their own heavier glass. They now
   read as objects resting on a surface rather than as cut-outs in it,
   which is the correct hierarchy: lighter material for the ground,
   denser material for the things placed on it. */

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  /* No backdrop-filter means no frosting, and unblurred video behind
     body copy is unreadable — so fall back to a near-solid ground. */
  body::after { background: rgba(10, 15, 26, 0.94); }
}

@media (prefers-reduced-transparency: reduce) {
  body::after {
    background: rgba(10, 15, 26, 0.96);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* The weakest tier gets a solid ground rather than a full-page blur,
   which is one of the most expensive things a phone GPU can be asked
   to composite while a video plays behind it. */
html[data-perf="low"] body::after {
  background: rgba(10, 15, 26, 0.95);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* ----------------------------------------------------------------
   Ambient film grain — 3% SVG noise overlay (brief §3.1).
   Fixed-position, full-page, non-interactive. Auto-disabled on
   the low-perf tier (saves a repaint layer on weak GPUs).
   ---------------------------------------------------------------- */
body::before {
  content: "";
  position: fixed;
  inset: -50%;
  pointer-events: none;
  z-index: var(--z-grain);
  opacity: 0.03;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.6 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-repeat: repeat;
}

html[data-perf="low"] body::before { display: none; }
@media (prefers-reduced-motion: reduce) {
  body::before { display: none; }
}

/* ----------------------------------------------------------------
   Editorial typographic refinements — drop cap, pull quote,
   small caps, italic display accents.
   ---------------------------------------------------------------- */

.dropcap::first-letter {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 500;
  float: left;
  font-size: 4.4em;
  line-height: 0.9;
  margin: 0.05em 0.18em -0.05em 0;
  color: var(--color-text);
}

.italic { font-style: normal; }

.smallcaps {
  font-variant: small-caps;
  letter-spacing: 0.04em;
}

.eyebrow--mono {
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  font-weight: 400;
}

.hairline {
  display: block;
  height: 1px;
  background: var(--color-divider);
  border: none;
  width: 100%;
}
.hairline--short { width: 48px; }

.editorial-num {
  font-family: var(--font-numeric);
  font-style: normal;
  font-weight: 400;
  font-feature-settings: "tnum", "lnum";
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -0.02em;
  line-height: 1;
}

/* ============================================================
   HOMEPAGE
   ============================================================ */

/* ----------------------------------------------------------------
   Hero section
   ---------------------------------------------------------------- */

.hero {
  position: relative;
  height: 100vh;
  height: 100dvh;
  min-height: 600px;
  display: grid;
  grid-template-rows: 1fr auto;
  align-items: end;
  padding: var(--header-h) var(--gutter-x) var(--space-8);
  /* Transparent — let the fixed video show through */
  background: transparent !important;
  z-index: var(--z-content);
  overflow: hidden;
}

.hero__inner {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding-bottom: clamp(3rem, 10vh, 7rem);
}

h1.hero__tagline,
.hero__tagline {
  /* Original display serif — Cormorant Garamond — UPRIGHT (no
     italic) and rendered bold for impact. Listed twice to outweigh
     h1.display in base.css. */
  font-family: "Cormorant Garamond", "GT Sectra", Georgia, serif;
  font-style: normal;
  font-weight: 600;
  font-size: clamp(3rem, 7vw, 6rem);
  line-height: 1.05;
  letter-spacing: -0.015em;
  color: var(--color-text);
  /* Wide enough to keep "Delivering Certainty." on a single line at
     desktop sizes — overridden on mobile by the rule below. */
  max-width: none;
  opacity: 0;
  transform: translateY(40px);
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.9),
    0 2px 14px rgba(0, 0, 0, 0.75),
    0 8px 48px rgba(0, 0, 0, 0.65);
}

/* Each sentence is its own line on every viewport. */
.hero__tagline-line {
  display: block;
}

body.lang-cn .hero__tagline {
  font-family: var(--font-cn);
  letter-spacing: 0.02em;
  font-weight: 600;
}

.hero__cue {
  position: absolute;
  bottom: var(--space-4);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  opacity: 0;
}

.hero__cue-line {
  display: block;
  width: 1px;
  height: 32px;
  background: linear-gradient(180deg, transparent 0%, var(--color-text) 100%);
  animation: heroCue 1.8s var(--ease-out) infinite;
}

.hero__cue-text {
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

@keyframes heroCue {
  0%, 100% { transform: translateY(0); opacity: 1; }
  50%      { transform: translateY(8px); opacity: 0.4; }
}

@media (max-width: 768px) {
  .hero { padding: var(--header-h-mobile) var(--gutter-x) var(--space-6); }
  .hero__inner { padding-bottom: var(--space-8); }
}

/* Mobile tagline — each word on its own line, gentle gap between
   sentences. word-spacing: 100vw is the canonical CSS-only trick to
   force every space to break the line; combined with display:block
   on each sentence wrapper it gives a clean stair-step layout. */
@media (max-width: 640px) {
  h1.hero__tagline,
  .hero__tagline {
    font-size: clamp(2.625rem, 13vw, 3.75rem);
    line-height: 1.1;
    max-width: none;
  }
  .hero__tagline-line {
    word-spacing: 100vw;
  }
  .hero__tagline-line + .hero__tagline-line {
    margin-top: 0.5em;
  }
  /* CN doesn't have spaces between words, so the trick above is
     a no-op there — fall back to a clean two-line layout. */
  body.lang-cn .hero__tagline-line {
    word-spacing: normal;
  }
}

/* ----------------------------------------------------------------
   Stats section
   ---------------------------------------------------------------- */

.stats {
  padding-block: clamp(5rem, min(12.0vw, 18.0vh), 9rem);
}

.stats__eyebrow {
  margin-bottom: var(--space-8);
}

.stats__grid {
  display: grid;
  grid-template-columns: 5fr 4fr 3fr;
  gap: var(--space-8);
  align-items: end;
}

.stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Asymmetric vertical stagger — editorial */
.stat--volume   { padding-top: var(--space-6); }
.stat--countries { padding-top: var(--space-12); }

.stat__value {
  /* Sans-serif numerics that match the label below (--font-sans).
     Modern numerals, tabular figures so digit widths line up. */
  font-family: var(--font-sans);
  font-size: var(--fs-stat);
  font-weight: 500;
  line-height: 0.95;
  letter-spacing: -0.035em;
  color: var(--color-text);
  display: inline-block;
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum", "lnum";
}

.stat__suffix {
  font-family: var(--font-sans);
  font-size: 0.42em;
  font-weight: 500;
  font-style: normal;
  color: var(--color-text-muted);
  margin-left: 0.22em;
  letter-spacing: 0;
  font-variant-numeric: normal;
  vertical-align: 0.32em;
}

body.lang-cn .stat__suffix {
  font-family: var(--font-cn);
  font-size: 0.36em;
}

.stat .rule-red--thin {
  margin-block: var(--space-3) 0;
}

.stat__label {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  color: var(--color-text);
  text-transform: uppercase;
  margin-top: var(--space-2);
}

@media (max-width: 900px) {
  .stats__grid {
    grid-template-columns: 1fr;
    gap: var(--space-6);
  }
  .stat--volume,
  .stat--countries { padding-top: 0; }
}

/* ----------------------------------------------------------------
   Three Principles
   ---------------------------------------------------------------- */

.principles__header {
  margin-bottom: var(--space-10);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  max-width: 56ch;
}

.principles__heading {
  font-size: clamp(2rem, 4vw, 3rem);
  line-height: 1.1;
}

.principles__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}

.principle {
  position: relative;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-divider);
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  transition:
    border-color var(--dur-short) var(--ease-out),
    transform    var(--dur-short) var(--ease-out),
    background-color var(--dur-short) var(--ease-out);
}

/* Hover lift only on devices with a real cursor — touch devices
   stay completely static, no tap-feedback visuals. */
@media (hover: hover) and (pointer: fine) {
  .principle:hover {
    border-color: var(--color-brand);
    transform: translateY(-4px);
    background: #131313;
  }
}

.principle__num {
  font-family: var(--font-numeric);
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum", "lnum";
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--color-brand);
  letter-spacing: 0.04em;
  display: inline-block;
  margin-bottom: var(--space-3);
}

.principle__title {
  font-size: var(--fs-xl);
  line-height: 1.15;
}

.principle__body {
  font-size: var(--fs-base);
  line-height: 1.6;
  max-width: 36ch;
  color: var(--color-text);
  opacity: 0.78;
}

@media (max-width: 900px) {
  .principles__grid { grid-template-columns: 1fr; gap: var(--space-2); }
}

/* ----------------------------------------------------------------
   Who We Are
   ---------------------------------------------------------------- */

.who__grid {
  display: grid;
  grid-template-columns: 4fr 6fr;
  gap: var(--space-8);
  align-items: start;
}

.who__col-label .eyebrow {
  position: sticky;
  top: calc(var(--header-h) + var(--space-4));
}

.who__col-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: 60ch;
}

.who__col-body p {
  font-size: var(--fs-md);
  line-height: 1.5;
  max-width: none;
}

.who__col-body .link-arrow {
  margin-top: var(--space-3);
}

@media (max-width: 900px) {
  .who__grid {
    grid-template-columns: 1fr;
    gap: var(--space-4);
  }
  .who__col-label .eyebrow { position: static; }
}

/* ----------------------------------------------------------------
   Contact strip
   ---------------------------------------------------------------- */

.contact-strip__grid {
  display: grid;
  grid-template-columns: 4fr 8fr;
  column-gap: var(--space-8);
  row-gap: var(--space-6);
  align-items: center;
}

.contact-strip__heading {
  font-size: clamp(2rem, 4.5vw, 3.25rem);
  line-height: 1.05;
  font-style: normal;
  max-width: 14ch;
  margin: 0;
  align-self: center;
}

body.lang-cn .contact-strip__heading {
  font-style: normal;
}

.contact-strip__body {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-3);
}

.contact-strip__more {
  align-self: flex-start;
  margin-top: var(--space-1);
}

@media (max-width: 768px) {
  .contact-strip__grid {
    grid-template-columns: 1fr;
    align-items: start;
  }
  .contact-strip__heading { max-width: none; }
}

.contact-strip__email {
  font-size: var(--fs-md);
  font-family: var(--font-sans);
  color: var(--color-text);
  border-bottom: 1px solid var(--color-text-subtle);
  padding-bottom: 2px;
  transition:
    color var(--dur-micro) var(--ease-micro),
    border-color var(--dur-micro) var(--ease-micro);
}

.contact-strip__email:hover {
  color: var(--color-brand-hover);
  border-color: var(--color-brand-hover);
}

@media (max-width: 768px) {
  .contact-strip__grid {
    grid-template-columns: 1fr;
    gap: var(--space-4);
    align-items: start;
  }
}

/* ============================================================
   INTERNAL PAGES — shared
   ============================================================ */

.page-hero {
  padding-top: calc(var(--header-h) + var(--space-12));
  padding-bottom: var(--space-8);
  position: relative;
  overflow: hidden;       /* clips the video to the hero rect */
  isolation: isolate;     /* establishes a stacking context for layered children */
}

/* Video layer — present on About/Approach/Activities page-heros only
   (Contact + Home opt out via not having the markup). Two stacked
   <video>s cycle intro→loop, lazy-loaded by js/pageHero.js. */
.page-hero__bg-video {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
}

.page-hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  z-index: 1;
  pointer-events: none;
}

.page-hero__video.is-active {
  opacity: 1;
  z-index: 2;
}

/* Suppress browser play overlays on these too. */
.page-hero__video::-webkit-media-controls,
.page-hero__video::-webkit-media-controls-panel,
.page-hero__video::-webkit-media-controls-overlay-play-button,
.page-hero__video::-webkit-media-controls-start-playback-button,
.page-hero__video::-webkit-media-controls-play-button {
  display: none !important;
  -webkit-appearance: none !important;
  appearance: none !important;
  opacity: 0 !important;
  pointer-events: none !important;
}

/* Card glass on page-hero — the section title sits over busy
   ocean, so this softens to a readable surface. Vertical gradient
   tail blends the bottom edge into the page below. */
.page-hero__glass {
  position: absolute;
  inset: 0;
  z-index: 2;
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--surface) 36%, transparent) 0%,
      color-mix(in srgb, var(--surface) 56%, transparent) 60%,
      color-mix(in srgb, var(--surface) 30%, transparent) 100%);
  backdrop-filter: var(--glass-card-filter);
  -webkit-backdrop-filter: var(--glass-card-filter);
  pointer-events: none;
}
.page-hero__glass::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: var(--glass-highlight);
  pointer-events: none;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .page-hero__glass { background: color-mix(in srgb, var(--surface) 92%, transparent); }
}

html[data-perf="low"] .page-hero__glass {
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.page-hero__inner {
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--gutter-x);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  position: relative;
  z-index: 3;             /* sits above the video + glass */
}

.page-hero__eyebrow {
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--color-text);
  display: inline-block;
  line-height: 1;
}

.page-hero__eyebrow::before {
  content: "";
  display: inline-block;
  width: 36px;
  height: 1.5px;
  background: var(--color-brand);
  vertical-align: 0.32em;
  margin-right: 14px;
}

.page-hero__title {
  font-family: var(--font-display);
  font-size: clamp(3.5rem, 9vw, 6.5rem);
  line-height: 0.95;
  letter-spacing: -0.02em;
  color: var(--color-text);
  font-weight: 500;
}

.page-hero__rule {
  display: block;
  width: 64px;
  height: 2px;
  background: var(--color-brand);
  border: none;
  margin-top: var(--space-3);
}

@media (max-width: 768px) {
  .page-hero { padding-top: calc(var(--header-h-mobile) + var(--space-8)); }
}

/* ----------------------------------------------------------------
   Editorial section — shared layout for internal page bodies
   ---------------------------------------------------------------- */

.editorial-section {
  padding-block: clamp(4rem, min(9.0vw, 13.5vh), 7rem);
  border-top: 1px solid var(--color-divider);
}

.editorial-section:first-of-type { border-top: none; }

.editorial-grid {
  display: grid;
  grid-template-columns: 4fr 8fr;
  gap: var(--space-8);
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--gutter-x);
  align-items: start;
}

.editorial-grid__label {
  position: sticky;
  top: calc(var(--header-h) + var(--space-4));
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.editorial-grid__label .eyebrow {
  display: block;
}

.editorial-grid__heading {
  font-family: var(--font-display);
  font-size: clamp(2rem, 3.6vw, 3rem);
  line-height: 1.08;
  color: var(--color-text);
  font-weight: 500;
  letter-spacing: -0.015em;
  max-width: 14ch;
}

.editorial-grid__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: 62ch;
}

.editorial-grid__body p {
  font-size: var(--fs-md);
  line-height: 1.55;
  color: var(--color-text);
  max-width: none;
}

.editorial-grid__body p + p { margin-top: 0; }

@media (max-width: 900px) {
  .editorial-grid {
    grid-template-columns: 1fr;
    gap: var(--space-4);
  }
  .editorial-grid__label { position: static; }
}

/* ----------------------------------------------------------------
   About page body font experiment — Avenir on Mac/iOS, Manrope
   everywhere else. Both are humanist geometric sans-serifs with
   open apertures and friendly proportions; together they give a
   classy, easy-to-read feel that's distinct from Inter.
   Scoped to .page-about only.
   ---------------------------------------------------------------- */

.page-about .editorial-grid__body p,
.page-about .founder-grid__body p {
  font-family: "Avenir Next", "Avenir", "Manrope", var(--font-sans);
  font-weight: 500;
  font-size: var(--fs-md);
  line-height: 1.6;
  letter-spacing: -0.005em;
  color: var(--color-text);
}

/* ----------------------------------------------------------------
   Founder section — photo + bio
   ---------------------------------------------------------------- */

.founder-grid {
  display: grid;
  grid-template-columns: 5fr 7fr;
  gap: var(--space-8);
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--gutter-x);
  align-items: start;
}

.founder-grid__media {
  position: sticky;
  top: calc(var(--header-h) + var(--space-4));
}

.founder-photo {
  position: relative;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.founder-photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  filter: grayscale(0.15) contrast(1.05) brightness(0.95);
  border: 1px solid var(--color-divider);
}

/* Subtle red corner mark — editorial accent */
.founder-photo::before {
  content: "";
  position: absolute;
  top: -8px;
  right: -8px;
  width: 32px;
  height: 32px;
  border-top: 1px solid var(--color-brand);
  border-right: 1px solid var(--color-brand);
  pointer-events: none;
}
.founder-photo::after {
  content: "";
  position: absolute;
  bottom: -8px;
  left: -8px;
  width: 32px;
  height: 32px;
  border-bottom: 1px solid var(--color-brand);
  border-left: 1px solid var(--color-brand);
  pointer-events: none;
}

.founder-photo__caption {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-top: var(--space-2);
}

.founder-photo__name {
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--color-text);
  letter-spacing: -0.01em;
}

.founder-photo__role {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tr-eyebrow);
  color: var(--color-text-muted);
}

.founder-grid__copy {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.founder-grid__copy .eyebrow { margin-bottom: var(--space-1); }

.founder-grid__copy .editorial-grid__heading {
  margin-bottom: var(--space-3);
}

.founder-grid__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.founder-grid__body p {
  font-size: var(--fs-md);
  line-height: 1.55;
  color: var(--color-text);
  max-width: 62ch;
}

@media (max-width: 900px) {
  .founder-grid {
    grid-template-columns: 1fr;
    gap: var(--space-4);
  }
  .founder-grid__media {
    position: static;
    max-width: 420px;
  }
}

/* ----------------------------------------------------------------
   Pull-quote treatment (Founder, Risk)
   ---------------------------------------------------------------- */

.pull-quote {
  position: relative;
  padding-block: clamp(4rem, min(8.0vw, 12.0vh), 7rem);
  padding-inline: var(--gutter-x);
  text-align: center;
  background: var(--color-bg);
  border-top: 1px solid var(--color-divider);
  border-bottom: 1px solid var(--color-divider);
}

.pull-quote__inner {
  max-width: 720px;
  margin-inline: auto;
  position: relative;
}

.pull-quote__text {
  max-width: 22ch;
  margin-inline: auto;
}

.pull-quote__rule {
  display: block;
  width: 48px;
  height: 1px;
  background: var(--color-brand);
  margin: 0 auto var(--space-4);
  border: none;
}

.pull-quote__rule--bottom {
  margin: var(--space-4) auto 0;
}

.pull-quote__text {
  font-family: var(--font-display);
  font-style: normal;
  font-size: clamp(1.75rem, 4vw, 3rem);
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--color-text);
  font-weight: 500;
  text-wrap: balance;
}

.pull-quote__text::before {
  content: open-quote;
  color: var(--color-brand);
  font-family: var(--font-display);
  font-size: 1.4em;
  line-height: 0;
  position: relative;
  top: 0.25em;
  margin-right: 0.05em;
}

.pull-quote__text::after {
  content: close-quote;
  color: var(--color-brand);
  font-family: var(--font-display);
  font-size: 1.4em;
  line-height: 0;
  position: relative;
  top: 0.25em;
  margin-left: 0.05em;
}

body.lang-cn .pull-quote__text { font-style: normal; }
body.lang-cn .pull-quote__text::before,
body.lang-cn .pull-quote__text::after { content: none; }

.pull-quote__attribution {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-top: var(--space-4);
  display: block;
}

/* Hero variant — full-width oversize for the Risk pull-quote on /approach */
.pull-quote--hero {
  padding-block: clamp(6rem, min(14.0vw, 21.0vh), 11rem);
}
.pull-quote--hero .pull-quote__text {
  font-size: clamp(2rem, 5vw, 4rem);
  max-width: 22ch;
  margin-inline: auto;
}

/* ----------------------------------------------------------------
   Activities — Products list (horizontal strip)
   ---------------------------------------------------------------- */

.products-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  border-top: 1px solid var(--color-divider);
  border-bottom: 1px solid var(--color-divider);
  margin-block: var(--space-6);
}

.products-strip__item {
  padding: var(--space-3) var(--space-2);
  border-right: 1px solid var(--color-divider);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  transition: background-color var(--dur-micro) var(--ease-micro);
}

.products-strip__item:last-child { border-right: none; }
.products-strip__item:hover { background: var(--color-bg-elevated); }

.products-strip__num {
  font-family: var(--font-numeric);
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum", "lnum";
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--color-brand);
  letter-spacing: 0;
}

.products-strip__name {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--color-text);
  font-weight: 500;
}

@media (max-width: 768px) {
  .products-strip { grid-template-columns: repeat(2, 1fr); }
  .products-strip__item:nth-child(2) { border-right: none; }
  .products-strip__item:nth-child(1),
  .products-strip__item:nth-child(2) { border-bottom: 1px solid var(--color-divider); }
}

/* World map block removed — see git history for the SVG version */

/* ----------------------------------------------------------------
   Activities — Strategic position regions
   ---------------------------------------------------------------- */

.regions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  align-items: baseline;
  margin-block: var(--space-6);
  padding: var(--space-5) 0;
  border-top: 1px solid var(--color-divider);
  border-bottom: 1px solid var(--color-divider);
}

.regions__item {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 2.6vw, 2.25rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--color-text);
  display: inline-flex;
  align-items: baseline;
}

.regions__item::after {
  content: "·";
  color: var(--color-brand);
  font-size: 1em;
  margin-inline: 0.5em;
  display: inline-block;
}

.regions__item:last-child::after { content: none; }

/* ----------------------------------------------------------------
   How We Trade — three numbered items
   ---------------------------------------------------------------- */

.how-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  max-width: 62ch;
}

.how-item {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-4);
  row-gap: var(--space-2);
  padding-block: var(--space-5);
  border-top: 1px solid var(--color-divider);
}

.how-item:last-child { border-bottom: 1px solid var(--color-divider); }

.how-item__num {
  font-family: var(--font-numeric);
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum", "lnum";
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--color-brand);
  letter-spacing: 0;
  align-self: start;
  padding-top: 0.2em;
}

.how-item__heading {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 500;
  line-height: 1.15;
  color: var(--color-text);
  letter-spacing: -0.01em;
}

.how-item__body {
  grid-column: 2;
  font-size: var(--fs-base);
  line-height: 1.6;
  color: var(--color-text-muted);
  max-width: none;
}

.how-closing {
  margin-top: var(--space-6);
  font-family: var(--font-display);
  font-style: normal;
  font-size: var(--fs-md);
  line-height: 1.5;
  color: var(--color-text);
  max-width: 50ch;
}

body.lang-cn .how-closing { font-style: normal; }

@media (max-width: 600px) {
  .how-item {
    grid-template-columns: 1fr;
    gap: var(--space-1);
  }
  .how-item__body { grid-column: 1; }
  .how-item__num { padding-top: 0; }
}

/* ----------------------------------------------------------------
   Contact page
   ---------------------------------------------------------------- */

.contact-page__grid {
  display: grid;
  grid-template-columns: 4fr 8fr;
  gap: var(--space-8);
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--gutter-x);
  padding-block: clamp(2rem, min(6.0vw, 9.0vh), 5rem) clamp(6rem, min(12.0vw, 18.0vh), 10rem);
}

.contact-page__col-label {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.contact-page__col-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.contact-block {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.contact-block__label {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.contact-block__company {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 500;
  letter-spacing: -0.01em;
}

.contact-block__address {
  font-family: var(--font-sans);
  font-size: var(--fs-md);
  line-height: 1.5;
  color: var(--color-text);
}

.contact-block__address span { display: block; }

.contact-block__email {
  font-family: var(--font-sans);
  font-size: var(--fs-md);
  color: var(--color-text);
  border-bottom: 1px solid var(--color-text-subtle);
  padding-bottom: 2px;
  display: inline-block;
  width: fit-content;
  transition:
    color var(--dur-micro) var(--ease-micro),
    border-color var(--dur-micro) var(--ease-micro);
}

.contact-block__email:hover {
  color: var(--color-brand-hover);
  border-color: var(--color-brand-hover);
}

@media (max-width: 768px) {
  .contact-page__grid {
    grid-template-columns: 1fr;
    gap: var(--space-4);
  }
}

/* ============================================================
   Activities — Global Flow editorial world map.

   Visual language: satellite-at-night. Continents are near-invisible
   warm-white outlines on a near-black radial background. Markers are
   red dots; trade routes are dashed brand-red curves. HQ Hong Kong
   gets a special pulsing ring + mono label. Everything else uses
   italic serif labels with thin connector lines drawn out over water.

   The map is a 2000x857 viewBox SVG injected at runtime by map.js.
   ============================================================ */

.world-flow {
  padding-block: clamp(4rem, min(9.0vw, 13.5vh), 8rem);
  background: var(--color-bg);
  position: relative;
}

.world-flow__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-3);
}

.world-flow__eyebrow {
  letter-spacing: 0.2em;
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
}

.world-flow__heading {
  font-family: var(--font-display);
  font-size: clamp(2rem, 4vw, 3rem);
  line-height: 1.1;
  margin: 0;
}

.world-flow__rule {
  margin-top: var(--space-2);
  margin-bottom: var(--space-3);
}

/* Legend — primary (red dashed) vs secondary (gold dashed) flows.
   Sits between the heading and the map. Mono labels, small swatches
   echoing the actual line styling. */
.world-flow__legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.world-flow__legend-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.world-flow__legend-swatch {
  display: inline-block;
  width: 32px;
  height: 0;
  border-bottom: 1.5px dashed var(--color-brand);
  vertical-align: middle;
  transform: translateY(-1px);
}

.world-flow__legend-item--secondary .world-flow__legend-swatch {
  border-bottom-color: #D4A85A;
}

/* Map container — transparent. Sits on the page background so only
   the continents, routes and markers carry visual weight; no panel,
   no frame, no vignette competing for attention.
   Locked to 2000:857 aspect ratio. The container is `visibility: hidden`
   until JS finishes wiring up the SVG hidden state and adds .is-ready
   — final-defense layer that prevents any boot-window flash. */
.world-flow__map {
  width: 100%;
  max-width: 1080px;
  aspect-ratio: 2000 / 857;
  position: relative;
  overflow: hidden;
  visibility: hidden;
  background: transparent;
}

.world-flow__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 3; /* sits above the ::before atmospheric tint */
}

/* Container becomes visible only after JS has wired up hidden state. */
.world-flow__map.is-ready {
  visibility: visible;
}

/* Pre-reveal: hide every dynamic layer until the timeline drives
   them in. Targeting all top-level <g> children is simpler than
   listing each one and guarantees nothing leaks through (e.g. the
   routes used to show on page load before the map even scrolled
   into view). */
.world-flow__svg.is-pre-reveal > g {
  opacity: 0;
}

/* ----- Layer 1: graticule (latitude reference lines) ----- */
.world-flow__graticule-line {
  stroke: rgba(255, 255, 255, 0.04);
  stroke-width: 0.5;
  stroke-dasharray: 2 6;
  fill: none;
  vector-effect: non-scaling-stroke;
}

/* ----- Layer 2: country paths (continents) ----- */
/* CSS overrides the source SVG's fill="#ececec" stroke="black"
   defaults — presentation attributes have lower specificity than
   any CSS rule so this is reliable. */
.world-flow__land path {
  /* Reads as warm-paper outlines at a glance — present enough to
     ground the routes, soft enough to never compete with them. */
  fill: rgba(255, 255, 255, 0.11);
  stroke: rgba(255, 255, 255, 0.55);
  stroke-width: 0.75;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* ----- Layer 3: trade routes ----- */
.world-flow__route {
  fill: none;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  /* will-change is intentionally omitted — these tween once via
     opacity then run a low-cost dash-shift animation. */
}

/* Primary flows (red, brighter than spec, with double drop-shadow
   for a richer glow). The flowing-dash animation cycles dashoffset
   by exactly one dash period (10 = 6+4) so the loop is mathematically
   seamless — no visual jump on cycle restart. */
.world-flow__route--primary {
  stroke: rgba(255, 60, 80, 0.95);
  stroke-width: 1.5;
  stroke-dasharray: 6 4;
  filter:
    drop-shadow(0 0 1.5px rgba(255, 90, 110, 0.85))
    drop-shadow(0 0 5px rgba(220, 30, 50, 0.45));
}

.world-flow__svg.is-revealed .world-flow__route--primary {
  animation: world-flow-route-flow 1.6s linear infinite;
}

/* Secondary flows (gold). Different dash pattern (3 5 = period 8) and
   reverse direction so primary + secondary read as two crossing
   currents at a glance, even where colors overlap. */
.world-flow__route--secondary {
  stroke: rgba(232, 188, 110, 0.92);
  stroke-width: 1.1;
  stroke-dasharray: 3 5;
  filter:
    drop-shadow(0 0 1px rgba(245, 210, 140, 0.75))
    drop-shadow(0 0 3.5px rgba(200, 160, 80, 0.4));
}

.world-flow__svg.is-revealed .world-flow__route--secondary {
  animation: world-flow-route-flow-secondary 2.2s linear infinite;
}

/* Loops over exactly one dash period so the cycle is seamless. */
@keyframes world-flow-route-flow {
  to { stroke-dashoffset: -10; }
}

@keyframes world-flow-route-flow-secondary {
  to { stroke-dashoffset: 8; }   /* reverse direction; period = 8 */
}

@media (prefers-reduced-motion: reduce) {
  .world-flow__svg.is-revealed .world-flow__route--primary,
  .world-flow__svg.is-revealed .world-flow__route--secondary {
    animation: none;
  }
}

/* ----- Layer 3.5: signal "ships" — small bright dots traveling
   along each route via SVG <animateMotion>. Native compositor
   animation; doesn't rely on the JS rAF loop. ----- */
.world-flow__signal-core {
  fill: #FFFFFF;
  filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.9));
}

.world-flow__signal-halo {
  fill: rgba(255, 255, 255, 0.18);
}

.world-flow__signal--primary .world-flow__signal-core {
  fill: #FFE5C2;
  filter: drop-shadow(0 0 5px rgba(255, 130, 130, 0.95));
}
.world-flow__signal--primary .world-flow__signal-halo {
  fill: rgba(255, 90, 110, 0.22);
}

.world-flow__signal--secondary .world-flow__signal-core {
  fill: #FFEFC8;
  filter: drop-shadow(0 0 4px rgba(245, 210, 140, 0.85));
}
.world-flow__signal--secondary .world-flow__signal-halo {
  fill: rgba(232, 188, 110, 0.2);
}

@media (prefers-reduced-motion: reduce) {
  .world-flow__signals {
    display: none;
  }
}

/* ----- Layer 4: hub markers ----- */
/* The outer .world-flow__hub <g> carries the translate that pins the
   marker to its map coordinate. The inner .world-flow__hub-inner <g>
   is the animation target — scaled by the reveal timeline (and never
   touches the outer translate). */
.world-flow__hub-inner {
  transform-box: fill-box;
  transform-origin: center;
}

.world-flow__hub-dot {
  fill: var(--color-brand);
  filter: drop-shadow(0 0 4px rgba(58, 77, 110, 0.6));
}

/* Secondary destination dots — smaller, gold, softer glow. */
.world-flow__hub-dot--secondary {
  fill: #E8BC6E;
  filter: drop-shadow(0 0 4px rgba(232, 188, 110, 0.7));
}

.world-flow__hub-ring {
  fill: none;
  stroke: rgba(255, 255, 255, 0.95);
  stroke-width: 1.2;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 0 2px rgba(255, 255, 255, 0.4));
}

.world-flow__hub-pulse {
  fill: none;
  stroke: rgba(255, 255, 255, 0.75);
  stroke-width: 1.1;
  opacity: 0;
  vector-effect: non-scaling-stroke;
  transform-box: fill-box;
  transform-origin: center;
}

/* Pulsing — only engaged once .is-pulsing is applied to the SVG
   (set after the reveal timeline completes). HQ pulse expands a
   ring outward; other hubs scale subtly. */
.world-flow__svg.is-pulsing .world-flow__hub-pulse {
  animation: world-flow-hq-pulse 2.4s ease-out infinite;
}

.world-flow__svg.is-pulsing .world-flow__hub:not(.world-flow__hub--hq) .world-flow__hub-inner {
  animation: world-flow-hub-pulse 2.8s ease-in-out infinite;
  animation-delay: var(--pulse-delay, 0s);
}

@keyframes world-flow-hq-pulse {
  0%   { r: 10; opacity: 0.9; }
  100% { r: 28; opacity: 0;   }
}

@keyframes world-flow-hub-pulse {
  0%, 100% { transform: scale(1);    opacity: 1;   }
  50%      { transform: scale(1.45); opacity: 0.55; }
}

/* ----- Layer 5: labels + connector lines ----- */
.world-flow__label {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 500;
  font-size: 17px;          /* rendered against viewBox space */
  fill: rgba(245, 240, 230, 1);
  paint-order: stroke fill;
  stroke: rgba(5, 5, 7, 0.85);
  stroke-width: 3;          /* heavier halo for legibility against any background */
  letter-spacing: 0.01em;
}

.world-flow__label--hq {
  font-family: var(--font-sans);
  font-style: normal;
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.18em;
  fill: rgba(255, 255, 255, 1);
  stroke: rgba(5, 5, 7, 0.9);
  stroke-width: 3.5;
  text-transform: none;     /* text is already uppercase in source */
}

.world-flow__label-connector {
  stroke: rgba(255, 255, 255, 0.45);
  stroke-width: 1;
  fill: none;
  vector-effect: non-scaling-stroke;
}

/* ----- Reduced motion: kill the keyframe pulses ----- */
@media (prefers-reduced-motion: reduce) {
  .world-flow__svg.is-pulsing .world-flow__hub-pulse,
  .world-flow__svg.is-pulsing .world-flow__hub:not(.world-flow__hub--hq) .world-flow__hub-inner {
    animation: none;
  }
}

/* ============================================================
   Region cards (below the map).
   Editorial row of minimal cards with hairline dividers. Mobile:
   horizontal scroll-snap, otherwise even row.
   ============================================================ */
.world-flow__cards {
  margin-top: clamp(2rem, 4vw, 3.5rem);
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 0;
  width: 100%;
  max-width: 1280px;
}

.world-flow__card {
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  text-align: left;
  border-left: 1px solid var(--color-divider);
  transition: background-color var(--dur-micro) var(--ease-micro);
}

.world-flow__card:first-child {
  border-left: none;
}

.world-flow__card-name {
  font-family: var(--font-sans);
  /* Bumped from --fs-xs to --fs-sm and weight 700 so region names
     read as the dominant element of each card — products read as
     supporting metadata. */
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-text);
  margin: 0;
  line-height: 1.15;
}

.world-flow__card-products {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
  margin: 0;
  line-height: 1.4;
  letter-spacing: 0.02em;
  transition: color var(--dur-micro) var(--ease-micro);
}

.world-flow__card-rule {
  width: 24px;
  height: 1px;
  background: var(--color-brand);
  border: none;
  margin: 0;
}

@media (hover: hover) {
  .world-flow__card:hover .world-flow__card-products {
    color: var(--color-text);
  }
}

/* Mobile: hide the cards row entirely. The map markers themselves
   carry the geography; on a phone, an 8-card horizontal scroll feels
   gimmicky. The (reduced) map alone is the right call here. */
@media (max-width: 768px) {
  .world-flow__cards {
    display: none;
  }
}

/* On small viewports, hide the on-map labels entirely — the markers
   carry the network at a glance and labels collide at narrow widths. */
@media (max-width: 640px) {
  .world-flow__labels {
    display: none;
  }
}

/* ============================================================
   About — The Desk (stacked editorial spread).

   Major section beat after the Founder. Header (mono label +
   display heading + red rule + italic intro) sits above two
   stacked profile rows. Each row is a 2-column internal grid:
   monogrammed serif initials on the left, name/title/rule/bio
   on the right. A single hairline <hr> separates the two
   profiles. No boxes, no cards, no numbering — typography and
   whitespace carry the entire structure.

   Defense-in-depth animation: the section ships with the
   .is-pre-reveal class, every animated child is opacity:0 (and
   transformed where applicable) from first paint. js/desk.js
   drops the class and runs the choreographed timeline; an 8s
   safety timer paints the final state if anything stalls.
   ============================================================ */
.the-desk {
  padding-block: var(--space-16);
}

.the-desk__inner {
  display: flex;
  flex-direction: column;
}

/* ----- Section header ----- */
.desk-header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-bottom: var(--space-16);
}

.desk-heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(3rem, 6vw, 5rem);
  line-height: 1.05;
  letter-spacing: var(--tr-display);
  color: var(--color-text);
  margin: 0;
}

.desk-rule {
  width: 64px;
  height: 1px;
  background: var(--color-brand);
  margin-top: var(--space-4);
  transform-origin: left center;
}

/* CN typography swap on the section heading. */
body.lang-cn .desk-heading {
  font-family: var(--font-cn);
  font-weight: 500;
  letter-spacing: 0;
}

/* ----- Per-profile row: initials | content ----- */
.desk-profile {
  display: grid;
  grid-template-columns: minmax(180px, 25%) 1fr;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: start;
}

/* ----- Initials (left column) ----- */
.profile-initials {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(7rem, 12vw, 11rem);
  line-height: 0.9;
  letter-spacing: -0.04em;
  color: var(--color-text);
  text-align: left;
  margin: 0;
  /* GSAP scales this slightly during reveal — set a transform-origin
     so the scale happens around the visual center of the letters. */
  transform-origin: left top;
  /* Hover transition (desktop only): tonal warmth shift. */
  transition: color 400ms var(--ease-micro), opacity 400ms var(--ease-micro);
}

/* ----- Content (right column) ----- */
.profile-content {
  display: flex;
  flex-direction: column;
}

.profile-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2rem, 4vw, 3rem);
  line-height: 1.1;
  letter-spacing: var(--tr-display);
  color: var(--color-text);
  margin: 0 0 var(--space-1) 0;
}

body.lang-cn .profile-name {
  font-family: var(--font-cn);
  font-weight: 500;
  letter-spacing: 0;
}

.profile-title {
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.25em;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-3) 0;
}

.profile-rule {
  width: 32px;
  height: 1px;
  background: var(--color-brand);
  margin-bottom: var(--space-4);
  transition: width 400ms var(--ease-micro);
}

.profile-bio {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: 56ch;
}

.profile-bio p {
  font-family: var(--font-sans);
  /* Bumped from --fs-base (16px) to 18px so the bios read with more
     editorial weight — a step up toward the founder's body size
     (20px) without claiming parity with it. Line-height tightens
     slightly to keep the proportions balanced at the larger size. */
  font-size: 1.125rem;
  line-height: 1.7;
  color: var(--color-text);
  margin: 0;
  max-width: 56ch;
}

/* ----- Divider between profiles ----- */
.desk-divider {
  border: 0;
  width: 100%;
  height: 1px;
  background: var(--color-divider);
  opacity: 0.6;
  margin: var(--space-12) 0;
}

/* ----- Hover (desktop pointer only) ----- */
@media (hover: hover) {
  .desk-profile:hover .profile-rule { width: 56px; }
  .desk-profile:hover .profile-initials {
    /* Subtle tonal warmth — a hint of red, not a full color change.
       0.85 opacity on the brand color keeps it editorial. */
    color: var(--color-brand);
    opacity: 0.85;
  }
}

/* ----- Mobile stacking ----- */
@media (max-width: 768px) {
  .desk-profile {
    grid-template-columns: 1fr;
    gap: var(--space-2);
  }
  .profile-initials {
    font-size: clamp(4rem, 14vw, 6rem);
    margin-bottom: var(--space-3);
  }
  .profile-name {
    font-size: clamp(1.75rem, 6vw, 2.25rem);
  }
  .profile-bio,
  .profile-bio p {
    max-width: none;
  }
  .desk-heading {
    font-size: clamp(2.5rem, 8vw, 3.5rem);
  }
}

/* ----- Pre-reveal hide (defense-in-depth) ----- */
/* Section ships with .is-pre-reveal. Every animated element starts
   hidden so NOTHING paints before js/desk.js drops the class and the
   timeline drives them in. */
.the-desk.is-pre-reveal .profile-initials,
.the-desk.is-pre-reveal .profile-content,
.the-desk.is-pre-reveal .desk-divider {
  opacity: 0;
}
.the-desk.is-pre-reveal .desk-heading {
  opacity: 0;
  transform: translateY(24px);
}
.the-desk.is-pre-reveal .profile-initials {
  transform: translateY(20px) scale(0.96);
}
.the-desk.is-pre-reveal .desk-rule {
  transform: scaleX(0);
}

/* Reduced motion: bypass the pre-reveal hide entirely. */
@media (prefers-reduced-motion: reduce) {
  .the-desk.is-pre-reveal .desk-heading,
  .the-desk.is-pre-reveal .desk-rule,
  .the-desk.is-pre-reveal .profile-initials,
  .the-desk.is-pre-reveal .profile-content,
  .the-desk.is-pre-reveal .desk-divider {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ============================================================
   ALGAMAR EDITORIAL — Met Gala-grade content components.
   Refined hero, italic display moments, glass cards, an
   ultra-restrained enquiry form. Couture restraint over flash.
   ============================================================ */


/* ----------------------------------------------------------------
   Hero tagline — italic Cormorant. The dateline sits in the
   top-left like a magazine masthead; the tagline drops in at the
   bottom-left of the viewport.
   ---------------------------------------------------------------- */
h1.hero__tagline,
.hero__tagline {
  font-family: "Cormorant Garamond", "GT Sectra", Georgia, serif;
  font-style: normal;
  font-weight: 400;
  font-size: clamp(3rem, 7.6vw, 6.8rem);
  line-height: 1.0;
  letter-spacing: -0.02em;
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.55),
    0 8px 40px rgba(0, 0, 0, 0.45);
}

.hero__dateline {
  position: absolute;
  top: calc(var(--header-h) + var(--space-3));
  left: var(--gutter-x);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.78);
  z-index: 3;
  opacity: 0;
  animation: heroFadeIn 1.2s var(--ease-out) 600ms forwards;
}
.hero__dateline-rule {
  display: inline-block;
  width: 28px;
  height: 1px;
  background: rgba(255, 255, 255, 0.6);
}
@keyframes heroFadeIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (max-width: 768px) {
  .hero__dateline { font-size: 10px; letter-spacing: 0.28em; gap: var(--space-1); }
  .hero__dateline-rule { width: 18px; }
}

/* ----------------------------------------------------------------
   Editorial metrics — four figures in display-serif italic,
   labels in mono small caps. A hairline separates each row.
   ---------------------------------------------------------------- */
.metrics {
  padding-block: clamp(5rem, min(12.0vw, 18.0vh), 9rem);
}

.metrics__header {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2);
  margin-bottom: clamp(2.5rem, 6vw, 5rem);
}

.metrics__eyebrow {
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
}

.metrics__rule {
  width: 100%;
  max-width: 100%;
  height: 1px;
  background: linear-gradient(90deg, rgba(255,255,255,0.30), rgba(255,255,255,0.04));
  border: none;
  margin: 0;
}

.metrics__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
}

.metric {
  position: relative;
  padding: var(--space-5) var(--space-4) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.metric + .metric {
  border-left: 1px solid rgba(255, 255, 255, 0.12);
}

.metric__num {
  font-family: var(--font-numeric);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(3rem, 6.5vw, 5.5rem);
  line-height: 0.92;
  letter-spacing: -0.025em;
  color: var(--color-text);
  font-feature-settings: "tnum", "lnum";
  font-variant-numeric: tabular-nums lining-nums;
}
.metric__suffix {
  display: inline-block;
  font-size: 0.42em;
  vertical-align: 0.55em;
  margin-left: 0.06em;
  color: rgba(255, 255, 255, 0.7);
  font-style: normal;
  letter-spacing: 0;
}

.metric__rule {
  display: block;
  width: 24px;
  height: 1px;
  background: rgba(255, 255, 255, 0.55);
  margin-top: var(--space-2);
}

.metric__label {
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.86);
}

@media (max-width: 900px) {
  .metrics__grid { grid-template-columns: repeat(2, 1fr); }
  .metric:nth-child(2n+1) { border-left: none; }
  .metric:nth-child(n+3)  { border-top: 1px solid rgba(255, 255, 255, 0.12); }
}
@media (max-width: 520px) {
  .metrics__grid { grid-template-columns: 1fr; }
  .metric { border-left: none !important; }
  .metric + .metric { border-top: 1px solid rgba(255, 255, 255, 0.12); }
}

/* ----------------------------------------------------------------
   "The House" — short editorial about-us. Italic eyebrow on the
   left column, lead paragraph with drop cap on the right.
   ---------------------------------------------------------------- */
.house {
  padding-block: clamp(5rem, min(12.0vw, 18.0vh), 9rem);
}
.house__grid {
  display: grid;
  grid-template-columns: 4fr 8fr;
  gap: clamp(2rem, 6vw, 6rem);
  align-items: start;
}
.house__label .eyebrow--mono { display: inline-block; }
.house__label-rule {
  display: block;
  width: 64px;
  height: 1px;
  background: rgba(255, 255, 255, 0.4);
  margin-top: var(--space-3);
}
.house__heading {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin-top: var(--space-3);
  color: var(--color-text);
  max-width: 18ch;
}
.house__body {
  font-family: var(--font-sans);
  font-size: clamp(1.0625rem, 1.4vw, 1.25rem);
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.96);
  max-width: 60ch;
  /* Matte glass surface so reading copy lifts off the moving ocean. */
  position: relative;
  background: var(--glass-matte-bg);
  backdrop-filter: var(--glass-matte-blur);
  -webkit-backdrop-filter: var(--glass-matte-blur);
  border: var(--glass-border);
  border-radius: 2px;
  isolation: isolate;
  padding: clamp(2rem, 4vw, 3rem) clamp(2rem, 4vw, 3.25rem);
  box-shadow:
    0 24px 60px -28px rgba(0, 0, 0, 0.55);
}
.house__body p + p { margin-top: var(--space-3); }
@media (max-width: 768px) {
  .house__grid { grid-template-columns: 1fr; gap: var(--space-4); }
}

/* ----------------------------------------------------------------
   Contact cards — three glass panels. Each is a hand-set card
   with eyebrow / italic heading / micro-paragraph / mailto link.
   ---------------------------------------------------------------- */
.contacts {
  padding-block: clamp(5rem, min(12.0vw, 18.0vh), 9rem);
}
.contacts__header {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: clamp(2rem, 5vw, 4rem);
}
.contacts__heading {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(2rem, 4vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.015em;
  max-width: 18ch;
}

.contacts__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}

.contact-card {
  padding: clamp(1.5rem, 2.5vw, 2.25rem);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-height: 240px;
  transition: transform var(--dur-short) var(--ease-out), box-shadow var(--dur-short) var(--ease-out);
}
.contact-card:hover {
  transform: translateY(-2px);
  box-shadow:
    0 32px 80px -32px rgba(0, 0, 0, 0.65);
}
.contact-card__eyebrow {
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7);
}
.contact-card__heading {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(1.75rem, 2.4vw, 2.25rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--color-text);
}
.contact-card__rule {
  display: block;
  width: 32px;
  height: 1px;
  background: rgba(255, 255, 255, 0.4);
  margin-top: var(--space-1);
}
.contact-card__body {
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.78);
  margin-top: auto;
}
.contact-card__link {
  margin-top: var(--space-2);
  display: inline-flex;
  align-items: baseline;
  gap: 0.5em;
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-text);
  border-bottom: 1px solid rgba(255, 255, 255, 0.4);
  padding-bottom: 4px;
  align-self: flex-start;
  transition: border-color var(--dur-micro) var(--ease-micro), gap var(--dur-short) var(--ease-out);
}
.contact-card__link:hover {
  border-bottom-color: var(--color-text);
  gap: 0.9em;
}
.contact-card__arrow { font-style: normal; }

@media (max-width: 900px) {
  .contacts__grid { grid-template-columns: 1fr; }
}

/* ----------------------------------------------------------------
   Products grid — editorial product tiles. Each tile is a glass
   card with a fish silhouette accent, italic name, small-cap kind.
   ---------------------------------------------------------------- */
.products {
  padding-block: clamp(4rem, min(9.0vw, 13.5vh), 7rem);
}
.products__intro {
  max-width: 64ch;
  margin-bottom: clamp(2.5rem, 6vw, 5rem);
  font-family: var(--font-sans);
  font-size: clamp(1.0625rem, 1.4vw, 1.25rem);
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.96);
  /* Matte panel — the intro paragraph reads off frosted glass. */
  position: relative;
  background: var(--glass-matte-bg);
  backdrop-filter: var(--glass-matte-blur);
  -webkit-backdrop-filter: var(--glass-matte-blur);
  border: var(--glass-border);
  border-radius: 2px;
  isolation: isolate;
  padding: clamp(2rem, 4vw, 3rem) clamp(2rem, 4vw, 3.25rem);
  box-shadow:
    0 24px 60px -28px rgba(0, 0, 0, 0.55);
}
.products__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}
.product-tile {
  position: relative;
  padding: clamp(1.5rem, 2.5vw, 2rem);
  min-height: 260px;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  transition: transform var(--dur-short) var(--ease-out), box-shadow var(--dur-short) var(--ease-out);
}
.product-tile:hover {
  transform: translateY(-2px);
  box-shadow:
    0 32px 80px -32px rgba(0, 0, 0, 0.65);
}
.product-tile__kind {
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7);
}
.product-tile__name {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(1.6rem, 2.4vw, 2.1rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--color-text);
}
.product-tile__rule {
  display: block;
  width: 28px;
  height: 1px;
  background: rgba(255, 255, 255, 0.4);
  margin-top: var(--space-1);
}
.product-tile__meta {
  margin-top: auto;
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.74);
}
.product-tile__meta-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  padding-top: 6px;
  border-top: 1px solid rgba(255, 255, 255, 0.10);
}
.product-tile__meta-row + .product-tile__meta-row { margin-top: 4px; }
.product-tile__meta-key {
  font-family: var(--font-sans);
  font-size: 10px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

@media (max-width: 900px) { .products__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .products__grid { grid-template-columns: 1fr; } }

/* ----------------------------------------------------------------
   About page editorial — long-form. Lead paragraph with drop cap,
   pull quote, supporting paragraphs.
   ---------------------------------------------------------------- */
.editorial {
  padding-block: clamp(4rem, min(9.0vw, 13.5vh), 7rem);
}
.editorial__grid {
  display: grid;
  grid-template-columns: 4fr 8fr;
  gap: clamp(2rem, 6vw, 6rem);
  align-items: start;
}
.editorial__label {
  position: sticky;
  top: calc(var(--header-h) + var(--space-3));
}
.editorial__eyebrow { display: inline-block; }
.editorial__heading {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(2rem, 3.4vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin-top: var(--space-3);
  color: var(--color-text);
  max-width: 16ch;
}
.editorial__body {
  font-family: var(--font-sans);
  font-size: clamp(1.0625rem, 1.4vw, 1.25rem);
  line-height: 1.75;
  color: rgba(255, 255, 255, 0.96);
  max-width: 64ch;
  /* Matte panel for long-form editorial copy. */
  position: relative;
  background: var(--glass-matte-bg);
  backdrop-filter: var(--glass-matte-blur);
  -webkit-backdrop-filter: var(--glass-matte-blur);
  border: var(--glass-border);
  border-radius: 2px;
  isolation: isolate;
  padding: clamp(2rem, 4vw, 3rem) clamp(2rem, 4vw, 3.25rem);
  box-shadow:
    0 24px 60px -28px rgba(0, 0, 0, 0.55);
}
.editorial__body p + p { margin-top: var(--space-4); }

.pull-quote {
  margin: clamp(3rem, 6vw, 5rem) 0;
  padding: clamp(2.5rem, 5vw, 4rem) clamp(2rem, 4vw, 3.5rem);
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(1.5rem, 2.6vw, 2.25rem);
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--color-text);
  text-align: center;
  position: relative;
  /* Matte panel — the quote is the editorial's quiet centrepiece. */
  background: var(--glass-matte-bg);
  backdrop-filter: var(--glass-matte-blur);
  -webkit-backdrop-filter: var(--glass-matte-blur);
  border: var(--glass-border);
  border-radius: 2px;
  isolation: isolate;
  box-shadow:
    0 24px 60px -28px rgba(0, 0, 0, 0.55);
}
.pull-quote::before,
.pull-quote::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 48px;
  height: 1px;
  background: rgba(255, 255, 255, 0.5);
  transform: translateX(-50%);
}
.pull-quote::before { top: 28px; }
.pull-quote::after  { bottom: 28px; }

@media (max-width: 768px) {
  .editorial__grid { grid-template-columns: 1fr; gap: var(--space-4); }
  .editorial__label { position: static; }
}

/* ----------------------------------------------------------------
   Contact page — address block + Write an Enquiry glass form.
   ---------------------------------------------------------------- */
.contact-page {
  padding-block: clamp(4rem, min(9.0vw, 13.5vh), 7rem);
}
.contact-page__grid {
  display: grid;
  /* minmax(0, …) not plain fr. A bare `1fr` is `minmax(auto, 1fr)`, so
     the track can never shrink below its content's min-content width —
     and the spec table inside carries a 34rem min-width. On a 375px
     screen that pushed this track to 646px and the section's
     overflow-x: hidden silently CLIPPED the right-hand third of every
     chapter rather than wrapping it. */
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(2rem, 6vw, 6rem);
  align-items: start;
}
.contact-page__address {
  font-family: var(--font-sans);
  font-size: var(--fs-md);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.96);
  /* Matte panel — address + contact rows on frosted glass. */
  position: relative;
  background: var(--glass-matte-bg);
  backdrop-filter: var(--glass-matte-blur);
  -webkit-backdrop-filter: var(--glass-matte-blur);
  border: var(--glass-border);
  border-radius: 2px;
  isolation: isolate;
  padding: clamp(2rem, 4vw, 2.75rem) clamp(2rem, 4vw, 3rem);
  box-shadow:
    0 24px 60px -28px rgba(0, 0, 0, 0.55);
}
.contact-page__address-lines {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(1.5rem, 2.4vw, 2rem);
  line-height: 1.25;
  margin-top: var(--space-2);
}
.contact-page__contacts {
  margin-top: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.contact-page__row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-bottom: var(--space-2);
  border-bottom: 1px solid rgba(255, 255, 255, 0.10);
}
.contact-page__row-key {
  font-family: var(--font-sans);
  font-size: 10px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}
.contact-page__row a {
  font-family: var(--font-sans);
  font-size: var(--fs-md);
  letter-spacing: 0;
  color: var(--color-text);
  border-bottom: 1px solid transparent;
  padding-bottom: 1px;
  transition: border-color var(--dur-micro) var(--ease-micro);
  align-self: flex-start;
}
.contact-page__row a:hover { border-bottom-color: rgba(255, 255, 255, 0.6); }

/* ============================================================
   PHASE 3D — CONTACT PAGE (brief §5.4)
   Office address block + Card-Glass enquiry form. Form fields are
   line-only inputs (no boxes), labels in eyebrow caps above each.
   ============================================================ */

.office {
  padding-block: var(--section-pad-y);
  position: relative;
  z-index: var(--z-content);
}
.office__grid {
  display: grid;
  grid-template-columns: 4fr 7fr;
  gap: clamp(2rem, 6vw, 6rem);
  align-items: start;
}
.office__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.office__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: 1.04;
  letter-spacing: var(--tr-display);
  color: var(--pearl);
}
.office__heading em { font-style: normal; font-weight: 400; }
.office__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.office__address {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: var(--type-display-m);
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--pearl);
  margin: 0;
  max-width: none;
}
.office__meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: 0;
}
.office__meta-row {
  display: grid;
  grid-template-columns: 100px 1fr;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-top: 1px solid color-mix(in srgb, var(--pearl) 10%, transparent);
  align-items: baseline;
}
.office__meta-row dt { color: var(--pearl-muted); }
.office__meta-row dd {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--type-body);
  color: var(--pearl);
}
.office__meta-row dd a {
  border-bottom: 1px solid color-mix(in srgb, var(--pearl) 30%, transparent);
  padding-bottom: 1px;
}
.office__meta-row dd a:hover {
  border-bottom-color: var(--pearl);
}

@media (max-width: 900px) {
  .office__grid { grid-template-columns: 1fr; gap: var(--space-4); }
  .office__meta-row { grid-template-columns: 1fr; gap: var(--space-1); padding: var(--space-2) 0; }
}

.enquiry-section {
  padding-block: var(--section-pad-y);
  position: relative;
  z-index: var(--z-content);
}

/* Enquiry form — line-only inputs (no boxes), labels in eyebrow
   caps above each field. Submit is the .btn--ghost component
   (fills from left on hover). Brief §5.4 spec. */
.enquiry {
  padding: clamp(2rem, 4vw, 3.5rem) clamp(2rem, 4vw, 3.25rem);
  border-radius: 16px;
  max-width: 880px;
  margin-inline: auto;
}
.enquiry__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
}
.enquiry__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-m);
  line-height: 1.1;
  letter-spacing: var(--tr-display);
  margin: 0;
  color: var(--pearl);
}
.enquiry__heading em { font-style: normal; font-weight: 400; }
.enquiry__intro {
  font-family: var(--font-sans);
  font-size: var(--type-body);
  line-height: 1.6;
  color: var(--pearl-muted);
  max-width: 50ch;
  margin-top: 0;
}
.enquiry__rule {
  display: block;
  width: 100%;
  height: 1px;
  background: rgba(255, 255, 255, 0.18);
  border: none;
  margin: var(--space-4) 0;
}
.enquiry__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4) var(--space-4);
}
.enquiry__field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.enquiry__field--full { grid-column: 1 / -1; }
.enquiry__label {
  font-family: var(--font-sans);
  font-size: 10px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.65);
}
.enquiry__input,
.enquiry__select,
.enquiry__textarea {
  font-family: var(--font-sans);
  font-size: var(--fs-md);
  color: var(--color-text);
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.30);
  padding: 8px 0;
  width: 100%;
  transition: border-color var(--dur-micro) var(--ease-micro);
  appearance: none;
  -webkit-appearance: none;
  border-radius: 0;
}
.enquiry__textarea {
  min-height: 120px;
  resize: vertical;
  line-height: 1.55;
}
.enquiry__input:focus,
.enquiry__select:focus,
.enquiry__textarea:focus {
  border-bottom-color: var(--color-text);
}
.enquiry__select {
  /* Custom caret since native select arrows look bad on glass. */
  background-image: linear-gradient(45deg, transparent 50%, rgba(255,255,255,0.6) 50%),
                    linear-gradient(135deg, rgba(255,255,255,0.6) 50%, transparent 50%);
  background-position: calc(100% - 14px) 50%, calc(100% - 9px) 50%;
  background-size: 5px 5px;
  background-repeat: no-repeat;
  padding-right: 28px;
}
.enquiry__select option {
  background: #0e1620;
  color: var(--color-text);
}
.enquiry__actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-5);
  flex-wrap: wrap;
}
.enquiry__submit {
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--color-text);
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.45);
  padding: 16px 32px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  transition: background-color var(--dur-short) var(--ease-out), border-color var(--dur-short) var(--ease-out), gap var(--dur-short) var(--ease-out);
  border-radius: 999px;
}
.enquiry__submit:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--color-text);
  gap: 1em;
}
.enquiry__submit-arrow { font-size: 14px; }
.enquiry__hint {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: rgba(255, 255, 255, 0.55);
  font-style: normal;
}

@media (max-width: 900px) {
  .contact-page__grid { grid-template-columns: 1fr; gap: var(--space-5); }
  .enquiry__grid { grid-template-columns: 1fr; }
}

/* ----------------------------------------------------------------
   Page-hero refinement — page-level title in italic display,
   centered eyebrow above, hairline rule below.
   ---------------------------------------------------------------- */
.page-hero__title {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(3rem, 7.6vw, 6.4rem);
  line-height: 1.0;
  letter-spacing: -0.02em;
}
.page-hero__eyebrow {
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.78);
  display: block;
  margin-bottom: var(--space-3);
}

/* ----------------------------------------------------------------
   Footer refinement — italic tagline, hairline ornaments,
   typographic balance with the hero. The site signs off with
   couture restraint.
   ---------------------------------------------------------------- */
.site-footer__tagline {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(1.5rem, 2.2vw, 2rem);
  line-height: 1.2;
  letter-spacing: -0.005em;
  max-width: 22ch;
}

/* ============================================================
   BUTTONS — three styles (brief §6.1)
   ============================================================ */

/* Shared base — flatten anchor and button into one ergonomics. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  font-family: var(--font-sans);
  font-size: var(--type-caption);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tr-eyebrow);
  line-height: 1;
  padding: 16px 32px;
  border-radius: 2px;     /* sharp — brief §6.1 says no border-radius (or 2px max) */
  border: 1px solid transparent;
  background: transparent;
  color: inherit;
  cursor: pointer;
  text-decoration: none;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: transform var(--dur-short) var(--ease-out-expo),
              color var(--dur-short) var(--ease-in-out-cubic),
              border-color var(--dur-short) var(--ease-in-out-cubic),
              background-color var(--dur-short) var(--ease-in-out-cubic),
              box-shadow var(--dur-short) var(--ease-out-expo);
}

/* ============================================================
   PHASE 3 — HOME PAGE (brief §5.1)
   Header: logo left, nav centre, clock right (mobile collapses
   centre + right into a hamburger). Hero: bottom-left content
   stack over cross-fading ocean videos. Metrics: 4-column
   asymmetric. About excerpt: editorial split. Contacts: three
   Card-Glass tiles. Footer: 4-column slim Whisper glass.
   ============================================================ */

/* ----------------------------------------------------------------
   HEADER LAYOUT — overrides existing site-header styles
   ---------------------------------------------------------------- */
.site-header__inner {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: var(--space-3);
  height: 100%;
  padding-inline: var(--container-pad);
  max-width: var(--container-max);
  margin-inline: auto;
}

.site-header__logo {
  display: block;
  line-height: 0;
  justify-self: start;
}
.site-header__logo img {
  height: 44px;
  width: auto;
  display: block;
}

/* Centre nav — inline links, brief §6.4. Active-page indicator
   is a tiny pearl dot below the current item. */
.site-header__nav {
  justify-self: center;
}
.site-header__nav ul {
  display: flex;
  gap: clamp(1rem, 2.6vw, 2.5rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav-link {
  position: relative;
  font-family: var(--font-sans);
  font-size: var(--type-caption);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--pearl-muted);
  text-transform: none;
  padding: 8px 4px;
  transition: color var(--dur-micro) var(--ease-out-expo);
}
.nav-link:hover { color: var(--pearl); }
.nav-link[aria-current="page"] { color: var(--pearl); }
.nav-link[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--pearl);
  transform: translateX(-50%);
}

/* Right-side meta block: Cochin · 09:47 IST */
.site-header__meta {
  justify-self: end;
  display: inline-flex;
  align-items: baseline;
  gap: 0.6em;
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--pearl-muted);
  white-space: nowrap;
}
.site-header__meta-place { letter-spacing: 0.22em; }
.site-header__meta-sep   { opacity: 0.6; }
.site-header__meta-time  { color: var(--pearl); font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.site-header__meta-colon { color: var(--pearl); }
.site-header__meta-zone  { color: var(--pearl-quiet); letter-spacing: 0.22em; }

/* ONE NAVIGATION, EVERY WIDTH.
   The inline centre nav is retired at all sizes and the hamburger is
   now the only way through the site. Two reasons this is the better
   design rather than a mobile compromise: the chrome stops changing
   shape between breakpoints (the same control, in the same place, at
   every size — Apple's familiarity/consistency principle), and the
   header reduces to mark | time | menu, which lets the ocean carry the
   top of every page instead of a row of links competing with it.
   The overlay is consequently no longer a mobile fallback — it is the
   primary navigation, and is styled as a first-class surface below. */
.site-header__nav { display: none; }
.menu-toggle { justify-self: end; display: inline-flex; }
.site-header__inner { grid-template-columns: auto 1fr auto auto; }

/* NO-JS FALLBACK. The overlay ships with the `hidden` attribute and is
   opened by JS, so hiding the inline nav unconditionally would leave a
   scripting-disabled visitor with no navigation whatsoever. The inline
   script adds `.js` to <html>, so when it is absent we restore the
   inline links and drop the toggle that cannot do anything. */
html:not(.js) .site-header__nav { display: block; }
html:not(.js) .site-header__nav ul { flex-wrap: wrap; justify-content: center; }
html:not(.js) .menu-toggle { display: none; }

@media (max-width: 900px) {
  /* The clock is the first thing to go when width gets tight. */
  .site-header__inner { grid-template-columns: auto 1fr auto; }
  .cochin-now { display: none; }
}
@media (max-width: 640px) {
  .site-header__logo img { height: 30px; }
}

/* On homepage, header items start invisible (revealed by hero.js). */
.page-home .site-header .site-header__logo,
.page-home .site-header .cochin-now,
.page-home .site-header .menu-toggle {
  opacity: 0;
}

/* ----------------------------------------------------------------
   HERO (brief §5.1) — full viewport, bottom-left content stack
   ---------------------------------------------------------------- */

/* Replace the prior hero layout with bottom-left content. */
.page-home .hero {
  position: relative;
  height: 100vh;
  height: 100dvh;
  min-height: 640px;
  padding: var(--header-h) var(--container-pad) clamp(4rem, 9vh, 7rem);
  display: flex;
  align-items: flex-end;
  background: transparent !important;
  z-index: var(--z-content);
  overflow: hidden;
}

.page-home .hero__inner {
  position: relative;
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.hero__eyebrow {
  /* Promoted off --pearl-muted: this is the smallest type on the page
     and sits highest in the frame, where the water is brightest. */
  color: var(--pearl);
  opacity: 0.9;
  font-weight: 550;
  /* Extra air beneath the eyebrow. The hero stack is bottom-anchored,
     so this lifts the eyebrow clear of the headline rather than pushing
     the headline down. The base .eyebrow leading of 1 is right for a
     single line but cramps the pair when it wraps on narrow screens. */
  line-height: 1.45;
  margin-bottom: var(--space-2);
}
@media (max-width: 640px) {
  .hero__eyebrow { margin-bottom: var(--space-3); }
}

.hero__headline {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-xl);
  line-height: var(--lh-display-xl);
  letter-spacing: var(--tr-display-xl);
  color: var(--pearl);
  max-width: 18ch;
  text-wrap: balance;
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.45),
    0 8px 32px rgba(0, 0, 0, 0.35);
}
.hero__headline em {
  font-style: normal;
  font-weight: 400;
}
.hero__headline-line {
  display: block;
  /* Lines themselves no longer reveal — words inside do (brief §7.1). */
}
/* Per-word wrappers (created by hero.js).
   NOTE: these used to carry `overflow: hidden` + `vertical-align: bottom`
   to mask a per-word reveal, where each word translated up from under
   its own clip box. That reveal is gone — the headline now arrives as a
   single plane travelling through z — so the mask had no job left, and
   with the display line-height at 0.98 it was silently clipping every
   descender that fell outside the box (the "g" in "generations", the
   italic "f" in "of excellence"). Overflow stays visible; the ancestor
   .hero still clips the video, which is the only clipping we want. */
.word {
  display: inline-block;
  vertical-align: baseline;
}
.word__inner {
  display: inline-block;
  will-change: transform, opacity;
}

.hero__sub {
  font-family: var(--font-sans);
  font-size: var(--type-body-l);
  line-height: 1.6;
  color: var(--pearl-muted);
  /* Spans with the headline, not a narrow ribbon under it. */
  max-width: 58ch;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}

/* Bottom-centre minimalist scroll indicator. */
.hero__cue {
  position: absolute;
  bottom: var(--space-4);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  opacity: 0;
}
.hero__cue-line {
  display: block;
  width: 1px;
  height: 40px;
  background: linear-gradient(180deg, transparent 0%, var(--pearl) 100%);
  animation: heroCue 1.8s var(--ease-in-out-cubic) infinite;
}
.hero__cue-text {
  font-family: var(--font-sans);
  font-size: 10px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--pearl-muted);
}
@keyframes heroCue {
  0%, 100% { transform: translateY(0); opacity: 1; }
  50%      { transform: translateY(6px); opacity: 0.4; }
}
@media (prefers-reduced-motion: reduce) {
  .hero__cue-line { animation: none; }
}

/* Hero video crossfade (brief §5.1): .is-active fades the active clip in
   and the outgoing one out over 1500ms.

   Scoped to the two hosts that rotate on a timer, NOT to .hero-video
   generally. about/contact/products hand off on `ended` and swap
   instantly on purpose (components.css: "gapless, no fade, no black
   frame"), so a blanket .hero-bg .hero-video rule would quietly hand
   those three a 1.5s fade nobody asked for.

   Matched on the slot's container rather than on per-slot --a/--b/--c
   classes: the homepage rotation grew from three clips to six, and a
   rule naming only the first three leaves d/e/f cutting hard. */
.page-home .hero-bg .hero-video,
.hero-bg[data-rotate-interval] .hero-video {
  transition: opacity var(--dur-fade) var(--ease-in-out-cubic);
}


@media (max-width: 768px) {
  .page-home .hero { padding: var(--header-h-mobile) var(--container-pad) var(--space-12); }
  .hero__headline { font-size: clamp(2.75rem, 14vw, 4.5rem); }
  .hero__sub { font-size: var(--type-body); }
}

/* ----------------------------------------------------------------
   METRICS (brief §5.1 — Section 2)
   Four metrics in a horizontal row. 64px gap. Asymmetric — first
   slightly left of grid, last slightly right. Count-up triggered
   by stats.js on intersection.
   ---------------------------------------------------------------- */
.metrics {
  padding-block: var(--section-pad-y);
  position: relative;
  z-index: var(--z-content);
}
.metrics .container { max-width: var(--container-max); }

.metrics__header {
  margin-bottom: clamp(3rem, 7vw, 5rem);
}

.metrics__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-8);
  align-items: end;
}

.metric {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: 0;
  border: none;
}
.metric + .metric { border: none; }
/* Asymmetric vertical break — first lifts a bit, last drops a bit. */
.metric--01 { transform: translate(-12px, -16px); }
.metric--02 { transform: translateY(8px); }
.metric--03 { transform: translateY(-4px); }
.metric--04 { transform: translate(12px, 20px); }

.metric__num {
  font-family: var(--font-numeric);
  font-style: normal;
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: 0.95;
  letter-spacing: -0.025em;
  color: var(--pearl);
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum", "lnum";
  display: inline-block;
}
.metric__suffix {
  display: inline-block;
  font-size: 0.5em;
  vertical-align: 0.45em;
  margin-left: 0.06em;
  color: var(--pearl-muted);
  font-style: normal;
}
.metric__rule {
  display: block;
  width: 32px;
  height: 1px;
  background: color-mix(in srgb, var(--pearl) 35%, transparent);
  margin-top: var(--space-1);
}
.metric__label {
  font-size: var(--type-eyebrow);
  letter-spacing: 0.18em;
  color: var(--pearl-muted);
  text-transform: uppercase;
}

@media (max-width: 900px) {
  .metrics__grid { grid-template-columns: 1fr 1fr; gap: var(--space-6); }
  .metric--01, .metric--02, .metric--03, .metric--04 { transform: none; }
}
@media (max-width: 520px) {
  .metrics__grid { grid-template-columns: 1fr; gap: var(--space-5); }
}

/* ----------------------------------------------------------------
   ABOUT EXCERPT (brief §5.1 — Section 3)
   ---------------------------------------------------------------- */
.about-excerpt {
  padding-block: var(--section-pad-y);
  position: relative;
  z-index: var(--z-content);
}
.about-excerpt__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 6vw, 6rem);
  align-items: start;
}
.about-excerpt__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: 1.04;
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  text-wrap: balance;
}
.about-excerpt__heading em {
  font-style: normal;
  font-weight: 400;
}
.about-excerpt__body {
  font-size: var(--type-body-l);
  line-height: 1.7;
  color: var(--pearl-muted);
  max-width: 50ch;
}
.about-excerpt__cta {
  margin-top: var(--space-3);
  display: inline-flex;
}
@media (max-width: 900px) {
  .about-excerpt__grid { grid-template-columns: 1fr; gap: var(--space-4); }
}

/* ----------------------------------------------------------------
   CONTACTS (brief §5.1 — Section 4)
   Three Card-Glass tiles. translateY(-4px) lift on hover.
   16px border-radius per brief §6.2.
   ---------------------------------------------------------------- */
.contacts {
  padding-block: var(--section-pad-y);
  position: relative;
  z-index: var(--z-content);
}
.contacts__header {
  margin-bottom: clamp(2.5rem, 6vw, 4rem);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.contacts__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-m);
  line-height: 1.1;
  letter-spacing: var(--tr-display);
  color: var(--pearl);
}
.contacts__heading em { font-style: normal; font-weight: 400; }
.contacts__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
}
.contact-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  min-height: 280px;
  border-radius: 16px;  /* brief §6.2 — subtle, not chunky */
  text-decoration: none;
  color: inherit;
  transition:
    transform var(--dur-short) var(--ease-out-expo),
    box-shadow var(--dur-short) var(--ease-out-expo);
  isolation: isolate;
}
.contact-card:hover {
  transform: translateY(-4px);
  box-shadow:
    0 32px 80px -24px rgba(0, 0, 0, 0.55),
    0 0 0 1px color-mix(in srgb, var(--pearl) 14%, transparent);
}
.contact-card:hover::before {
  /* Top specular line brightens on hover (brief §5.1). */
  background: linear-gradient(90deg,
    transparent 0%,
    color-mix(in srgb, var(--pearl) 50%, transparent) 50%,
    transparent 100%);
}
.contact-card__eyebrow { color: var(--pearl-muted); }
.contact-card__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-m);
  line-height: 1.1;
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  font-style: normal;
}
.contact-card__body {
  font-family: var(--font-sans);
  font-size: var(--type-body);
  line-height: 1.55;
  color: var(--pearl-muted);
  margin: 0;
  max-width: 100%;
}
.contact-card__cta {
  margin-top: auto;
  display: inline-flex;
  align-items: baseline;
  gap: 0.5em;
  font-family: var(--font-sans);
  font-size: var(--type-caption);
  letter-spacing: 0.04em;
  color: var(--pearl);
  padding-top: var(--space-2);
  border-top: 1px solid color-mix(in srgb, var(--pearl) 12%, transparent);
}
.contact-card__arrow {
  transition: transform var(--dur-short) var(--ease-out-expo);
}
.contact-card:hover .contact-card__arrow { transform: translateX(4px); }

@media (max-width: 900px) {
  .contacts__grid { grid-template-columns: 1fr; gap: var(--space-3); }
  .contact-card { min-height: 220px; }
}

/* ----------------------------------------------------------------
   FOOTER REDESIGN — slim Whisper glass, 4 columns (mark + Navigate
   + Connect + Compliance), brief §5.1 footer spec.
   ---------------------------------------------------------------- */
.site-footer--slim {
  padding-block: var(--space-8) var(--space-4);
}
.site-footer--slim .site-footer__grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  gap: var(--space-4);
  padding: 0 0 var(--space-6) 0;
}
.site-footer__mark { height: 34px; width: auto; }
.site-footer__mark-link { display: inline-block; line-height: 0; }

.site-footer__col {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.site-footer__col-head {
  color: var(--pearl-muted);
  margin-bottom: var(--space-1);
}
.site-footer__col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.site-footer__col li,
.site-footer__col a {
  font-family: var(--font-sans);
  font-size: var(--type-caption);
  color: var(--pearl-muted);
  line-height: 1.55;
}
.site-footer__col a {
  border-bottom: 1px solid transparent;
  padding-bottom: 1px;
  transition: color var(--dur-micro) var(--ease-out-expo), border-color var(--dur-micro) var(--ease-out-expo);
}
.site-footer__col a:hover {
  color: var(--pearl);
  border-bottom-color: color-mix(in srgb, var(--pearl) 30%, transparent);
}

.site-footer__bottom {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding-top: var(--space-3);
}
.site-footer__legal,
.site-footer__signoff {
  font-family: var(--font-sans);
  font-size: var(--type-caption);
  color: var(--pearl-quiet);
}
.site-footer__signoff { font-style: normal; }

@media (max-width: 900px) {
  .site-footer--slim .site-footer__grid {
    grid-template-columns: 1fr 1fr;
    row-gap: var(--space-5);
  }
  .site-footer__mark-link { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
  .site-footer--slim .site-footer__grid { grid-template-columns: 1fr; row-gap: var(--space-4); }
}

/* ============================================================
   PHASE 3B — ABOUT PAGE (brief §5.2)
   Half-viewport hero (no video), four long-form story sections
   with sticky eyebrow + heading column and reading body column,
   centred closing with portfolio link.
   ============================================================ */

/* Page-hero half-viewport variant (About / Contact / Products). */
.page-hero.page-hero--half {
  height: 60vh;
  min-height: 480px;
}

.page-hero {
  position: relative;
  height: 100vh;
  /* svh, not dvh: this hero must NOT resize when the mobile browser
     bars retract mid-scroll — a hero that grows under the reader is
     the jump this pair exists to prevent. svh is the small (bars
     shown) height, so the hero is laid out once and stays put. */
  height: 100svh;
  min-height: 560px;
  display: flex;
  align-items: flex-end;
  padding: var(--header-h) var(--container-pad) clamp(3rem, 8vh, 6rem);
  /* COMPLETELY clear — crisp untinted water, same as the home hero.
     The fade into the glass happens at this element's bottom edge
     via main::before/::after (the shared canvas pane). Title and sub
     carry their own soft shadows for legibility over bright frames. */
  background: transparent;
  z-index: var(--z-content);
}
/* LEGIBILITY SCRIM.
   The hero deliberately shows clear, untinted water — but pearl text on
   a sunlit frame measured 1.41:1 (title) and 1.12:1 (sub), i.e. close to
   invisible at the video's brightest moments. Tinting the whole hero
   would fix contrast and destroy the clarity that is the point of it.
   So the scrim is bound to the TEXT instead: a soft vertical gradient
   that rises out of the section boundary below and fades to nothing
   well before the top of the hero. It reads as depth in the water, not
   as a panel, and it leaves the upper two-thirds of the frame pristine.
   Sized in ch/em off the text block so it always covers the copy, at
   any viewport, in any language. */
.page-hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.page-hero__title,
.page-hero__sub {
  /* Kept alongside the scrim, but lighter now that the scrim carries
     the contrast: this only sharpens letterform edges against moving
     highlights. */
  text-shadow: 0 1px 2px rgba(10, 15, 26, 0.55), 0 2px 18px rgba(10, 15, 26, 0.40);
}
.page-hero__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-xl);
  line-height: var(--lh-display-xl);
  letter-spacing: var(--tr-display-xl);
  color: var(--pearl);
  max-width: 16ch;
  text-wrap: balance;
  font-optical-sizing: auto;
}
.page-hero__title em { font-style: normal; font-weight: 400; }
.page-hero__sub {
  font-family: var(--font-sans);
  font-size: var(--type-body-l);
  /* Promoted from --pearl-muted: the sub is the one line that has to
     survive the brightest frame, and muted grey never cleared 4.5:1. */
  color: var(--pearl);
  opacity: 0.92;
  max-width: 40ch;
  line-height: var(--lh-body-l);
  letter-spacing: var(--tr-body-l);
}

/* Story section — editorial split. Left column: sticky eyebrow +
   heading. Right column: body paragraphs. */
.story {
  padding-block: var(--section-pad-y);
  position: relative;
  z-index: var(--z-content);
}
.story__grid {
  display: grid;
  grid-template-columns: 4fr 7fr;
  gap: clamp(2rem, 6vw, 6rem);
  align-items: start;
}
.story__head {
  position: sticky;
  top: calc(var(--header-h) + var(--space-3));
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.story__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: 1.04;
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  text-wrap: balance;
  max-width: 14ch;
}
.story__heading em { font-style: normal; font-weight: 400; }
.story__body {
  font-family: var(--font-sans);
  font-size: var(--type-body-l);
  line-height: 1.75;
  color: var(--pearl-muted);
  max-width: 64ch;
}
.story__body p { color: var(--pearl-muted); max-width: 64ch; }
.story__body p + p { margin-top: var(--space-3); }
.story__body p:first-child { color: var(--pearl); }

/* Story divider — hairline pearl between consecutive .story sections. */
.story + .story {
  border-top: 1px solid color-mix(in srgb, var(--pearl) 8%, transparent);
}

@media (max-width: 900px) {
  .story__grid { grid-template-columns: 1fr; gap: var(--space-4); }
  .story__head { position: static; }
}

/* ============================================================
   PHASE 3C — PRODUCTS PAGE (brief §5.3)
   Four chapters, each its own quiet section. A massive Display
   numeral sits behind the content as a watermark — pearl-quiet at
   ~20% opacity, top-left of the section.
   ============================================================ */

.chapter {
  position: relative;
  padding-block: var(--section-pad-y);
  overflow: hidden;
  isolation: isolate;
  z-index: var(--z-content);
}

/* The 01/02/03/04 watermark numeral — large display serif behind
   content, opacity 0.18. Brief §5.3 spec. */
.chapter__numeral {
  position: absolute;
  top: clamp(2rem, 6vw, 5rem);
  left: clamp(-1rem, -2vw, -0.5rem);
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 500;
  font-size: clamp(8rem, 22vw, 18rem);
  line-height: 0.85;
  letter-spacing: -0.04em;
  color: color-mix(in srgb, var(--pearl-quiet) 28%, transparent);
  pointer-events: none;
  z-index: -1;
  user-select: none;
}

.chapter__inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 5fr 7fr;
  gap: clamp(2rem, 6vw, 6rem);
  align-items: start;
}
.chapter__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.chapter__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: 1.04;
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  max-width: 14ch;
  text-wrap: balance;
}
.chapter__heading em { font-style: normal; font-weight: 400; }

.chapter__lead {
  grid-column: 2;
  font-family: var(--font-sans);
  font-size: var(--type-body-l);
  line-height: 1.7;
  color: var(--pearl-muted);
  max-width: 60ch;
}

.chapter__detail {
  grid-column: 2;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4) var(--space-6);
  padding-top: var(--space-3);
  border-top: 1px solid color-mix(in srgb, var(--pearl) 10%, transparent);
}
.chapter__detail-block {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.chapter__detail-key {
  color: var(--pearl-muted);
}
.chapter__detail-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.chapter__detail-list li {
  font-family: var(--font-sans);
  font-size: var(--type-body);
  line-height: 1.5;
  color: var(--pearl);
}

.chapter-divider {
  position: relative;
  z-index: var(--z-content);
  height: 1px;
  background: color-mix(in srgb, var(--pearl-quiet) 30%, transparent);
  border: none;
  margin: 0 auto;
  max-width: calc(var(--container-max) - 2 * var(--container-pad));
  width: calc(100% - 2 * var(--container-pad));
}

@media (max-width: 900px) {
  .chapter__inner { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
  .chapter__lead,
  .chapter__detail { grid-column: 1; }
  .chapter__detail { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
  .chapter__numeral {
    font-size: clamp(7rem, 26vw, 11rem);
    top: 1rem;
    left: -0.5rem;
  }
}

/* Closing block — centred, generous space. */
.story-closing {
  padding-block: clamp(8rem, min(16.0vw, 24.0vh), 14rem);
  text-align: center;
  position: relative;
  z-index: var(--z-content);
}
.story-closing__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-m);
  line-height: 1.1;
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-bottom: var(--space-4);
  text-wrap: balance;
}
.story-closing__heading em { font-style: normal; font-weight: 400; }
.story-closing__cta {
  margin-inline: auto;
}

/* ============================================================
   PHASE 4 — VIEW TRANSITIONS (brief §7.4)
   Chrome 111+ / Edge 111+: navigating between same-origin pages
   cross-fades current page out (600ms ease-out-expo) and the new
   page in (800ms ease-out-expo + 12px translate-up). Safari/FF
   degrade to instant navigation — no flicker, no jank.
   ============================================================ */
@view-transition {
  navigation: auto;
}
::view-transition-old(root) {
  animation: ftOutDown 600ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
::view-transition-new(root) {
  animation: ftInUp 800ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes ftOutDown {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(12px); }
}
@keyframes ftInUp {
  from { opacity: 0; transform: translateY(-12px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation-duration: 1ms; }
}

/* The header logo is persistent across pages — give it a stable
   view-transition-name so it doesn't fade out and back in. */
.site-header__logo img {
  view-transition-name: site-logo;
}

/* ----------------------------------------------------------------
   PRIMARY button refined fill — keep existing rule and append:
   ---------------------------------------------------------------- */
/* PRIMARY — pearl fill, abyssal text, subtle scale on hover. */
.btn--primary {
  background: var(--pearl);
  color: var(--abyssal);
  border-color: var(--pearl);
}
.btn--primary:hover {
  transform: scale(1.02);
  box-shadow: 0 8px 28px -6px color-mix(in srgb, var(--pearl) 22%, transparent);
}

/* GHOST — transparent, 1px border, fill-from-left on hover. */
.btn--ghost {
  border-color: var(--pearl);
  color: var(--pearl);
  background: transparent;
}
.btn--ghost::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--pearl);
  transform-origin: left center;
  transform: scaleX(0);
  transition: transform var(--dur-short) var(--ease-in-out-cubic);
  z-index: -1;
}
.btn--ghost:hover {
  color: var(--abyssal);
}
.btn--ghost:hover::before {
  transform: scaleX(1);
}

/* LINK-WITH-ARROW — handled by .link-arrow in base.css. Provide
   a button-styled alias for consistency in component documentation. */
.btn--link {
  padding: 0;
  background: transparent;
  border: none;
  color: var(--pearl);
}
.btn--link .arrow { transition: transform var(--dur-short) var(--ease-out-expo); }
.btn--link:hover .arrow { transform: translateX(4px); }


/* ============================================================
   PHASE 6 — REVAMP
   New sections: portfolio preview, process, global reach,
   certifications strip (home) · chapter index + capabilities
   (products) · timeline + principles (about) · FAQ (contact) ·
   quality page (pipeline, assurance grid).
   Same language: hairlines, eyebrows, italic display, glass.
   ============================================================ */

/* ----------------------------------------------------------------
   PORTFOLIO PREVIEW (home) — four category cards linking into
   the products chapters. Card-Glass, 16px radius, hover lift
   mirroring .contact-card.
   ---------------------------------------------------------------- */
.folio {
  padding-block: var(--section-pad-y);
}
.folio__header {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: clamp(3rem, 7vw, 5rem);
}
.folio__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-top: var(--space-2);
  text-wrap: balance;
}
.folio__heading em { font-style: normal; font-weight: 400; }
.folio__grid {
  /* Three columns, not four: the portfolio is six disciplines, which
     lands as two clean rows of three. At four columns the last two
     cards stranded on a half-empty second row. */
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}
.folio-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-height: 300px;
  padding: var(--space-4);
  border-radius: 16px;
  text-decoration: none;
  transition:
    transform var(--dur-short) var(--ease-out-expo),
    border-color var(--dur-short) var(--ease-out-expo);
}
.folio-card:hover { transform: translateY(-4px); }
.folio-card__num {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: var(--type-display-m);
  line-height: 1;
  color: color-mix(in srgb, var(--pearl-quiet) 60%, transparent);
}
.folio-card__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.5rem;
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-top: auto;
  text-wrap: balance;
}
.folio-card__species {
  color: var(--pearl-muted);
  font-size: var(--type-caption);
  line-height: 1.6;
}
.folio-card__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: var(--space-2);
  color: var(--pearl);
  font-size: var(--type-caption);
}
.folio-card__cta .arrow { transition: transform var(--dur-short) var(--ease-out-expo); }
.folio-card:hover .folio-card__cta .arrow { transform: translateX(4px); }

@media (max-width: 1100px) {
  .folio__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .folio__grid { grid-template-columns: 1fr; }
  .folio-card { min-height: 0; }
  .folio-card__heading { margin-top: var(--space-2); }
}

/* ----------------------------------------------------------------
   PROCESS (home) — how we work, four numbered steps. Hairline
   top rules, italic numerals, quiet editorial columns.
   ---------------------------------------------------------------- */
.process {
  padding-block: var(--section-pad-y);
}
.process__header { margin-bottom: clamp(3rem, 7vw, 5rem); }
.process__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-top: var(--space-2);
  text-wrap: balance;
}
.process__heading em { font-style: normal; font-weight: 400; }
.process__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-6);
}
.process-step {
  padding-top: var(--space-3);
  border-top: var(--hairline) solid var(--color-divider);
}
.process-step__num {
  display: block;
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: var(--type-display-m);
  line-height: 1;
  color: color-mix(in srgb, var(--pearl-quiet) 60%, transparent);
  margin-bottom: var(--space-3);
}
.process-step__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.375rem;
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-bottom: var(--space-2);
}
.process-step__body {
  color: var(--pearl-muted);
  font-size: var(--type-caption);
  line-height: var(--lh-body);
}
@media (max-width: 1100px) {
  .process__grid { grid-template-columns: repeat(2, 1fr); gap: var(--space-4); }
}
@media (max-width: 640px) {
  .process__grid { grid-template-columns: 1fr; }
}

/* ----------------------------------------------------------------
   GLOBAL REACH (home) — editorial region rows. Region name in
   italic display; markets in muted caption; hairline dividers.
   ---------------------------------------------------------------- */
.reach {
  padding-block: var(--section-pad-y);
}
.reach__grid {
  display: grid;
  grid-template-columns: 4fr 7fr;
  gap: clamp(2rem, 6vw, 6rem);
  align-items: start;
}
.reach__head { position: sticky; top: calc(var(--header-h) + var(--space-4)); }
.reach__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-top: var(--space-2);
  text-wrap: balance;
}
.reach__heading em { font-style: normal; font-weight: 400; }
.reach__note {
  margin-top: var(--space-3);
  color: var(--pearl-muted);
  font-size: var(--type-caption);
  line-height: var(--lh-body);
  max-width: 36ch;
}
.reach__rows { border-top: var(--hairline) solid var(--color-divider); }
.reach-row {
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  gap: var(--space-3);
  /* Centred against the label rather than sharing its baseline. The
     label is one short italic line; the markets list wraps to two or
     three. Baseline alignment pinned the label to the FIRST of those
     lines, so it read as hanging off the top of the block instead of
     belonging to it. */
  align-items: center;
  padding-block: var(--space-4);
  border-bottom: var(--hairline) solid var(--color-divider);
}
.reach-row__region {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: var(--type-display-m);
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
}
.reach-row__markets {
  color: var(--pearl-muted);
  font-size: var(--type-caption);
  line-height: 1.8;
  /* The separators make natural break points, so the ragged right edge
     that justification would otherwise have to fix is not there to fix.
     Balanced wrapping keeps the lines even instead. */
  text-wrap: balance;
  max-width: 46ch;
}
@media (max-width: 900px) {
  .reach__grid { grid-template-columns: 1fr; }
  .reach__head { position: static; }
  .reach-row { grid-template-columns: 1fr; gap: var(--space-1); }
}

/* ----------------------------------------------------------------
   CERTIFICATIONS STRIP (home + quality) — hairline-boxed row.
   Restrained: code in display serif, status in eyebrow.
   ---------------------------------------------------------------- */
.certs {
  padding-block: var(--section-pad-y);
}
.certs__header { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.certs__grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  border-top: var(--hairline) solid var(--color-divider);
  border-left: var(--hairline) solid var(--color-divider);
}
.cert {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: 150px;
  padding: var(--space-3);
  border-right: var(--hairline) solid var(--color-divider);
  border-bottom: var(--hairline) solid var(--color-divider);
  /* Glass — visibly lighter/frosted against the abyssal section
     behind it (surface-elevated tint, stronger than the standard
     Card-Glass recipe, since a single-tone flat background needs
     more contrast than a card floating over varied content to read
     as "glass" at a glance). Kept light enough that the code +
     status text (the only content) stays fully legible. */
  background: color-mix(in srgb, var(--surface-elevated) 55%, transparent);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border-top: 1px solid color-mix(in srgb, var(--pearl) 12%, transparent);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--pearl) 10%, transparent), 0 12px 32px -12px rgba(0, 0, 0, 0.35);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .cert { background: color-mix(in srgb, var(--surface-elevated) 78%, transparent); }
}
.cert__code {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.375rem;
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
}
.cert__status {
  color: var(--pearl-quiet);
  font-size: var(--type-eyebrow);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
}
@media (max-width: 1100px) {
  .certs__grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 640px) {
  .certs__grid { grid-template-columns: repeat(2, 1fr); }
  .cert { min-height: 120px; }
}

/* ----------------------------------------------------------------
   CHAPTER INDEX (products) — sticky whisper-glass anchor bar
   directly under the header. Horizontal scroll on mobile.
   ---------------------------------------------------------------- */
.chapter-nav {
  /* A floating glass pill, not a full-width strip. The section itself
     is transparent and lets clicks through; only the pill is real. */
  position: sticky;
  top: calc(var(--header-h) + 0.6rem);
  z-index: calc(var(--z-header) - 1);
  pointer-events: none;
  padding-block: 0.25rem;
}
@media (max-width: 768px) {
  .chapter-nav { top: calc(var(--header-h-mobile) + 0.5rem); }
}
.chapter-nav .container { display: flex; justify-content: center; }
.chapter-nav__list {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  list-style: none;
  margin: 0;
  padding: 0.35rem;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
  border-radius: 999px;
  background: rgba(10, 18, 32, 0.55);
  -webkit-backdrop-filter: blur(24px) saturate(160%);
  backdrop-filter: blur(24px) saturate(160%);
  border: 1px solid rgba(245, 243, 238, 0.14);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    0 12px 32px -14px rgba(0, 0, 0, 0.75);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .chapter-nav__list { background: rgba(10, 15, 26, 0.96); }
}
.chapter-nav__list::-webkit-scrollbar { display: none; }
.chapter-nav__link {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  white-space: nowrap;
  text-decoration: none;
  color: var(--pearl-muted);
  font-size: var(--type-caption);
  padding: 0.5rem 1rem;
  border-radius: 999px;
  transition:
    color var(--dur-micro) var(--ease-out-expo),
    background-color 240ms var(--ease-out-expo),
    /* keep the shared pressable release — this shorthand would
       otherwise erase components.css's transform transition and the
       press-scale would snap back instead of easing out */
    transform 260ms var(--ease-out-expo);
}
.chapter-nav__link:hover { color: var(--pearl); }
/* Scrollspy state, set by chapterNav.js. */
.chapter-nav__link.is-active {
  color: var(--pearl);
  background: rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16);
}
.chapter-nav__link .num {
  font-family: var(--font-display);
  color: var(--pearl-quiet);
}

/* ----------------------------------------------------------------
   CAPABILITIES (products + quality) — quiet definition rows.
   ---------------------------------------------------------------- */
.capabilities {
  padding-block: var(--section-pad-y);
}
.capabilities__grid {
  display: grid;
  grid-template-columns: 4fr 7fr;
  gap: clamp(2rem, 6vw, 6rem);
  align-items: start;
}
.capabilities__head { position: sticky; top: calc(var(--header-h) + var(--space-4)); }
.capabilities__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-top: var(--space-2);
  text-wrap: balance;
}
.capabilities__heading em { font-style: normal; font-weight: 400; }
.cap-list { border-top: var(--hairline) solid var(--color-divider); }
.cap-row {
  display: grid;
  grid-template-columns: 1fr 1.6fr;
  gap: var(--space-3);
  padding-block: var(--space-3);
  border-bottom: var(--hairline) solid var(--color-divider);
}
.cap-row__key {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.125rem;
  letter-spacing: var(--tr-display);
  color: var(--pearl);
}
.cap-row__val {
  color: var(--pearl-muted);
  font-size: var(--type-caption);
  line-height: var(--lh-body);
}
@media (max-width: 900px) {
  .capabilities__grid { grid-template-columns: 1fr; }
  .capabilities__head { position: static; }
  .cap-row { grid-template-columns: 1fr; gap: var(--space-1); }
}

/* ----------------------------------------------------------------
   TIMELINE (about) — milestone rows. Year in italic display.
   ---------------------------------------------------------------- */
.timeline {
  padding-block: var(--section-pad-y);
}
.timeline__grid {
  display: grid;
  grid-template-columns: 4fr 7fr;
  gap: clamp(2rem, 6vw, 6rem);
  align-items: start;
}
.timeline__head { position: sticky; top: calc(var(--header-h) + var(--space-4)); }
.timeline__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-top: var(--space-2);
  text-wrap: balance;
}
.timeline__heading em { font-style: normal; font-weight: 400; }
.timeline__rows { border-top: var(--hairline) solid var(--color-divider); }
.timeline-row {
  display: grid;
  grid-template-columns: 1fr 2.4fr;
  gap: var(--space-3);
  padding-block: var(--space-4);
  border-bottom: var(--hairline) solid var(--color-divider);
}
.timeline-row__year {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: var(--type-display-m);
  line-height: 1;
  color: var(--pearl);
}
.timeline-row__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.25rem;
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-bottom: var(--space-1);
}
.timeline-row__body {
  color: var(--pearl-muted);
  font-size: var(--type-caption);
  line-height: var(--lh-body);
  max-width: 52ch;
}
@media (max-width: 900px) {
  .timeline__grid { grid-template-columns: 1fr; }
  .timeline__head { position: static; }
  .timeline-row { grid-template-columns: 1fr; gap: var(--space-2); }
}

/* ----------------------------------------------------------------
   PRINCIPLES (about) — three numbered tenets.
   ---------------------------------------------------------------- */
.principles {
  padding-block: var(--section-pad-y);
}
.principles__header { margin-bottom: clamp(3rem, 7vw, 5rem); }
.principles__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-top: var(--space-2);
  text-wrap: balance;
}
.principles__heading em { font-style: normal; font-weight: 400; }
.principles__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-6);
}
@media (max-width: 900px) {
  .principles__grid { grid-template-columns: 1fr; gap: var(--space-4); }
}

/* ----------------------------------------------------------------
   FAQ (contact) — native details/summary accordion, styled to
   the hairline system. No JS required.
   ---------------------------------------------------------------- */
.faq {
  padding-block: var(--section-pad-y);
}
.faq__grid {
  display: grid;
  grid-template-columns: 4fr 7fr;
  gap: clamp(2rem, 6vw, 6rem);
  align-items: start;
}
.faq__head { position: sticky; top: calc(var(--header-h) + var(--space-4)); }
.faq__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-top: var(--space-2);
  text-wrap: balance;
}
.faq__heading em { font-style: normal; font-weight: 400; }
.faq__list { border-top: var(--hairline) solid var(--color-divider); }
.faq__item { border-bottom: var(--hairline) solid var(--color-divider); }
.faq__q {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: var(--space-3);
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.25rem;
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  transition: color var(--dur-micro) var(--ease-out-expo);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q:hover { color: var(--pearl-muted); }
.faq__q::after {
  content: '+';
  flex: none;
  font-family: var(--font-display);
  font-style: normal;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--pearl-quiet);
  transition: transform var(--dur-short) var(--ease-out-expo);
}
.faq__item[open] .faq__q::after { transform: rotate(45deg); }
.faq__a {
  padding-bottom: var(--space-3);
  color: var(--pearl-muted);
  font-size: var(--type-caption);
  line-height: var(--lh-body);
  max-width: 58ch;
}
@media (max-width: 900px) {
  .faq__grid { grid-template-columns: 1fr; }
  .faq__head { position: static; }
}

/* ----------------------------------------------------------------
   QUALITY PAGE — inspection pipeline. Vertical numbered stages
   joined by a hairline spine.
   ---------------------------------------------------------------- */
.pipeline {
  padding-block: var(--section-pad-y);
}
.pipeline__header { margin-bottom: clamp(3rem, 7vw, 5rem); }
.pipeline__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
  margin-top: var(--space-2);
  text-wrap: balance;
}
.pipeline__heading em { font-style: normal; font-weight: 400; }
.pipeline__list {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
}
.pipeline__list::before {
  content: '';
  position: absolute;
  top: 0.5rem;
  bottom: 0.5rem;
  left: clamp(1.25rem, 3vw, 2.25rem);
  width: var(--hairline);
  background: var(--color-divider);
}
.pipeline-stage {
  position: relative;
  display: grid;
  grid-template-columns: clamp(2.5rem, 6vw, 4.5rem) 1fr 1.4fr;
  gap: var(--space-3);
  align-items: baseline;
  padding-block: var(--space-4);
}
.pipeline-stage + .pipeline-stage { border-top: var(--hairline) solid var(--color-divider); }
.pipeline-stage__num {
  position: relative;
  z-index: 1;
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  font-size: var(--type-display-m);
  line-height: 1;
  color: var(--pearl-quiet);
  /* Masks the spine line behind the numeral. Translucent (not solid
     abyssal) so it doesn't read as an opaque patch on the section's
     glass — the double tint lands close to the surrounding pane. */
  background: color-mix(in srgb, var(--abyssal) 55%, transparent);
}
.pipeline-stage__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.375rem;
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-display);
  color: var(--pearl);
}
.pipeline-stage__body {
  color: var(--pearl-muted);
  font-size: var(--type-caption);
  line-height: var(--lh-body);
}
@media (max-width: 900px) {
  .pipeline-stage { grid-template-columns: clamp(2.5rem, 6vw, 4.5rem) 1fr; }
  .pipeline-stage__body { grid-column: 2; }
}

/* ----------------------------------------------------------------
   SITE HEADER — crystal clear, and identical on every page.

   The header has NO surface anywhere: no tint, no blur, no border, no
   specular line, and no scrim. It floats directly on the footage.

   THE SCRIM THIS REPLACES. The internal pages used to carry a
   .site-header::before gradient — 0.72 alpha at the top edge, fading
   out over 220% of the header's height. It was added for a real
   reason: against the brightest specular frame of the hero footage the
   nav links measured 1.11:1, which is unreadable. But a soft-edged
   gradient is still a bar. It read as one, it made the internal pages
   visibly different from the home page, and the client has now asked
   for it gone twice.

   Legibility instead comes entirely from the drop-shadow below, which
   is applied to the header CONTENTS rather than to a rectangle behind
   them. The protection travels with the letterforms, so it holds over
   any frame of any clip without ever drawing an edge. The values are
   raised from the old pair (which only had to finish a job the scrim
   started) to carry it alone — verified by pixel measurement against
   the brightest hero frame, not by eye.
   ---------------------------------------------------------------- */
.site-header.is-visible {
  background: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border-bottom: none;
}
.site-header.is-visible::after  { display: none; }
.site-header.is-visible::before { display: none; }

.site-header .site-header__inner {
  /* Three stacked shadows, each doing a different job: a tight dark
     halo that sharpens the glyph edge, a mid spread that separates the
     text from mid-tone water, and a wide soft pool that kills the
     brightest speculars. Cheap — one filter on one element, no repaint
     beyond the header. */
  filter: drop-shadow(0 1px 2px  rgba(10, 15, 26, 0.78))
          drop-shadow(0 2px 8px  rgba(10, 15, 26, 0.62))
          drop-shadow(0 4px 20px rgba(10, 15, 26, 0.55));
}

/* ----------------------------------------------------------------
   PAGE-HERO LEGIBILITY FIELD.

   Not a bar, and deliberately not shaped like one: it spans the whole
   hero band, is weakest at the very top, and deepens toward the bottom
   where the title and standfirst actually sit. That gradient reads as
   photographic vignetting on the footage rather than as chrome — there
   is no edge anywhere for the eye to catch.

   It exists because the band had NO darkening of any kind, which was
   survivable while every internal page ran the same dim underwater
   clip. The quality page now runs plant footage shot on a white
   conveyor: measured against it the title came out at 3.76:1 and the
   standfirst at 4.37:1, both under the 4.5:1 floor.

   The stops are set from the WORST case, not the current frame. White
   type at #F5F3EE needs the composited backdrop at or below ~rgb(113)
   to clear 4.5:1, and the belt runs about rgb(235) — which takes 0.56
   alpha to pull down. The title sits between 0.5 and 0.8 of the band,
   so that whole stretch is held at 0.56 or darker. Tuning to the frame
   that happened to be on screen would have passed the measurement and
   still failed in use.
   ---------------------------------------------------------------- */
.page-hero { position: relative; }
.page-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(10, 15, 26, 0.28)  0%,
    rgba(10, 15, 26, 0.20) 20%,
    rgba(10, 15, 26, 0.45) 45%,
    rgba(10, 15, 26, 0.62) 60%,
    rgba(10, 15, 26, 0.72) 84%,
    /* Fades to NOTHING at the band's foot, because by that row the page
       pane beneath has ramped to full and is carrying the tint. Two
       scrims stacked at the boundary was what made the line. The title
       band (0.66-0.80 of the height) still gets its full 0.72, so the
       contrast measured against the white-conveyor footage is
       untouched. */
    rgba(10, 15, 26, 0) 100%);
  pointer-events: none;
  z-index: -1;
}

/* ----------------------------------------------------------------
   STANDALONE DIVIDERS — soften AND seal. Two problems with the old
   1px rules: (1) a hard full-bleed line slices the glass, and
   (2) the divider row itself carried no section tint, so its strip
   of backdrop leaked through at full brightness between the tinted
   sections — the "lines breaking up the page". Layer a faint
   centre-fading line OVER the same section tint so the strip is
   sealed and the line only whispers.
   ---------------------------------------------------------------- */
main > .divider,
.chapter-divider {
  height: 1px;
  margin: 0;
  border: none;
  /* No base tint needed anymore — the continuous body::after pane
     runs beneath transparent sections AND these divider rows, so
     nothing leaks. Just the whisper of a centre-fading line. */
  background: linear-gradient(90deg,
    transparent 0%,
    color-mix(in srgb, var(--pearl-quiet) 22%, transparent) 50%,
    transparent 100%);
}

/* ----------------------------------------------------------------
   THE TWO ARMS — home-page section stating the business model in one
   glance: global trading + frozen exports, side by side as two glass
   cards (reusing the contact-card surface so the language stays
   consistent). Collapses to a single column on narrow screens.
   ---------------------------------------------------------------- */
.arms {
  padding-block: var(--section-pad-y);
  position: relative;
  z-index: var(--z-content);
}
.arms__header { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.arms__heading em { font-style: normal; font-weight: 400; }
.arms__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-3);
}
@media (max-width: 900px) {
  .arms__grid { grid-template-columns: 1fr; }
}

/* ==================================================================
   LOCAL TIME — analogue dial (contact page).
   The reference is an automotive cabin clock: baton indices instead of
   numerals, a fine minute track, slim hands with a counterweight tail,
   and a maker's line under twelve. Restraint is the whole effect —
   there is no colour on the dial except a single teal second hand,
   which is the site's "accent of accents" spent in exactly one place.
   ================================================================== */
.localtime {
  /* Deliberately tighter than --section-pad-y (which runs 6-12rem).
     This is one quiet object, not a full content section — full section
     rhythm left it marooned in empty space, and it reads better sitting
     close to the contact detail it belongs with. */
  padding-block: clamp(2rem, min(4.0vw, 6.0vh), 3.5rem);
  position: relative;
  z-index: var(--z-content);
}
.localtime__grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: clamp(2rem, 6vw, 6rem);
  align-items: center;
}
.localtime__heading em { font-style: normal; font-weight: 400; }
.localtime__note {
  margin-top: var(--space-3);
  color: var(--pearl-muted);
  font-size: var(--type-caption);
  line-height: var(--lh-body-text);
  max-width: 46ch;
}

/* The disc reads as a piece of glass set into the page: card-tier tint,
   a bright top edge where light catches the bezel, and a deep shadow
   so it sits ON the canvas rather than in it. */
.clock {
  width: clamp(200px, 26vw, 280px);
  aspect-ratio: 1;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(26, 35, 48, 0.50);
  background: var(--glass-card-bg);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  backdrop-filter: blur(18px) saturate(150%);
  box-shadow:
    inset 0 1px 0 rgba(245, 243, 238, 0.22),
    inset 0 -1px 0 rgba(245, 243, 238, 0.06),
    0 28px 60px -22px rgba(0, 0, 0, 0.65);
}
.clock__svg { width: 100%; height: 100%; display: block; }

.clock__ticks line {
  stroke: var(--pearl);
  stroke-opacity: 0.28;
  stroke-width: 0.7;
}
.clock__batons line {
  stroke: var(--pearl);
  stroke-opacity: 0.62;
  stroke-width: 2.2;
  stroke-linecap: round;
}
.clock__batons--cardinal line {
  stroke-opacity: 0.95;
  stroke-width: 2.8;
}

.clock__wordmark,
.clock__zone {
  fill: var(--pearl);
  font-family: var(--font-sans);
  text-anchor: middle;
  text-transform: uppercase;
}
.clock__wordmark {
  font-size: 8px;
  font-weight: 550;
  letter-spacing: 2.4px;
  fill-opacity: 0.62;
}
.clock__zone {
  font-size: 6.5px;
  font-weight: 500;
  letter-spacing: 2px;
  fill-opacity: 0.34;
}

.clock__hand line { stroke: var(--pearl); }
.clock__hand--hour   line { stroke-width: 4.4; stroke-opacity: 0.94; }
.clock__hand--minute line { stroke-width: 2.8; stroke-opacity: 0.94; }
.clock__hand--second line,
.clock__hand--second circle {
  stroke: var(--teal);
  fill: var(--teal);
  stroke-width: 1;
  stroke-opacity: 0.9;
  fill-opacity: 0.9;
}
.clock__cap     { fill: var(--pearl); }
.clock__cap-pin { fill: var(--deep); }

@media (max-width: 900px) {
  .localtime__grid {
    grid-template-columns: 1fr;
    justify-items: start;
    gap: var(--space-6);
  }
}

/* Reduced transparency: the dial becomes a solid disc rather than
   disappearing into the page. */
@media (prefers-reduced-transparency: reduce) {
  .clock {
    background: rgba(19, 26, 38, 0.98);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* ==================================================================
   GLOSSARY — decodes the trade abbreviations.

   Both competitors print HLSO and PDTO with no definition anywhere.
   That serves the trade buyer who already knows and quietly loses the
   importer, retailer or private-label brand who does not — which is
   precisely the higher-margin customer.
   ================================================================== */

.glossary { padding-block: clamp(4rem, min(9.0vw, 13.5vh), 7rem); }
.glossary__header { margin-bottom: clamp(2.5rem, 5vw, 4rem); }

/* The regrouped glossary: a hook line under the heading, then four named
   groups (shrimp / cephalopods / fish / freezing). Subheads borrow the
   eyebrow's voice so the groups read as chapters, not a second heading
   competing with "The trade, in plain words." */
.glossary__lead {
  margin: var(--space-3) 0 0;
  max-width: 58ch;
  font-size: var(--type-caption);
  line-height: 1.6;
  color: var(--color-text-muted);
}
.glossary__section + .glossary__section { margin-top: clamp(2.25rem, 4.5vw, 3.25rem); }
.glossary__subhead {
  font-family: var(--font-sans);
  font-size: var(--type-eyebrow);
  font-weight: 550;
  text-transform: uppercase;
  letter-spacing: var(--tr-eyebrow-t);
  line-height: var(--lh-eyebrow);
  color: var(--pearl-muted);
  margin: 0 0 var(--space-2);
}

.glossary__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  gap: 0;
  border-top: var(--hairline) solid var(--color-divider);
}

.glossary__item {
  display: grid;
  grid-template-columns: 7.5rem 1fr;
  gap: var(--space-3);
  align-items: baseline;
  padding: 1.15em 0;
  border-bottom: var(--hairline) solid var(--color-divider);
}
/* Two columns of definitions need a gutter between them, but only when
   there actually are two columns. */
@media (min-width: 60rem) {
  .glossary__grid { column-gap: clamp(2rem, 5vw, 4rem); }
}

.glossary__term {
  font-family: var(--font-sans);
  font-size: var(--type-caption);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--color-text);
  margin: 0;
}

.glossary__def {
  font-size: var(--type-caption);
  line-height: 1.55;
  color: var(--color-text-muted);
  margin: 0;
}

@media (max-width: 480px) {
  .glossary__item { grid-template-columns: 1fr; gap: var(--space-1); }
}


/* Enquiry fields — focus indicator with actual area. `outline: none` used
   to leave a 1px border tint as the only cue, which is invisible at a
   glance and fails the 3:1 WCAG asks of a focus indicator. */
.enquiry__input:focus-visible,
.enquiry__select:focus-visible,
.enquiry__textarea:focus-visible {
  outline: none;
  border-bottom-color: var(--pearl);
  box-shadow: 0 2px 0 0 var(--pearl);
}

/* ==================================================================
   RFQ FORM — grouped fields, and the copy-out panel.

   Fieldsets rather than one flat grid: thirteen inputs in an
   undifferentiated block reads as work, the same thirteen in three
   named groups reads as a form with a shape. Only four are required.
   ================================================================== */

.enquiry__set {
  border: 0;
  padding: 0;
  margin: 0 0 clamp(2rem, 4vw, 2.75rem);
}
.enquiry__set:last-of-type { margin-bottom: var(--space-4); }

.enquiry__legend {
  padding: 0;
  margin-bottom: var(--space-3);
  color: var(--color-text-subtle);
}

.enquiry__aside {
  margin: calc(var(--space-2) * -1) 0 var(--space-4);
  font-size: var(--type-caption);
  color: var(--color-text-subtle);
  max-width: 46ch;
}

/* Quantity and its unit are one answer, so they sit on one line. */
.enquiry__combo { display: grid; grid-template-columns: 1fr auto; gap: var(--space-2); align-items: end; }
.enquiry__select--unit { width: auto; min-width: 7.5rem; }

/* The month input is the one control browsers style natively; force it
   onto the same baseline as its siblings. */
.enquiry__input[type="month"] {
  color-scheme: dark;
  min-height: 2.6rem;
}

/* ------------------------------------------------------------------
   Copy-out panel. A mailto: hand-off silently does nothing for anyone
   on webmail — Outlook Web and Gmail in a browser, which is most of
   this trade — and they get no error to act on. Rather than lose the
   enquiry, the composed text is shown here to copy and paste.
   ------------------------------------------------------------------ */
.enquiry__fallback {
  margin-top: var(--space-4);
  padding: clamp(1.25rem, 3vw, 1.75rem);
  border: var(--hairline) solid var(--color-divider);
  border-radius: var(--radius-md, 8px);
  background: rgba(26, 35, 48, 0.45);
  background: color-mix(in srgb, var(--surface) 45%, transparent);
}
.enquiry__fallback[hidden] { display: none; }

.enquiry__fallback-title {
  font-family: var(--font-sans);
  font-size: var(--type-caption);
  font-weight: 550;
  color: var(--color-text);
  margin: 0 0 var(--space-2);
}
.enquiry__fallback-body {
  font-size: var(--type-caption);
  color: var(--color-text-muted);
  margin: 0 0 var(--space-3);
  max-width: 54ch;
}
.enquiry__fallback-text {
  width: 100%;
  min-height: 9rem;
  font-family: var(--font-sans);
  font-size: 0.78rem;
  line-height: 1.55;
  color: var(--color-text-muted);
  background: rgba(10, 15, 26, 0.55);
  border: var(--hairline) solid var(--color-divider);
  border-radius: 4px;
  padding: var(--space-3);
  resize: vertical;
}
.enquiry__fallback-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  margin-top: var(--space-3);
}
.enquiry__fallback-status {
  font-size: var(--type-caption);
  color: var(--color-text-subtle);
}

@media (max-width: 520px) {
  .enquiry__combo { grid-template-columns: 1fr; }
  .enquiry__select--unit { width: 100%; }
}


/* ==================================================================
   SPOTLIGHT — the two offers that separate this house from the field.

   Given a treatment deliberately unlike the chapters: a pair of bordered
   panels with a bright top edge, rather than the chapters' watermark
   numeral and editorial rhythm. The point is that the eye should not
   file these as "category six and seven".
   ================================================================== */

.spotlight { padding-block: clamp(4rem, min(9.0vw, 13.5vh), 7rem); }
.spotlight__header { margin-bottom: clamp(2.5rem, 5vw, 3.5rem); }
.spotlight__heading {
  font-family: var(--font-display);
  font-size: var(--type-display-sm, clamp(1.75rem, 4vw, 2.75rem));
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin: var(--space-2) 0 0;
}

.spotlight__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: clamp(1.25rem, 2.5vw, 2rem);
}

.spotlight-card {
  position: relative;
  padding: clamp(1.75rem, 3.5vw, 2.5rem);
  border-radius: 10px;
  background: rgba(26, 35, 48, 0.42);
  background: color-mix(in srgb, var(--surface) 42%, transparent);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
  backdrop-filter: blur(20px) saturate(150%);
  border: 1px solid rgba(245, 243, 238, 0.10);
  border: 1px solid color-mix(in srgb, var(--pearl) 10%, transparent);
  overflow: hidden;
}

/* Bright top edge — light catching the leading face of the material.
   It is what separates these panels from the flatter chapter surfaces. */
.spotlight-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg,
    transparent,
    rgba(245, 243, 238, 0.45) 22%,
    rgba(245, 243, 238, 0.45) 78%,
    transparent);
  pointer-events: none;
}

.spotlight-card__tag {
  display: block;
  color: var(--color-text-subtle);
  margin-bottom: var(--space-3);
}

.spotlight-card__heading {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3.2vw, 2.25rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-3);
}

.spotlight-card__body {
  color: var(--color-text-muted);
  margin: 0 0 var(--space-4);
  max-width: 42ch;
}

.spotlight-card__list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: var(--hairline) solid var(--color-divider);
}
.spotlight-card__list li {
  padding: 0.65em 0;
  border-bottom: var(--hairline) solid var(--color-divider);
  font-size: var(--type-caption);
  color: var(--color-text-muted);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .spotlight-card { background: color-mix(in srgb, var(--abyssal) 92%, transparent); }
}

/* ----------------------------------------------------------------
   THE RANGE (home) — replaces .folio.

   A specification ledger, not a card grid. Five categories as five
   hairline-ruled rows carrying species AND forms inline; the two
   differentiators sit BESIDE the ledger as one glass plate with a
   teal edge, introduced by a plain sentence and carrying no numeral,
   so they cannot be misread as items 06 and 07.

   TEAL BUDGET — teal is "the accent of accents" (tokens.css §COLOUR).
   It is spent exactly three times in this section: the plate's left
   edge, and the two kicker marks. Nowhere else. Do not add a fourth.
   ---------------------------------------------------------------- */

/* ==================================================================
   THE REEL — a continuous run of the range beneath the heritage text.

   Two identical tracks laid end to end, translated by exactly -50% and
   restarted. Because the second track is a copy of the first, the frame
   at 100% is pixel-identical to the frame at 0%, so the loop has no
   seam and needs no JavaScript.

   The photographs are placeholders and will not match each other — one
   is a market stall, one a banana leaf, one a harbour. A duotone fixes
   that: greyscale first, then a single blue gradient applied in `color`
   blend mode, so every frame ends up built from the same two inks and
   the set reads as one regardless of what was shot.
   ================================================================== */

.reel {
  margin-top: clamp(2.5rem, 5vw, 4rem);
  overflow: hidden;
  border-radius: 10px;
  border: 1px solid rgba(245, 243, 238, 0.10);
  background: var(--abyssal);
  /* Feather both ends so frames enter and leave rather than being cut. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.reel__track {
  display: flex;
  width: max-content;
  /* One source of truth for the frame geometry. The seam depends on
     every frame carrying an identical trailing margin — including the
     last — so that the track is exactly 2N x (frame + margin). */
  --reel-frame: clamp(230px, 26vw, 360px);
  --reel-gap: 2px;
  /* NO `gap` HERE — this is the bug that made the loop jump.

     With `gap`, a track of 2N frames is N frames + (N - 0.5) gaps wide
     at the halfway mark, because the run has 2N-1 gaps between its
     items and none after the last. translateX(-50%) therefore lands
     half a gap short of the seam, and every single cycle the whole
     reel snapped sideways by that amount. It reads as the loop
     "breaking".

     A trailing margin on every frame — including the last — makes the
     track exactly 2N x (frame + margin), so -50% is exactly N frames
     and N margins: the seam is mathematically invisible, at any frame
     count and any fractional frame width. */
  gap: 0;
  animation: reel-run 83s linear infinite;
  /* The track is promoted for the whole of its (permanent) animation,
     which is the one case where a standing compositor layer is right. */
  will-change: transform;
}
.reel__track > .reel__item { margin-right: var(--reel-gap); }

/* Hovering holds the run so a frame can actually be looked at. */
@media (hover: hover) {
  .reel:hover .reel__track { animation-play-state: paused; }
}

.reel__item {
  position: relative;
  flex: 0 0 auto;
  width: var(--reel-frame);
  aspect-ratio: 4 / 3;
  margin: 0;
  overflow: hidden;
  background: var(--abyssal);
}

.reel__item img {
  /* ABSOLUTE, and this is load-bearing, not cosmetic. As an in-flow
     child the <img> contributed its intrinsic 900px width to the
     track's `max-content` sizing, so a track holding 26 frames of
     230px (6032px of actual content) reported 23924px wide. The
     animation translates by -50% OF THAT, i.e. 11962px, when one copy
     of the run is only 3016px — so the reel spent most of every cycle
     scrolling through empty space. That is the "loop breaking".
     Out-of-flow children contribute nothing to intrinsic sizing, so
     the track now measures what it actually contains. */
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Ink one: everything reduced to a single tonal range. */
  /* True colour — the client asked to see the photographs as shot. */
  filter: contrast(1.03) saturate(1.02);
}


/* A little depth so the strip sits in the page rather than on it. */
.reel__item::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgba(10, 15, 26, 0) 55%, rgba(10, 15, 26, 0.45) 100%);
  pointer-events: none;
}

/* -50% of the track is exactly one full copy of the run. Duration is
   set for a constant SPEED, not a constant cycle: 13 frames need
   roughly 90s to travel at the same pace 7 frames did in 48s. Change
   the frame count and this wants changing with it. */
/* -50% is exactly one copy of the run, and that is now MEASURABLE:
   with the images out of flow the track reports 6032px for 26 frames
   of 230+2, and half of that is 3016px — precisely the distance to
   the duplicate frame. Frame 14 lands where frame 1 began, so the
   restart is invisible. Duration is set for constant speed, so it
   wants changing if the frame count does. */
@keyframes reel-run {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* Motion off: the strip becomes a plain, still row. It still shows the
   range; it simply stops moving. */
@media (prefers-reduced-motion: reduce) {
  .reel__track { animation: none; }
  .reel { overflow-x: auto; }
}


@media (max-width: 640px) {
  .reel__track { animation-duration: 34s; }
}

/* ==================================================================
   THE RANGE — a menu, not a table.

   Two earlier versions were rejected as crowded, and both failed the
   same way: a numeral, a name, a species line, a forms line and an
   arrow on every row, with the two offers squeezed into a side column
   alongside. That is five columns of furniture around what is really
   five words. Everything decorative is gone here — the category sits in
   display type, its species sits quietly beside it, a hairline divides
   them, and nothing else competes.
   ================================================================== */

/* On the shared section rhythm. It previously carried its own,
   heavier clamp, which made it the one block that felt oversized
   next to everything around it. */
.range { padding-block: var(--section-pad-y); }

.range__header { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.range__heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--type-display-l);
  line-height: var(--lh-display-l);
  letter-spacing: var(--tr-display-l);
  color: var(--pearl);
  margin: var(--space-2) 0 0;
}
.range__heading em { font-style: normal; font-weight: 400; }


.range__more { display: inline-flex; margin-top: clamp(2rem, 4vw, 3rem); }

/* ---------- The two offers, underneath and at full width ---------- */


@media (max-width: 720px) {
  .range__link { grid-template-columns: 1fr; gap: var(--space-1); }
}
@media (prefers-reduced-motion: reduce) {
  .range-offer:hover { transform: none; }
}


/* ==================================================================
   HERO LEGIBILITY WITHOUT A SCRIM.

   The hero text used to sit on a 428px gradient that reached 68% black.
   It did the job, but a wash that size over open water is exactly the
   dark fade that kept being reported, so it is gone.

   Contrast is carried by the type instead. Two shadows: a tight one
   that separates each letterform from whatever is directly behind it,
   and a wide soft one that darkens a small halo around the text without
   drawing an edge anywhere. Nothing is laid across the footage, so
   there is no band to see at any scroll position.

   Note for later: automated contrast checkers measure text against the
   colour behind it and cannot see a text-shadow, so this hero will
   report a low ratio even though it reads cleanly. If a formal WCAG
   figure is ever required, the honest fix is a solid panel behind the
   text — not the gradient that was just removed.
   ================================================================== */
.hero__headline,
.hero__eyebrow,
.hero__sub,
.page-hero__title,
.page-hero__sub {
  text-shadow:
    0 1px 3px rgba(10, 15, 26, 0.62),
    0 4px 22px rgba(10, 15, 26, 0.52);
}

@media (prefers-contrast: more) {
  .hero__headline,
  .hero__eyebrow,
  .hero__sub,
  .page-hero__title,
  .page-hero__sub {
    text-shadow:
      0 1px 2px rgba(10, 15, 26, 0.95),
      0 2px 10px rgba(10, 15, 26, 0.9),
      0 0 30px rgba(10, 15, 26, 0.8);
  }
}


/* ==================================================================
   TOUCH TARGETS

   Measured on a 375px viewport: footer links were 25px tall and the
   link-arrows 33px, against a 44px minimum. Padding is added rather
   than font-size, so nothing about the visual rhythm changes — the
   target simply extends past the glyphs where a fingertip lands.
   ================================================================== */
@media (max-width: 900px) {
  .site-footer a,
  .footer-col a,
  .menu-list a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  .link-arrow {
    min-height: 44px;
    align-items: center;
  }

  .site-header__logo,
  .site-footer__mark-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* The range rows are already tall, but make the whole row the target
     rather than only the text inside it. */
  .range__link { min-height: 56px; }

  /* The chapter rail is the primary way through the products page on a
     phone; 27px was well under a fingertip. */
  .chapter-nav__link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  .contact-card,
  .range-offer { min-height: 44px; }

  /* Phone, WhatsApp and email in the office block: these are the three
     links a buyer on a phone is most likely to actually press, and they
     were the smallest on the page at 20px. */
  .office__meta-row dd a { display: inline-flex; align-items: center; min-height: 44px; }
}

/* ==================================================================
   HERO TYPEFACE — Plus Jakarta Sans

   The hero display line moves from Gambetta to Plus Jakarta Sans.
   Every other heading on the site stays on Gambetta: this is a
   deliberate split of roles, not drift.

   Tracking and weight are re-tuned rather than inherited. The display
   tokens were set for a serif at 96px, where -0.035em is right; a
   geometric sans at that size closes up badly at the same value and the
   counters start to fill in. Sans also carries less optical weight at
   display size, so the weight steps up from 500 to 600 to hold the same
   presence against the ocean behind it.
   ================================================================== */
/* Selector carries the element as well as the class. base.css has
   `h1.display, h2.display, h3.display { font-family: var(--font-display) }`
   at specificity (0,1,1), and both hero titles are <h1 class="... display">.
   A bare `.hero__headline` is (0,1,0) and loses to it no matter how late
   it appears in the cascade — which is exactly what happened: the size
   and tracking below applied while the family and weight silently did
   not. */
h1.hero__headline,
h1.page-hero__title,
.hero__headline,
.page-hero__title {
  font-family: var(--font-hero);
  /* 500, down from 600. General Sans has a fuller, more geometric bowl
     than the face this replaced, so the same numeric weight rendered
     heavier on the page than it measured. 500 is where the display line
     reads as confident rather than bold. */
  font-weight: 500;
  letter-spacing: -0.022em;
}

/* Sized down. A geometric sans reads BIGGER than a serif at the same
   nominal size — the x-height is taller and the counters are wider, so
   Gambetta's scale was overpowering here once the face changed. Roughly
   a fifth off the top end, with the floor lowered less so it does not
   collapse on a phone. */
.hero__headline {
  font-size: clamp(2.25rem, min(4.8vw, 7.5vh), 4.25rem);
  max-width: 22ch;
}
.page-hero__title { font-size: clamp(2.25rem, min(5.2vw, 8vh), 4rem); }

.hero__headline {
  /* Gambetta's tall ascenders needed 0.98; the sans sits lower and
     wants a touch more air between the two lines. */
  line-height: 1.02;
}

.page-hero__title { line-height: 0.98; }

/* The accent line, one step below the title it sits under: 400 against
   500. Not italic -- the emphasis is carried by the weight drop and the
   line break alone, which is why every one of these is font-style:
   normal despite being marked up as <em>.

   This is the ONLY place the accent weight is set. A second, later rule
   used to re-declare it for the homepage at a heavier value, which meant
   the hero's two lines rendered identically while this rule looked like
   it was creating the contrast. */
h1.hero__headline em,
h1.page-hero__title em,
.hero__headline em,
.page-hero__title em {
  font-style: normal;
  font-weight: 400;
}

@media (max-width: 640px) {
  .hero__headline,
  .page-hero__title { letter-spacing: -0.018em; }

  /* On a phone the hero is the eyebrow and the headline, full stop. The
     standfirst below it pushed the line off a 375pt screen and turned an
     opening statement into a paragraph. Hidden rather than deleted: the
     markets it lists appear twice more on this page, so nothing is lost
     to a reader or a crawler, and the copy returns intact at 641px. */
  .hero__sub { display: none; }
}

/* ==================================================================
   LOGO SCALE + HERO LINE 2

   Header mark up from 44px to 60px, and the bar grows with it rather
   than clipping — a 60px logo inside a 72px bar leaves 6px of breathing
   room top and bottom, which reads as cramped, so the header token goes
   to 92px (76px on mobile) to keep the old proportion.

   Footer mark roughly doubled from its previous clamp.
   ================================================================== */
:root {
  --header-h:        92px;
  --header-h-mobile: 76px;
}

.site-header__logo img { height: 52px; }

@media (max-width: 768px) {
  .site-header__logo img { height: 41px; }
}
@media (max-width: 480px) {
  .site-header__logo img { height: 36px; }
}

.site-footer__mark { width: clamp(200px, 22vw, 300px); }

/* ==================================================================
   FORM TILES — iOS-style glass, with the range revealed on hover.

   Four decisions worth recording:

   1. THE MATERIAL is built the way Apple builds Liquid Glass, not by
      stacking blur on a tint. Four layers: a translucent fill; a rim
      whose brightness VARIES around the tile, drawn as a gradient
      border via mask-composite rather than a flat border-colour, which
      is the difference between reading as glass and reading as a
      stroke; a specular sheen across the top third; and a shadow pair
      that lifts the tile off the page. A flat border and a blur look
      like a box. Light behaving unevenly at the edges looks like glass.

   2. THE PHOTOGRAPH IS SUBORDINATE. It sits at low opacity behind a
      duotone, and only lifts on hover. That is what lets the row stay
      calm at rest, and it means a weak or mismatched photograph cannot
      wreck the design — which matters, because these are placeholders.

   3. THE RANGE APPEARS ON HOVER. At rest the tile states the form. On
      hover the products inside that form rise into view. The line
      underneath cross-fades out as the list comes in, so the tile never
      grows and the row never reflows.

   4. TOUCH GETS EVERYTHING AT REST. There is no hover on a phone, so
      below the hover breakpoint the product list is simply always
      visible. No tile hides its content behind an interaction the
      device cannot perform.
   ================================================================== */

.forms {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(0.75rem, 1.3vw, 1.15rem);
}

.form-tile { position: relative; }

.form-tile__link {
  position: relative;
  display: block;
  height: 100%;
  min-height: clamp(15rem, min(23vw, 34vh), 21rem);
  padding: clamp(1.35rem, 2vw, 1.85rem);
  border-radius: 20px;
  text-decoration: none;
  color: inherit;
  overflow: hidden;
  isolation: isolate;
  background: rgba(255, 255, 255, 0.055);
  -webkit-backdrop-filter: blur(22px) saturate(170%);
  backdrop-filter: blur(22px) saturate(170%);
  box-shadow:
    0 18px 44px -20px rgba(0, 0, 0, 0.75);
  transition:
    transform 560ms var(--ease-out-expo),
    box-shadow 560ms var(--ease-out-expo),
    background-color 560ms var(--ease-out-expo);
}

/* The rim. Uneven around the tile, the way light actually falls. */
.form-tile__link::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(150deg,
    rgba(255, 255, 255, 0.55) 0%,
    rgba(255, 255, 255, 0.08) 38%,
    rgba(255, 255, 255, 0.05) 64%,
    var(--tile-edge) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
  opacity: 0.85;
  transition: opacity 560ms var(--ease-out-expo);
}

/* Specular sheen across the top — the reflection off a curved surface. */
.form-tile__link::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 42%;
  z-index: 2;
  border-radius: 20px 20px 40% 40% / 20px 20px 18% 18%;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.13) 0%,
    rgba(255, 255, 255, 0.03) 55%,
    rgba(255, 255, 255, 0) 100%);
  pointer-events: none;
}

/* ---- the photograph ------------------------------------------- */
.form-tile__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  border-radius: inherit;
}
.form-tile__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Greyscale first, then the tile's own hue laid over it, so twelve
     mismatched stock photographs read as one set. */
  filter: grayscale(1) contrast(1.1) brightness(0.55);
  transform: scale(1.06);
  opacity: 0.5;
  transition:
    opacity 700ms var(--ease-out-expo),
    transform 900ms var(--ease-out-expo);
}
.form-tile__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(4, 12, 26, 0.15) 0%, rgba(4, 12, 26, 0.88) 78%),
    linear-gradient(160deg, var(--tile-glow) 0%, transparent 72%);
  mix-blend-mode: normal;
}

/* ---- content --------------------------------------------------- */
.form-tile__body {
  position: relative;
  z-index: 4;
  display: flex;
  flex-direction: column;
  height: 100%;
  justify-content: flex-end;
}

.form-tile__name {
  font-family: var(--font-hero);
  font-weight: 600;
  font-size: clamp(1.45rem, min(2.2vw, 3.4vh), 2rem);
  line-height: 1.04;
  letter-spacing: -0.022em;
  color: var(--pearl);
  margin: 0 0 var(--space-2);
}

/* The line and the list occupy the same space; one fades as the other
   arrives, so the tile never changes height. */
.form-tile__line,
.form-tile__items {
  grid-area: 1 / 1;
  margin: 0;
  transition:
    opacity 420ms var(--ease-out-expo),
    transform 480ms var(--ease-out-expo);
}
.form-tile__swap { display: grid; }

.form-tile__line {
  font-size: var(--type-caption);
  line-height: 1.5;
  color: var(--color-text-muted);
  max-width: 28ch;
}

.form-tile__items {
  list-style: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.16rem;
  opacity: 0;
  transform: translateY(8px);
}
/* Plain lines, not chips. The chip pills wrapped unpredictably and
   overflowed narrow tiles; a short list of words needs no boxes. */
.form-tile__items li {
  font-size: var(--type-eyebrow);
  letter-spacing: 0.02em;
  line-height: 1.4;
  color: rgba(245, 243, 238, 0.92);
}
.form-tile__items li::before {
  content: "·";
  margin-right: 0.5em;
  color: rgba(245, 243, 238, 0.5);
}

.form-tile__go {
  position: absolute;
  right: clamp(1.35rem, 2vw, 1.85rem);
  bottom: clamp(1.35rem, 2vw, 1.85rem);
  z-index: 4;
  font-size: 1.1rem;
  color: var(--pearl);
  opacity: 0.45;
  transition:
    transform 480ms var(--ease-out-expo),
    opacity 480ms var(--ease-out-expo);
}

.form-tile--frozen    { --tile-glow: rgba(30, 92, 200, 0.34);  --tile-edge: rgba(122, 176, 255, 0.55); }
.form-tile--chilled   { --tile-glow: rgba(38, 158, 205, 0.32); --tile-edge: rgba(138, 226, 250, 0.55); }
.form-tile--canned    { --tile-glow: rgba(198, 132, 40, 0.30); --tile-edge: rgba(246, 194, 116, 0.55); }
.form-tile--precooked { --tile-glow: rgba(190, 82, 42, 0.30);  --tile-edge: rgba(244, 152, 110, 0.55); }

@media (hover: hover) {
  .form-tile__link:hover {
    transform: translateY(-8px);
    background: rgba(255, 255, 255, 0.085);
    box-shadow:
      0 30px 62px -22px rgba(0, 0, 0, 0.85);
  }
  .form-tile__link:hover::before { opacity: 1; }
  .form-tile__link:hover .form-tile__media img { opacity: 0.9; transform: scale(1); }
  .form-tile__link:hover .form-tile__line  { opacity: 0; transform: translateY(-6px); }
  .form-tile__link:hover .form-tile__items { opacity: 1; transform: translateY(0); }
  .form-tile__link:hover .form-tile__go    { opacity: 1; transform: translateX(4px); }
}

/* Keyboard parity — focus reveals exactly what hover does. */
.form-tile__link:focus-visible {
  outline: 2px solid var(--pearl);
  outline-offset: 3px;
}
.form-tile__link:focus-visible .form-tile__media img { opacity: 0.9; transform: scale(1); }
.form-tile__link:focus-visible .form-tile__line  { opacity: 0; }
.form-tile__link:focus-visible .form-tile__items { opacity: 1; transform: translateY(0); }

/* No hover on touch: show the range at rest rather than hiding it
   behind a gesture the device cannot make. */
@media (hover: none) {
  .form-tile__line  { display: none; }
  .form-tile__items { opacity: 1; transform: none; position: static; }
  .form-tile__media img { opacity: 0.72; }
}

@media (max-width: 1000px) { .forms { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .forms { grid-template-columns: minmax(0, 1fr); }
                             .form-tile__link { min-height: 13rem; } }

@media (prefers-reduced-motion: reduce) {
  .form-tile__link, .form-tile__media img, .form-tile__line,
  .form-tile__items, .form-tile__go { transition-duration: 1ms; }
  .form-tile__link:hover { transform: none; }
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .form-tile__link { background: rgba(14, 22, 38, 0.88); }
}

/* ==================================================================
   PRODUCTS — organised by FORM, not by species.

   The old page ran five chapters by species: cephalopods, shrimp, fish,
   canned, cannery supply. That is how a processor thinks about its own
   factory. It is not how a buyer arrives. A buyer arrives knowing the
   form they need — a frozen block for a re-processing line, chilled
   fillets on a plane, a canned retail pack — and the species is the
   second question, not the first. So the page is cut the same way the
   home page is: frozen, chilled, canned, pre-cooked.

   Every card carries a media band whether or not a photograph exists
   for it yet. Cards without one render a quiet gradient plate rather
   than a gap, so the grid never goes ragged while the client's own
   photography is still being shot. Adding a real photo is a one-line
   change: drop the file in assets/products/ and swap the placeholder
   div for an <img class="product-card__img">.
   ================================================================== */

.form-intro {
  padding: clamp(2rem, 4vh, 3rem) 0 0;
  position: relative;
  z-index: 1;
}
.form-intro__body {
  max-width: 46rem;
  font-size: var(--type-body-l);
  line-height: 1.62;
  color: var(--color-text-muted);
}

.form-chapter {
  position: relative;
  z-index: 1;
  padding: clamp(2.5rem, 6vh, 4.5rem) 0 clamp(1.5rem, 3vh, 2.5rem);
  /* Clear the fixed header AND the floating chapter bar. */
  scroll-margin-top: calc(var(--header-h) + 4.75rem);
}

.form-chapter__head { max-width: 44rem; margin-bottom: clamp(1.5rem, 3vh, 2.25rem); }
.form-chapter__heading {
  font-size: clamp(1.9rem, min(4.2vw, 5.4vh), 3rem);
  line-height: 1.06;
  margin: 0.4rem 0 0.75rem;
}
.form-chapter__lead {
  font-size: var(--type-body-l);
  line-height: 1.6;
  color: var(--color-text-muted);
  margin: 0;
}

.product-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15.5rem), 1fr));
  gap: clamp(0.85rem, 1.4vw, 1.25rem);
}

/* Same material as the home-page tiles: translucent fill, uneven rim,
   specular sheen. Repeating the recipe here rather than sharing a class
   keeps the two components free to diverge — the tiles are a four-across
   hero row, these are a dense grid — without one dragging the other. */
.product-card {
  position: relative;
  display: flex;
  flex-direction: column;
  border-radius: 18px;
  overflow: hidden;
  isolation: isolate;
  background: rgba(255, 255, 255, 0.05);
  -webkit-backdrop-filter: blur(20px) saturate(165%);
  backdrop-filter: blur(20px) saturate(165%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.2),
    0 14px 34px -18px rgba(0, 0, 0, 0.7);
  transition:
    transform 520ms var(--ease-out-expo),
    box-shadow 520ms var(--ease-out-expo),
    background-color 520ms var(--ease-out-expo);
}
.product-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(150deg,
    rgba(255, 255, 255, 0.48) 0%,
    rgba(255, 255, 255, 0.07) 40%,
    rgba(255, 255, 255, 0.04) 66%,
    rgba(255, 255, 255, 0.16) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
}

@media (hover: hover) {
  .product-card:hover {
    transform: translateY(-3px);
    background: rgba(255, 255, 255, 0.075);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.28),
      0 22px 48px -18px rgba(0, 0, 0, 0.8);
  }
  .product-card:hover .product-card__img { opacity: 0.92; transform: scale(1.04); }
}

.product-card__media {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  /* The plate every card falls back to. Deep water, not grey — a card
     with no photograph still belongs to the page. */
  background:
    radial-gradient(120% 90% at 22% 12%, rgba(90, 150, 175, 0.30), transparent 62%),
    linear-gradient(160deg, rgba(12, 32, 54, 0.85), rgba(6, 16, 30, 0.92));
}
.product-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0.78;
  filter: saturate(0.92) contrast(1.02);
  transition: opacity 620ms var(--ease-out-expo), transform 900ms var(--ease-out-expo);
}
/* A single soft swell across the placeholder, so it reads as a
   considered surface rather than a missing image. */
.product-card__media[data-photo="pending"]::after {
  content: "";
  position: absolute;
  left: -10%;
  right: -10%;
  bottom: -30%;
  height: 90%;
  border-radius: 50%;
  background: radial-gradient(60% 50% at 50% 50%, rgba(255, 255, 255, 0.09), transparent 70%);
}

.product-card__body { padding: clamp(0.9rem, 1.4vw, 1.15rem) clamp(1rem, 1.5vw, 1.3rem) clamp(1.1rem, 1.7vw, 1.4rem); }
.product-card__name {
  font-family: var(--font-sans);
  font-size: clamp(1rem, 1.25vw, 1.12rem);
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0 0 0.4rem;
  color: var(--pearl);
}
.product-card__detail {
  margin: 0;
  font-size: clamp(0.9rem, 1.05vw, 0.98rem);
  line-height: 1.55;
  color: var(--color-text-subtle);
}

/* Terms of trade — how a flight is booked, how a can is specified.
   Genuinely useful, but not a product, so it never sits in the grid. */
.form-chapter__note {
  margin-top: clamp(1rem, 1.8vh, 1.5rem);
  padding: clamp(1.1rem, 1.8vw, 1.5rem);
  border-radius: 16px;
  border-left: 2px solid rgba(122, 178, 199, 0.5);
  background: rgba(255, 255, 255, 0.035);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  backdrop-filter: blur(16px) saturate(150%);
  max-width: 52rem;
}
.form-chapter__note-title {
  font-family: var(--font-sans);
  font-size: var(--type-eyebrow);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--pearl-quiet);
  margin: 0 0 0.45rem;
}
.form-chapter__note-body {
  margin: 0;
  font-size: clamp(0.95rem, 1.1vw, 1.02rem);
  line-height: 1.6;
  color: var(--color-text-muted);
}

.form-closing {
  position: relative;
  z-index: 1;
  padding: clamp(2rem, 5vh, 3.5rem) 0 clamp(1rem, 2vh, 2rem);
}
.form-closing__body {
  max-width: 44rem;
  font-size: var(--type-body-l);
  line-height: 1.62;
  color: var(--color-text-muted);
  margin: 0 0 clamp(1.25rem, 2.5vh, 1.75rem);
}

@media (max-width: 640px) {
  .product-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr)); }
}
