/* Generated by src/build.cjs from src/css/*.css; edit those files, not this one. */
/* ===== src/css/base.css ===== */
/* Meridian Flow Capital website, shared system. Owner: design-system workstream.
   25 Sep 2026 owner brief: the design discipline of sonavirarecords.com carried into MFC's own
   identity. A near-black blue field, warm off-white type, MFC cyan as the one accent (used
   sparingly), and a two-family type system: Instrument Serif (OFL) for display, roman as the main
   voice and italic for accents; Plus Jakarta Sans (OFL) for everything a reader operates (nav,
   labels, body, buttons, metadata); the system mono for coordinates and figures. Brand constants
   stay verbatim from Design System/DESIGN.md v1.3; the field, the serif and the 2 px control
   radius are the owner's deliberate departures from that print contract.
   Radius rule: controls and panels 2 px, images and sections 0. No pills anywhere. */

@font-face{font-family:"Plus Jakarta Sans";src:url(../fonts/plus-jakarta-sans-latin-wght-normal.woff2) format("woff2");font-weight:200 800;font-style:normal;font-display:swap}
@font-face{font-family:"Instrument Serif";src:url(../fonts/instrument-serif-latin-normal.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Instrument Serif";src:url(../fonts/instrument-serif-latin-italic.woff2) format("woff2");font-weight:400;font-style:italic;font-display:swap}
/* Metric-matched stand-ins (fontTools, English letter frequencies), so a late font barely moves the text. */
@font-face{font-family:"Plus Jakarta Sans Fallback";src:local("Arial"),local("ArialMT");size-adjust:106.05%;ascent-override:97.88%;descent-override:20.93%;line-gap-override:0%}
@font-face{font-family:"Instrument Serif Fallback";src:local("Times New Roman"),local("TimesNewRomanPSMT");size-adjust:83.65%;ascent-override:118.35%;descent-override:37.06%;line-gap-override:0%}

:root{
  /* Brand constants (DESIGN.md v1.3, verbatim). */
  --navy: #264566;
  --navy-deep: #0B2438;
  --teal: #219EBC;
  --teal-ink: oklch(47% .10 228);
  --teal-light: oklch(78% .10 215);

  /* Field: near-black blue-black, two raised steps, and the deep navy of the map field. */
  --bg: #091117;
  --bg-2: #0d171f;
  --bg-3: #122029;
  --deep: color-mix(in oklab, var(--navy-deep) 70%, var(--bg));
  /* Type, warm off-white. WCAG contrast on --bg, and on --bg-3 (the lightest dark surface):
     ink 16.4 / 14.3, fg 13.1 / 11.4, ink-2 8.6 / 7.5, muted 5.2 / 4.5, accent 9.8 / 8.6.
     AA at every size on every dark surface; keep --muted for metadata and large text. */
  --ink: #f1eee8;
  --fg: #d9d6cf;
  --ink-2: #a9afb0;
  --muted: #7e878a;
  /* Three line weights: dividers (1.4:1 on --bg), structural rules (2.3:1), control edges (3.6:1). */
  --line: rgb(241 238 232 / .14);
  --line-strong: rgb(241 238 232 / .28);
  --edge: rgb(241 238 232 / .42);
  --accent: var(--teal-light);
  /* The corporate surface (Home #corporate, the register on corporate.html). It was the one light
     sheet; since 26 Sep 2026 (owner's call) it takes the dark field like every other section. The
     light values, should it return: #ecebe6, #e2e1db, #0b1218, #4a555c, rgb(11 18 24 / .18), #13607a. */
  --paper: var(--bg);
  --paper-2: var(--bg-2);
  --paper-ink: var(--ink);
  --paper-ink-2: var(--ink-2);
  --paper-line: var(--line);
  --paper-accent: var(--accent);
  /* Globe (globe.js reads these). */
  --globe-ocean-lit: #132b3d;
  --globe-ocean: #0a1822;
  --globe-ocean-edge: #060d12;
  --globe-land: #1e364a;

  --serif: "Instrument Serif", "Instrument Serif Fallback", "Iowan Old Style", Georgia, serif;
  --sans: "Plus Jakarta Sans", "Plus Jakarta Sans Fallback", "Segoe UI", system-ui, sans-serif;
  --mono: ui-monospace, "SFMono-Regular", "Cascadia Mono", Consolas, monospace;

  /* Type scale, fluid, with a deliberately wide step between display and body (16 px). */
  --fs-h1: clamp(3.25rem, 1.6rem + 5vw, 7rem);
  --fs-h2: clamp(2.75rem, 1.5rem + 4vw, 6rem);
  --fs-h3: clamp(1.75rem, 1.2rem + 1.7vw, 2.75rem);
  --fs-h4: clamp(1.375rem, 1.15rem + .7vw, 1.75rem);
  --fs-lead: clamp(1.0625rem, 1rem + .35vw, 1.25rem);
  --fs-small: .9375rem;

  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px;
  --s6:32px; --s7:48px; --s8:64px; --s9:96px; --s10:128px; --s11:176px;
  /* Section rhythm: --sec is the space on each side of a section boundary. It follows the width,
     and the height on short screens (landscape phones). --sec-s tightens a boundary, --sec-l opens
     one; sections pick them by class (the Home pacing block below, .contact). */
  --sec: clamp(48px, min(2.5rem + 4.5vw, 12vh), 136px);
  --sec-s: calc(var(--sec) * .65);
  --sec-l: calc(var(--sec) * 1.4);
  --gutter: clamp(20px, 4.6vw, 112px);
  --max: 1680px;
  --nav-top: 12px;
  --nav-h: 56px;
  --r: 2px;
  --ease: cubic-bezier(.22, 1, .36, 1);
  --ease-io: cubic-bezier(.65, 0, .35, 1);
}
@media (max-width:899.98px){ :root{ --nav-top:8px; --nav-h:54px } }
@media (max-width:699.98px){ :root{ --sec:clamp(64px, 8vw + 40px, 80px) } }

*, *::before, *::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%; scroll-padding-top:calc(var(--nav-top) + var(--nav-h) + var(--s5)); background:var(--bg); color-scheme:dark}
/* Smooth only once the page has loaded (site.js adds .ready): WebKit applies smooth scrolling to its
   first jump to a #fragment, which layout can interrupt, leaving a direct link at the top. */
@media (prefers-reduced-motion:no-preference){ html.ready{scroll-behavior:smooth} }
body{margin:0; background:var(--bg); color:var(--fg); font:400 1rem/1.65 var(--sans); -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale; overflow-x:clip}
img, svg, video, canvas{display:block; max-width:100%}
h1, h2, h3{margin:0; color:var(--ink); font-weight:400; text-wrap:balance}
/* Display: the serif in roman; italic (em, .it) is the accent voice. */
h1, h2, h3{font-family:var(--serif); letter-spacing:-.015em}
h1{font-size:var(--fs-h1); line-height:.95}
h2{font-size:var(--fs-h2); line-height:.96}
h3{font-size:var(--fs-h3); line-height:1.02; letter-spacing:-.01em}
em, .it{font-style:italic}
p, ul, ol, dl, dd, figure{margin:0}
/* No stranded last word in running text or list items. */
p, dd, li{text-wrap:pretty}
a{color:inherit}
[hidden]{display:none !important}
:focus-visible{outline:2px solid var(--accent); outline-offset:3px}
::selection{background:var(--teal); color:var(--bg)}
.shell{width:min(100% - 2 * var(--gutter), var(--max)); margin-inline:auto}
.sr-only{position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0}
.skip{position:fixed; left:var(--s4); top:-80px; z-index:95; background:var(--ink); color:var(--bg); padding:var(--s3) var(--s4); border-radius:var(--r); font-weight:600; text-decoration:none}
.skip:focus{top:var(--s3)}
.i{width:20px; height:20px; fill:currentColor; flex:none}
.accent{color:var(--accent)}
.num{font-family:var(--mono); font-weight:500; letter-spacing:0; font-variant-numeric:tabular-nums}

/* Metadata. Tracked capitals as labels, never as a heading above every heading; mono for figures. */
.caps{font:600 13px/1.3 var(--sans); letter-spacing:.18em; text-transform:uppercase; color:var(--ink-2)}
.coord{font:400 13px/1.4 var(--mono); letter-spacing:.02em; color:var(--ink-2); font-variant-numeric:tabular-nums}
.eyebrow{display:inline-flex; align-items:center; gap:var(--s3); font:600 13px/1.3 var(--sans); letter-spacing:.2em; text-transform:uppercase; color:var(--ink-2)}
.eyebrow::before{content:""; width:32px; height:1px; background:var(--teal)}

/* Actions: rectangular, 2 px corners. A fill rises from the bottom edge on hover or focus (cyan on
   the primary, ink on the secondary); the arrow leaves to the right as a second one arrives from
   the left. Press: Motion scales to .97 (site.js); without it the button dips 1 px. */
.btn{position:relative; isolation:isolate; overflow:hidden; display:inline-flex; align-items:center; justify-content:center; gap:14px; min-height:54px; padding:0 22px 0 26px; border:1px solid transparent; border-radius:var(--r); font:600 15px/1 var(--sans); letter-spacing:.01em; text-decoration:none; white-space:nowrap; cursor:pointer; transition:color .35s var(--ease), border-color .35s var(--ease), background-color .35s var(--ease)}
.btn::before{content:""; position:absolute; inset:0; z-index:-1; background:var(--teal-light); transform:scaleY(0); transform-origin:bottom center; transition:transform .35s var(--ease)}
.btn:focus-visible::before{transform:scaleY(1)}
.btn .go{position:relative; display:inline-flex; width:18px; height:18px; overflow:hidden}
.btn .go .i{position:absolute; inset:0; width:18px; height:18px; transition:transform .35s var(--ease)}
.btn .go .i + .i{transform:translateX(-140%)}
.btn:focus-visible .go .i:first-child{transform:translateX(140%)}
.btn:focus-visible .go .i + .i{transform:translateX(0)}
.btn-primary{background:var(--ink); color:var(--bg)}
.btn-secondary{background:transparent; color:var(--ink); border-color:var(--edge)}
.btn-secondary::before{background:var(--ink)}
.btn-secondary:focus-visible{color:var(--bg); border-color:var(--ink)}
html:not(.has-motion) .btn:active{transform:translateY(1px)}
.cta-row{display:flex; flex-wrap:wrap; align-items:center; gap:var(--s3) var(--s6)}

/* Text links: a quiet hairline at rest; on hover or focus the full underline draws in from the left. */
.text-link{--u:var(--line-strong); display:inline-flex; align-items:center; gap:10px; min-height:44px; color:var(--ink); font-weight:600; text-decoration:none; background:linear-gradient(currentColor, currentColor) 0 calc(100% - 9px) / 0 1px no-repeat, linear-gradient(var(--u), var(--u)) 0 calc(100% - 9px) / 100% 1px no-repeat; transition:background-size .35s var(--ease), color .2s var(--ease)}
.text-link:focus-visible{background-size:100% 1px, 100% 1px}
.text-link .i{width:18px; height:18px; color:var(--accent); transition:transform .35s var(--ease)}
.text-link:focus-visible .i{transform:translateX(4px)}
.after-link{margin-top:var(--s6)}
/* Hover only where a pointer truly hovers: on touch a tap would leave the fill stuck on. */
@media (hover:hover) and (pointer:fine){
  .btn:hover::before{transform:scaleY(1)}
  .btn:hover .go .i:first-child{transform:translateX(140%)}
  .btn:hover .go .i + .i{transform:translateX(0)}
  .btn-secondary:hover{color:var(--bg); border-color:var(--ink)}
  .text-link:hover{background-size:100% 1px, 100% 1px}
  .text-link:hover .i{transform:translateX(4px)}
}

/* ---------- Navigation: a flat floating bar, one line at desktop (W3C APG disclosure below 1024 px) ---------- */
/* The bar's palette lives in --n-* so one block can retone it. */
.site-header{--n-bg:var(--bg); --n-line:var(--line); --n-edge:var(--edge); --n-ink:var(--ink); --n-ink-2:var(--ink-2); --n-dim:var(--muted); --n-acc:var(--teal-light); --n-on:var(--bg); position:fixed; top:var(--nav-top); left:0; right:0; z-index:50; pointer-events:none}
.nav-bar{position:relative; display:flex; align-items:center; gap:var(--s5); width:min(100% - 2 * var(--gutter) + 24px, var(--max) + 24px); min-height:var(--nav-h); margin-inline:auto; padding:0 6px 0 14px; border:1px solid transparent; border-radius:var(--r); pointer-events:auto; transition:background-color .35s var(--ease), border-color .35s var(--ease)}
/* Solid once the page has moved (site.js watches a sentinel, no scroll listener), while the menu is
   open, and always without JavaScript. Opaque, not frosted. */
.is-solid .nav-bar, .menu-open .nav-bar, html:not(.js) .nav-bar{background:var(--n-bg); border-color:var(--n-line)}
.brand{display:inline-flex; align-items:center; flex:none; color:var(--ink); padding:var(--s2) 0}
.site-header .brand{min-height:44px; color:var(--n-ink); transition:color .35s var(--ease)}
.brand .logo{height:27px; width:auto}
.menu-toggle{display:none; margin-left:auto; align-items:center; gap:10px; min-height:44px; padding:0 var(--s4) 0 14px; background:transparent; color:var(--n-ink); border:1px solid var(--n-edge); border-radius:var(--r); font:600 15px/1 var(--sans); letter-spacing:.01em; cursor:pointer; transition:background-color .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease)}
.menu-toggle .i{width:18px; height:18px}
.menu-toggle .i-close, .menu-toggle[aria-expanded="true"] .i-menu{display:none}
.menu-toggle[aria-expanded="true"] .i-close{display:block}
.menu-toggle[aria-expanded="true"]{background:var(--ink); color:var(--bg); border-color:var(--ink)}
.site-nav{position:relative; display:flex; align-items:center; gap:var(--s4); margin-left:auto}
/* Index figures (00 Home to 04 Corporate) before the names; the alt text after the slash keeps them
   out of the accessible name, and browsers without that syntax skip the declaration. */
.site-nav ul{position:relative; display:flex; align-items:center; gap:2px; list-style:none; margin:0; padding:0; counter-reset:nav -1}
.site-nav li{counter-increment:nav}
.site-nav a{position:relative; z-index:1; display:inline-flex; align-items:center; gap:7px; min-height:44px; padding:0 12px; color:var(--n-ink-2); font:500 15px/1 var(--sans); letter-spacing:.005em; text-decoration:none; white-space:nowrap; transition:color .25s var(--ease)}
.site-nav ul a::before{content:counter(nav, decimal-leading-zero) / ""; font:500 11px/1 var(--mono); letter-spacing:0; color:var(--n-dim); transform:translateY(-5px); transition:color .25s var(--ease)}
.site-nav a[aria-current]{color:var(--n-ink)}
.site-nav ul a[aria-current]::before{color:var(--n-acc)}
/* Current marker: a cyan hairline under the item. site.js slides one shared marker with Motion;
   without it each current link draws its own. */
.site-nav ul a[aria-current]::after{content:""; position:absolute; left:12px; right:12px; bottom:7px; height:1px; background:var(--n-acc)}
.has-motion .site-nav ul a[aria-current]::after{display:none}
.nav-ind{position:absolute; left:0; bottom:7px; z-index:2; width:0; height:1px; background:var(--n-acc); pointer-events:none; opacity:0; transition:background-color .35s var(--ease)}
.has-motion .nav-ind.on{opacity:1}
/* The header action: a hairline box whose ink fill rises on hover, like the buttons. */
.site-nav .nav-cta{isolation:isolate; overflow:hidden; gap:10px; margin-left:var(--s2); padding:0 14px 0 16px; color:var(--n-ink); border:1px solid var(--n-edge); border-radius:var(--r); font-weight:600; transition:color .35s var(--ease), border-color .35s var(--ease)}
.site-nav .nav-cta::before{content:""; position:absolute; inset:0; z-index:-1; background:var(--n-ink); transform:scaleY(0); transform-origin:bottom center; transition:transform .35s var(--ease)}
.site-nav .nav-cta .i{width:16px; height:16px; transition:transform .35s var(--ease)}
.site-nav .nav-cta:focus-visible{color:var(--n-on); border-color:var(--n-ink)}
.site-nav .nav-cta:focus-visible::before{transform:scaleY(1)}
.site-nav .nav-cta:focus-visible .i{transform:translate(2px, -2px)}
.site-nav .nav-cta[aria-current]{border-color:var(--n-acc)}
@media (hover:hover) and (pointer:fine){
  .site-nav a:hover{color:var(--n-ink)}
  .site-nav ul a:hover::before{color:var(--n-acc)}
  .site-nav .nav-cta:hover{color:var(--n-on); border-color:var(--n-ink)}
  .site-nav .nav-cta:hover::before{transform:scaleY(1)}
  .site-nav .nav-cta:hover .i{transform:translate(2px, -2px)}
}
.nav-meta{display:none}
.site-header :focus-visible{outline-color:var(--n-acc)}
@media (max-width:1023.98px){
  .nav-bar{width:calc(100% - 2 * var(--gutter) + 16px); padding:0 5px 0 12px}
  .brand .logo{height:25px}
  .js .menu-toggle{display:inline-flex}
  /* The open menu: a sheet attached under the bar, serif links on hairlines, the action and the
     registered office at its foot. A scrim (the header's ::before) dims the page; a tap on it closes. */
  .js .site-header::before{content:""; position:fixed; inset:0; background:rgb(4 8 11 / .7); opacity:0; visibility:hidden; pointer-events:auto; transition:opacity .3s var(--ease), visibility 0s linear .3s}
  .js .site-header.menu-open::before{opacity:1; visibility:visible; transition:opacity .3s var(--ease)}
  .js .site-nav{position:absolute; left:-1px; right:-1px; top:100%; display:none; flex-direction:column; align-items:stretch; gap:0; margin:0; padding:var(--s2) var(--s5) var(--s5); max-height:calc(100svh - var(--nav-top) - var(--nav-h) - var(--s4)); overflow-y:auto; overscroll-behavior:contain; background:var(--bg); border:1px solid var(--line); border-top:0; border-radius:0 0 var(--r) var(--r)}
  .js .site-nav.is-open{display:flex}
  .js .menu-open .nav-bar{border-bottom-color:var(--line); border-radius:var(--r) var(--r) 0 0}
  .js .site-nav ul{flex-direction:column; align-items:stretch; gap:0}
  .js .site-nav ul li{border-bottom:1px solid var(--line)}
  .js .site-nav ul a{display:flex; min-height:64px; padding:0; gap:var(--s4); font:400 clamp(1.875rem, 1.3rem + 2.6vw, 2.75rem)/1 var(--serif); letter-spacing:-.01em; color:var(--ink)}
  .js .site-nav ul a::before{flex:none; width:24px; font-size:12px; transform:none}
  .js .site-nav ul a[aria-current]::after{display:block; left:auto; right:0; top:50%; bottom:auto; width:28px; height:1px}
  .js .nav-ind{display:none}
  .js .site-nav .nav-cta{justify-content:space-between; min-height:56px; margin:var(--s5) 0 0; padding:0 18px 0 20px; font:600 16px/1 var(--sans); background:var(--ink); color:var(--bg); border-color:var(--ink)}
  .js .site-nav .nav-cta::before{background:var(--teal-light)}
  .js .nav-meta{display:flex; flex-wrap:wrap; justify-content:space-between; gap:var(--s1) var(--s4); margin-top:var(--s5)}
  .nav-meta .caps{font-size:12px}
  /* While the sheet is open the page behind it stays still (site.js sets .nav-lock on the root);
     the stable gutter keeps a classic scrollbar's width, so nothing shifts as it goes. */
  html{scrollbar-gutter:stable}
  html.nav-lock{overflow:hidden}
  /* Without JavaScript the links wrap onto several lines: the header takes its place in the flow
     instead of overlaying the page head (whose padding assumes a one-line bar). */
  html:not(.js) .site-header{position:static; padding-top:var(--nav-top)}
  html:not(.js) .nav-bar{flex-wrap:wrap; padding:var(--s2) var(--s3)}
  html:not(.js) .site-nav, html:not(.js) .site-nav ul{flex-wrap:wrap; margin-left:0}
}
/* Landscape phones: the links in two columns, so the action stays in view without an inner scroll. */
@media (max-width:1023.98px) and (max-height:500px){
  .js .site-nav{padding-top:var(--s1)}
  .js .site-nav ul{display:grid; grid-template-columns:1fr 1fr; column-gap:var(--s6)}
  .js .site-nav ul a{min-height:52px; font-size:1.625rem}
  .js .site-nav .nav-cta{margin-top:var(--s4)}
  .js .nav-meta{display:none}
}

/* ---------- Page head: opens every detail page ---------- */
.page-head{position:relative; padding:calc(var(--nav-top) + var(--nav-h) + clamp(64px, 9vw, 160px)) 0 clamp(56px, 6vw, 112px); border-bottom:1px solid var(--line-strong)}
.page-head .shell{display:grid; grid-template-columns:minmax(0, 8fr) minmax(0, 4fr); gap:var(--s6) var(--s8); align-items:end}
.page-head h1{max-width:14ch}
/* The lede reads as a caption column: a structural rule above it. */
.page-head .lede{padding-top:var(--s4); border-top:1px solid var(--line-strong); font-size:var(--fs-lead); line-height:1.6; max-width:44ch; color:var(--ink-2)}
.page-head .crumb{grid-column:1 / -1; margin-bottom:var(--s3)}
@media (max-width:899.98px){
  .page-head{padding:calc(var(--nav-top) + var(--nav-h) + var(--s8)) 0 var(--s8)}
  .page-head .shell{grid-template-columns:1fr}
}

/* ---------- Generic sections (detail pages) ---------- */
.sec{padding:var(--sec) 0}
.sec + .sec{border-top:1px solid var(--line)}
/* The page head's rule already opens the first section: less air above its heading. */
.page-head + .sec{padding-top:calc(var(--sec) * .7)}
/* A raised band between plain ones, for rhythm on the long detail pages. */
.sec.tint{background:var(--bg-2)}
.sec-head{display:grid; grid-template-columns:minmax(0, 7fr) minmax(0, 5fr); gap:var(--s5) var(--s8); align-items:end}
.sec-head h2{max-width:16ch}
/* The lead fills its column, so its rule meets the shell edge (the column keeps the measure). */
.sec-head .lead{margin:0 0 .35em; padding-top:var(--s4); border-top:1px solid var(--line-strong); max-width:none}
@media (max-width:899.98px){ .sec-head{grid-template-columns:1fr} }
.lead{margin-top:var(--s5); font-size:var(--fs-lead); line-height:1.6; max-width:52ch; color:var(--ink-2)}
.note{font-size:var(--fs-small); line-height:1.6; color:var(--ink-2); max-width:62ch}

/* Numbered checklist: serif figures, a structural rule on top, hairlines between items. */
.checklist{list-style:none; margin:var(--s7) 0 0; padding:0; counter-reset:item; display:grid; gap:0 var(--s8); border-top:1px solid var(--line-strong)}
.checklist li{counter-increment:item; display:grid; grid-template-columns:60px minmax(0, 1fr); gap:var(--s4); align-items:baseline; padding:var(--s5) 0; border-bottom:1px solid var(--line); color:var(--fg)}
.checklist li::before{content:counter(item, decimal-leading-zero); font:400 2rem/1 var(--serif); letter-spacing:-.01em; color:var(--accent)}
@media (min-width:900px){ .checklist.cols-2{grid-template-columns:1fr 1fr} }
@media (max-width:599.98px){ .checklist li{grid-template-columns:44px minmax(0, 1fr); gap:var(--s3)} .checklist li::before{font-size:1.75rem} }

/* What the company does not claim or perform. */
.not-list{list-style:none; margin:var(--s7) 0 0; padding:0; display:grid; gap:0 var(--s8); border-top:1px solid var(--line-strong)}
.not-list li{display:grid; grid-template-columns:24px minmax(0, 1fr); gap:var(--s3); padding:var(--s5) 0; border-bottom:1px solid var(--line)}
.not-list .i{margin-top:3px; color:var(--ink-2)}
@media (min-width:900px){ .not-list{grid-template-columns:1fr 1fr} }

/* Principles: numbered serif statements in two columns. */
.principles{display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:0 var(--s8); margin-top:var(--s7); border-top:1px solid var(--line-strong); counter-reset:pr}
.principle{counter-increment:pr; display:grid; grid-template-columns:64px minmax(0, 1fr); gap:var(--s3) var(--s4); align-content:start; padding:var(--s6) 0 var(--s7); border-bottom:1px solid var(--line)}
.principle::before{content:counter(pr, decimal-leading-zero); grid-row:span 2; font:italic 400 2.25rem/1 var(--serif); color:var(--accent)}
.principle h3{font:400 var(--fs-h4)/1.1 var(--serif); letter-spacing:-.01em}
.principle p{max-width:52ch; color:var(--ink-2)}
@media (max-width:767.98px){ .principles{grid-template-columns:1fr} }

/* Emphasis: one sentence between structural rules, full-width rules, text held to a reading measure.
   The condensed serif is kept for statements of two lines or less; a long one reads in the sans. */
.statement{margin-top:var(--s7); padding:var(--s6) max(0px, 100% - 58ch) var(--s6) 0; border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); color:var(--ink); font:400 clamp(1.1875rem, 1rem + .6vw, 1.5rem)/1.55 var(--sans); letter-spacing:-.005em; max-width:none}

/* Closing band on the detail pages: the brand's deep navy field, a large serif line, the actions. */
.cta-band{padding:var(--sec) 0; background:var(--deep); border-top:1px solid var(--line-strong)}
.cta-grid{display:grid; grid-template-columns:minmax(0, 1fr) auto; gap:var(--s6) var(--s8); align-items:end}
.cta-grid h2{max-width:18ch; font-size:clamp(2.5rem, 1.5rem + 3.4vw, 5.25rem)}
.cta-grid p{margin-top:var(--s4); max-width:48ch; color:var(--ink-2)}
.cta-actions{display:flex; flex-wrap:wrap; gap:var(--s3)}
@media (max-width:899.98px){ .cta-grid{grid-template-columns:1fr; align-items:start} }
@media (max-width:479.98px){ .cta-actions .btn{flex:1 1 100%} }

/* ---------- Footer: brand and contact, an index of the pages, the notice; the legal line in mono ---------- */
.site-footer{position:relative; padding:var(--sec) 0 var(--s6); border-top:1px solid var(--line-strong); font-size:var(--fs-small); color:var(--fg)}
.f-top{display:grid; grid-template-columns:minmax(0, 4fr) minmax(0, 3fr) minmax(0, 5fr); gap:var(--s7) var(--s8)}
/* Brand at the top of its column, direct contact anchored to the foot of the row. */
.f-brand{display:flex; flex-direction:column; align-items:flex-start; gap:var(--s4)}
.f-brand .brand{padding:0}
.f-brand .brand .logo{height:40px}
.f-brand p{color:var(--ink-2); max-width:30ch}
.f-contact{display:grid; gap:var(--s2); margin-top:auto; padding-top:var(--s5)}
.f-contact a{justify-self:start; display:inline-flex; align-items:center; min-height:44px; color:var(--ink); font:400 1.5rem/1.2 var(--serif); letter-spacing:-.005em; text-decoration:underline; text-decoration-color:var(--line-strong); text-decoration-thickness:1px; text-underline-offset:5px; overflow-wrap:anywhere; transition:text-decoration-color .25s var(--ease)}
.f-h{font:600 12px/1.3 var(--sans); letter-spacing:.18em; text-transform:uppercase; color:var(--ink-2); padding-bottom:var(--s3); margin-bottom:0; border-bottom:1px solid var(--line-strong)}
/* Pages, not sections: no index figures here, so no number ever means two things. */
.f-nav ul{list-style:none; margin:0; padding:0}
.f-nav li{border-bottom:1px solid var(--line)}
.f-nav a{display:flex; align-items:center; min-height:48px; padding:var(--s2) 0; text-decoration:none; color:var(--ink); font:400 1.5rem/1.1 var(--serif); letter-spacing:-.005em; transition:color .25s var(--ease)}
.f-nav a:focus-visible{color:var(--accent)}
.f-notice p{color:var(--ink-2); max-width:68ch; font-size:14px; line-height:1.65}
.f-notice .f-h{margin-bottom:var(--s4)}
.f-notice p + p{margin-top:var(--s3)}
.legal{display:flex; flex-wrap:wrap; align-items:center; gap:var(--s2) var(--s6); margin-top:var(--s9); padding-top:var(--s5); border-top:1px solid var(--line-strong); font:400 13px/1.5 var(--mono); color:var(--ink-2)}
.legal > :last-child{margin-left:auto}
.legal a{display:inline-flex; align-items:center; min-height:44px; color:var(--ink); text-decoration:underline; text-decoration-color:var(--line-strong); text-underline-offset:4px}
@media (hover:hover) and (pointer:fine){
  .f-contact a:hover, .legal a:hover{text-decoration-color:var(--accent)}
  .f-nav a:hover{color:var(--accent)}
}
@media (max-width:1023.98px){ .f-top{grid-template-columns:1fr 1fr} .f-notice{grid-column:1 / -1} }
@media (max-width:599.98px){
  .f-top{grid-template-columns:1fr; gap:var(--s8)}
  .legal{flex-direction:column; align-items:flex-start; gap:var(--s1); margin-top:var(--s8)}
  .legal > :last-child{margin-left:0}
}

/* Motion gate: hidden only while the head script's .intro class is present (lifted by site.js or a timer). */
.intro [data-enter], .intro [data-anim]{opacity:0}
.top-sentinel{position:absolute; top:0; left:0; width:1px; height:48px; pointer-events:none; visibility:hidden}
@media (prefers-reduced-motion:reduce){
  *, *::before, *::after{transition-duration:.01ms !important; animation-duration:.01ms !important; animation-iteration-count:1 !important; scroll-behavior:auto !important}
}
@media print{
  *{-webkit-print-color-adjust:exact; print-color-adjust:exact}
  .site-header{position:absolute}
  .ix-screen{display:none !important}
  [data-enter], [data-anim], [data-rise], [data-rise] > *{opacity:1 !important; transform:none !important}
}

/* ---------- Section heads on Home: a serif title, its lead in a caption column beside or below ---------- */
.head{display:grid; grid-template-columns:minmax(0, 7fr) minmax(0, 5fr); gap:var(--s5) var(--s8); align-items:end; padding-bottom:var(--s7)}
/* Wide enough that each .ln line mask holds one line; the author sets the breaks with .ln. */
.head h2{max-width:16ch}
.head h2 .it{font-style:italic}
.head .lead{margin:0 0 .4em; padding-top:var(--s4); border-top:1px solid var(--line-strong); max-width:none}
@media (max-width:899.98px){ .head{grid-template-columns:1fr} }

/* ---------- Register: label and value rows on hairlines (corporate record) ---------- */
.register{margin-top:var(--s7); border-top:1px solid var(--line-strong)}
.register > div{display:grid; grid-template-columns:minmax(0, 18rem) minmax(0, 1fr); gap:var(--s5); align-items:baseline; padding:var(--s4) 0; border-bottom:1px solid var(--line)}
.register dt{font:600 12px/1.6 var(--sans); letter-spacing:.16em; text-transform:uppercase; color:var(--ink-2)}
.register dd{color:var(--ink); font-weight:500; text-wrap:balance}
@media (max-width:699.98px){ .register > div{grid-template-columns:1fr; gap:var(--s1)} }
.record-note{margin-top:var(--s6); max-width:68ch}

/* ---------- Page list (404): an index of the pages, serif names on hairlines ---------- */
.page-list{list-style:none; margin:0; padding:0; border-top:1px solid var(--line-strong); max-width:52rem}
.page-list li{border-bottom:1px solid var(--line)}
.page-list .text-link{display:flex; align-items:center; gap:var(--s5); min-height:80px; font:400 clamp(1.75rem, 1.3rem + 1.6vw, 2.5rem)/1 var(--serif); letter-spacing:-.01em; background:none}
.page-list .text-link .i{width:22px; height:22px; margin-left:auto}
.page-list .text-link:focus-visible{color:var(--accent)}
@media (hover:hover) and (pointer:fine){ .page-list .text-link:hover{color:var(--accent)} }

/* ---------- Credits ---------- */
.credit-list{margin:var(--s3) 0 0; padding-left:1.1em}
.credit-list li + li{margin-top:var(--s2)}
.credits{margin-top:var(--s6); border-top:1px solid var(--line-strong)}
.credits > div{display:grid; grid-template-columns:minmax(0, 14rem) minmax(0, 1fr); gap:var(--s5); padding:var(--s5) 0; border-bottom:1px solid var(--line)}
.credits dt{font:400 1.5rem/1.2 var(--serif); color:var(--ink)}
.credits dd p + p{margin-top:var(--s2)}
.credits a{color:var(--accent); overflow-wrap:anywhere}
@media (max-width:699.98px){ .credits > div{grid-template-columns:1fr; gap:var(--s2)} }

/* Home sections: shared vertical rhythm. Clipped sideways so nothing that bleeds past the screen
   edge (map labels, cropped rings) can widen the page; clip keeps position:sticky working.
   Each side reads --sec-t / --sec-b (default --sec), so pacing is set per boundary by class. */
.lsec{position:relative; padding:var(--sec-t, var(--sec)) 0 var(--sec-b, var(--sec)); overflow-x:clip}
/* Home pacing: regular at most boundaries; tight from the statement into the plates (its bottom
   edge reads --sec in motion.css), generous under contact, where the bezel horizon fills it
   (corporate.css). */
.lsec.say{--sec:var(--sec-s)}
.say + .lsec{--sec-t:var(--sec-s)}

/* ===== src/css/motion.css ===== */
/* Motion system (landing.js): line masks, the scroll-lit statement and the closing rail.
   Owner: motion workstream. Nothing here hides content: every start state is set by the script
   that also plays it, so without JavaScript, without Motion or under reduced motion the page
   shows everything at rest. Timing (landing.js): entrances 0.7 to 0.9 s on --ease, stagger
   70 to 80 ms; wipes on --ease-io; scroll-linked effects end at rest once they have played. */

/* Line masks: each .ln is a block whose words rise from behind its own lower edge. The padding
   keeps italic descenders inside the mask; the negative margin keeps the line spacing. */
.ln{display:block; overflow:hidden; padding-bottom:.14em; margin-bottom:-.14em}
.ln > span{display:inline-block}

/* ---------- Statement: one sentence, lit word by word as it passes through the screen ---------- */
/* Spacing follows the section rhythm (--sec) and is deliberately uneven: a clear break after the
   hero, a short step from the sentence to its particulars, and a short hand-off into What we
   source (the particulars' hairlines close the block, so it needs no full section gap below). */
.say{padding:calc(var(--sec) * .75) 0 calc(var(--sec) * .4)}
@media (max-width:699.98px){ .say{padding-top:max(var(--s7), calc(var(--sec) * .5))} }
.say-text{max-width:17em; font:400 clamp(2.5rem, 1.1rem + 5.2vw, 8.25rem)/1.02 var(--serif); letter-spacing:-.02em; color:var(--ink); text-wrap:balance}
/* One sentence per line group: source, markets, hub. */
.say-text > span, .say-text > [aria-hidden] > span{display:block}
.say-text em{font-style:italic}
.say-text .accent{color:var(--accent)}
/* landing.js keeps the whole sentence for assistive technology in a hidden copy; copying the
   text should give the visible words once. */
.say-text .sr-only{-webkit-user-select:none; user-select:none}
.say-meta{display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:var(--s5); margin-top:clamp(40px, 4.5vw, 88px); border-top:1px solid var(--line-strong)}
.say-meta div{display:grid; align-content:start; gap:var(--s2); padding-top:var(--s5)}
.say-meta dt{font:600 12px/1.3 var(--sans); letter-spacing:.18em; text-transform:uppercase; color:var(--ink-2)}
.say-meta dd{font:400 clamp(1.25rem, 1.1rem + .4vw, 1.5rem)/1.25 var(--serif); color:var(--ink)}
.say-meta .num{font:400 1.0625rem/1.5 var(--mono)}
@media (max-width:699.98px){
  .say-meta{grid-template-columns:1fr; gap:0}
  .say-meta div{padding:var(--s4) 0; border-bottom:1px solid var(--line)}
}

/* ---------- Closing rail: the places of the commercial focus in one endless line ---------- */
.rail{position:relative; overflow:hidden; padding:clamp(40px, 5vw, 88px) 0; border-top:1px solid var(--line); font:400 clamp(4rem, 2rem + 8vw, 11rem)/1 var(--serif); letter-spacing:-.02em; color:var(--ink); -webkit-user-select:none; user-select:none}
.rail-track{display:flex; width:max-content}
.has-motion .rail-track{will-change:transform}
.rail-set{display:flex; align-items:center; flex:none}
.rail-item{display:inline-flex; align-items:center; gap:.3em; padding-right:.3em; white-space:nowrap}
/* The second voice: solid italic in a muted ink (a hairline outline shimmers while it moves). */
.rail-item:nth-child(even){font-style:italic; color:color-mix(in oklab, var(--ink) 42%, var(--bg))}
/* Separator: a meridian mark, the brand's own sign (a globe crossed by its meridian). */
.rail-mark{width:.32em; height:.32em; flex:none; overflow:visible; fill:none; stroke:var(--teal-light); stroke-width:1.5; stroke-linecap:round}
.rail-mark > *{vector-effect:non-scaling-stroke}
.rail::before, .rail::after{content:""; position:absolute; top:0; bottom:0; z-index:1; width:var(--gutter); pointer-events:none}
.rail::before{left:0; background:linear-gradient(90deg, var(--bg), transparent)}
.rail::after{right:0; background:linear-gradient(-90deg, var(--bg), transparent)}

@media print{
  [data-rise] > *, .ln > span, .say-text, .say-text .w, .rail-track{opacity:1 !important; transform:none !important}
  [data-lift]{clip-path:none !important}
}

/* ===== src/css/hero.css ===== */
/* Home hero: composition, the globe (globe.js), its rings and labels, and the arrival screen.
   Owner: hero workstream. */

/* ---------- Arrival: the first visit of a session (head script adds .ix; CSS runs it, script can skip it) ----------
   0 to 1.15 s: the meridian and the bar draw, the counter runs 000 to 055 (the office's meridian),
   three words follow one another without overlapping; 1.15 to 1.70 s: the screen lifts. */
@property --ixn{syntax:"<integer>"; inherits:false; initial-value:0}
.ix-screen{display:none}
.ix .ix-screen{position:fixed; inset:0; z-index:90; display:grid; grid-template-rows:auto 1fr auto; padding:clamp(20px, 3vw, 40px) var(--gutter); background:var(--bg); color:var(--ink); pointer-events:auto; animation:ix-out .55s var(--ease-io) 1.15s both}
.ix-top{display:flex; justify-content:space-between; gap:var(--s5); animation:ix-fade .3s var(--ease) both}
.ix-top > :last-child{text-align:right}
.ix-mid{position:relative; display:grid; place-items:center}
.ix-meridian{position:absolute; left:50%; top:-12vh; bottom:-12vh; width:1px; background:linear-gradient(transparent, var(--teal-light) 18%, var(--teal-light) 82%, transparent); transform-origin:top center; animation:ix-draw 1.1s var(--ease-io) both}
.ix-words{position:relative; display:grid; font:italic 400 clamp(3rem, 1.5rem + 5vw, 6.5rem)/1 var(--serif); letter-spacing:-.01em}
/* One word at a time: each owns a 0.34 s slot (about 0.2 s fully shown) and the next starts 0.02 s
   after it has gone; the last one stays through the lift. */
.ix-words span{grid-area:1 / 1; padding:0 .25em; background:var(--bg); text-align:center; opacity:0; animation:ix-word .34s linear both}
.ix-words span:nth-child(1){animation-delay:.08s}
.ix-words span:nth-child(2){animation-delay:.44s}
.ix-words span:nth-child(3){animation-delay:.8s; animation-name:ix-word-last}
.ix-foot{display:flex; justify-content:space-between; align-items:flex-end; gap:var(--s5)}
.ix-count{font:italic 400 clamp(4.5rem, 2rem + 9vw, 11rem)/.85 var(--serif); letter-spacing:-.02em; font-variant-numeric:tabular-nums; counter-reset:ixn var(--ixn); animation:ix-count 1.05s var(--ease-io) .05s both}
.ix-count::before{content:"0" counter(ixn, decimal-leading-zero)}
.ix-count small{font-size:.42em; font-style:normal; vertical-align:top; margin-left:.05em; color:var(--accent)}
.ix-bar{position:absolute; left:0; right:0; bottom:0; height:1px; background:var(--teal-light); transform-origin:left center; animation:ix-draw-x 1.1s var(--ease-io) both}
@keyframes ix-fade{from{opacity:0}}
@keyframes ix-draw{from{transform:scaleY(0)}}
@keyframes ix-draw-x{from{transform:scaleX(0)}}
@keyframes ix-count{from{--ixn:0} to{--ixn:55}}
@keyframes ix-word{0%{opacity:0; transform:translateY(40%); animation-timing-function:cubic-bezier(.22, 1, .36, 1)} 24%{opacity:1; transform:none} 80%{opacity:1; transform:none; animation-timing-function:cubic-bezier(.55, 0, 1, .45)} 100%{opacity:0; transform:translateY(-30%)}}
@keyframes ix-word-last{0%{opacity:0; transform:translateY(40%); animation-timing-function:cubic-bezier(.22, 1, .36, 1)} 24%, 100%{opacity:1; transform:none}}
/* An explicit start: from its initial "none" a clip-path cannot interpolate and would cut at 50%. */
@keyframes ix-out{from{clip-path:inset(0 0 0 0)} to{clip-path:inset(0 0 100% 0); visibility:hidden}}
.ix-done .ix-screen{display:none}

/* ---------- Home hero: a poster around the globe ----------
   Geometry lives in custom properties. Values holding 100% are width relative (the hero's width), so
   they are only used in inline-axis properties and in margins, which resolve against width too.
   --F headline size, bound by width and by height: the copy block is 257 px plus 3.6 F tall, and the
       two height terms are that block solved against the paddings, so eyebrow, four lines, summary
       and actions always fit the first screen.
   --D globe diameter: 1.16 screen heights at most, and no wider than the room right of the copy. The
       box shows 85.8% of its width (13% bleeds off the right edge, 1.2% is ring margin). The ring's
       leftmost point sits level with the last headline line (4.2 F wide) or the summary, so that is
       what it clears; the wider first line sits where the curve has already turned away.
   --gt globe top: always clear of the navigation; --gy centres the globe on tall screens instead. */
.hero{
  --nav-b:calc(var(--nav-top) + var(--nav-h));
  --left:max(var(--gutter), (100% - var(--max)) / 2);
  --F:clamp(3.2rem, min(9.8vw, 25.5svh - 92px, 27svh - 105px), 12.5rem);
  --sw:31rem;
  --gap:clamp(20px, 2.4vw, 64px);
  --gt:calc(var(--nav-b) + clamp(20px, 3.6svh, 52px));
  --D:min(116svh, (100% - var(--left) - max(var(--F) * 4.2, var(--sw)) - var(--gap)) / .858);
  --gy:max(var(--gt), (100svh - var(--D)) / 2);
  position:relative; isolation:isolate; overflow:clip; min-height:max(100svh, 640px); display:grid; align-items:center;
  padding:calc(var(--nav-b) + clamp(16px, 2.6svh, 48px)) 0 clamp(48px, 5.5svh, 96px);
}
/* The foot of the poster dissolves into the page, so the section edge never cuts the globe hard. */
.hero::after{content:""; position:absolute; left:0; right:0; bottom:0; z-index:1; height:clamp(96px, 17svh, 240px); background:linear-gradient(rgb(9 17 23 / 0), rgb(9 17 23 / .72) 55%, var(--bg)); pointer-events:none}
.hero-copy{position:relative; z-index:2}
.hero-title{margin-top:var(--s5); font-size:var(--F); line-height:.9; letter-spacing:-.022em}
.hero-title .it{font-style:italic}
.hero-title .accent{font-style:italic; color:var(--accent)}
.hero-sub{margin-top:var(--s5); max-width:var(--sw); font-size:var(--fs-lead); line-height:1.6; color:var(--ink-2)}
.hero-sub strong{display:block; font-weight:600; color:var(--ink)}
.hero .cta-row{margin-top:var(--s6)}

/* The globe: the kinetic object. --tilt and --story are read by globe.js (view latitude, and the
   longitude the slow part of the turn is centred on); --out is where hero.js takes the box as the
   hero scrolls away. The rings turn on their own clocks. */
.hero-globe{--tilt:17; --story:70; --out:translate3d(-4%, 24%, 0) scale(.88); container:globe / inline-size; position:absolute; z-index:1; top:0; right:calc(var(--D) * -.13); width:var(--D); aspect-ratio:1; margin-top:var(--gy); pointer-events:none}
/* A cold light behind the globe, falling off to the ink field. */
.hero-globe::before{content:""; position:absolute; inset:-16%; border-radius:50%; background:radial-gradient(closest-side, color-mix(in oklab, var(--navy-deep) 78%, transparent), transparent)}
.globe{position:relative; width:100%; height:100%}
.globe canvas{position:absolute; inset:0; width:100%; height:100%}
/* The disc before the canvas has drawn, and without JavaScript. */
.globe::before{content:""; position:absolute; inset:5%; border-radius:50%; background:radial-gradient(circle at 32% 28%, var(--globe-ocean-lit), var(--globe-ocean) 55%, var(--globe-ocean-edge)); box-shadow:0 0 0 1px rgb(127 211 232 / .16)}
.globe.is-live::before{background:none}
.ring{position:absolute; inset:0; width:100%; height:100%; overflow:visible; fill:none; stroke:rgb(214 238 245 / .2); vector-effect:non-scaling-stroke}
.ring text{fill:rgb(214 238 245 / .45); stroke:none; font:400 11px/1 var(--mono); letter-spacing:.08em}
.ring-inner{stroke:rgb(214 238 245 / .12)}
@media (prefers-reduced-motion:no-preference){
  .ring-outer{animation:turn 240s linear infinite}
  .ring-inner{animation:turn 170s linear infinite reverse}
}
@keyframes turn{to{transform:rotate(360deg)}}
/* Labels follow their places (globe.js); each takes the side that keeps it on screen, clear of the copy
   and of the other labels. Same language as the geography plate: a serif place name, a small caps
   role line and a hairline on the side facing the place; a halo of the field colour keeps them
   legible where they cross the cyan source countries. */
.globe-labels{position:absolute; inset:0}
.g-lbl{position:absolute; left:0; top:0; visibility:hidden; opacity:0; will-change:transform, opacity}
.g-lbl > span{position:absolute; left:14px; top:-12px; display:block; padding-left:10px; border-left:1px solid var(--line-strong); font:400 1.25rem/1.1 var(--serif); color:var(--ink); white-space:nowrap; text-shadow:0 0 2px var(--bg), 0 0 8px var(--bg), 0 0 16px rgb(9 17 23 / .8)}
.g-lbl[data-side="left"] > span{left:auto; right:14px; padding:0 10px 0 0; border-left:0; border-right:1px solid var(--line-strong); text-align:right}
/* Dubai's label clears the hub's ring; it sits west of the hub by default, between the diagonal routes
   to Europe and Africa, leaving the east side to the routes from China and Vietnam and their labels. */
.g-lbl[data-at="dubai"] > span{left:22px}
.g-lbl[data-at="dubai"][data-side="left"] > span{left:auto; right:22px}
.g-lbl small{display:block; margin-top:4px; font:600 11px/1.3 var(--sans); letter-spacing:.14em; text-transform:uppercase; color:var(--ink-2)}
/* A small globe (landscape phones, small windows): the names alone, a size down, as on the plate. */
@container globe (max-width:560px){
  .g-lbl > span{top:-10px; font-size:1.0625rem}
  .g-lbl small{display:none}
}
.intro .hero-globe{opacity:0}

/* Left margin: a meridian rule. Its tick sits on the registered office's parallel as the globe draws
   it (25.16 N, 8.16 degrees above the view's centre latitude: 0.436 of the globe box from its top), so
   Dubai crosses the tick whenever the readout below passes 55.3 E. A faint ring leaves the tick on
   each hand-over at Dubai (globe.js keeps the two on one clock). The rule spans the hero, so its
   children resolve the width-relative geometry against the hero. */
.hero-rail{position:absolute; inset:0; z-index:2; pointer-events:none; --x:calc(var(--left) - clamp(26px, 2.4vw, 56px))}
.hero-rail::before{content:""; position:absolute; left:var(--x); width:1px; top:calc(var(--nav-b) + clamp(16px, 2.6svh, 48px)); bottom:clamp(28px, 3.6svh, 48px); background:linear-gradient(transparent, var(--line-strong) 8%, var(--line-strong) 92%, transparent)}
.rail-at{position:absolute; left:var(--x); top:0; width:1px; height:1px; margin-top:calc(var(--gy) + var(--D) * .436)}
.rail-at::before{content:""; position:absolute; left:-4px; top:0; width:9px; height:1px; background:var(--teal-light)}
.rail-at::after{content:""; position:absolute; left:-15px; top:-15px; width:31px; height:31px; border:1px solid var(--teal-light); border-radius:50%; opacity:0}
.rail-at .coord{position:absolute; left:-8px; top:18px; writing-mode:vertical-rl; transform:rotate(180deg); font-size:12px; letter-spacing:.06em; white-space:nowrap}
@media (prefers-reduced-motion:no-preference){ .rail-at::after{animation:rail-ping 4.2s linear infinite} }
@keyframes rail-ping{0%{opacity:.7; transform:scale(.25); animation-timing-function:cubic-bezier(.22, 1, .36, 1)} 70%, 100%{opacity:0; transform:scale(1)}}
/* The globe's instrument: its live central meridian (globe.js), under the globe on the grid's right edge. */
.hero-readout{position:absolute; z-index:2; right:var(--left); bottom:clamp(20px, 3svh, 44px); display:flex; gap:var(--s4); align-items:baseline}
.hero-readout .caps{font-size:12px}
.hero-readout .coord{color:var(--ink); min-width:7ch; text-align:right}
html:not(.js) .hero-readout{display:none}
@media (max-width:1279.98px){
  /* The summary runs to four lines here (one more 32 px line), so the headline gives up the difference. */
  .hero{--sw:26rem; --F:clamp(3.2rem, min(9.4vw, 26svh - 108px), 12.5rem)}
  .hero-rail{display:none}
}

/* ---------- Stacked: portrait phones and tablets, and narrow windows: the globe above the title ----------
   The globe hangs under the navigation with the story on its upper half; the copy starts at its
   equator and the lower half dissolves behind the headline. Its size is what the height leaves once
   the copy fits the first screen with both actions: D = 2 x (height - top - copy) = 200svh - 7.36 F
   - --K, where --K holds the copy's fixed part and the margins (878 px when the actions take two
   rows, under 480 px wide). Landscape phones keep the side by side poster, where the height goes
   further. */
@media (max-width:1199.98px) and (orientation:portrait), (max-width:599.98px){
  .hero{--K:772px; --F:clamp(3rem, 14.6vw, 7.5rem); --D:clamp(260px, min(128vw, 200svh - var(--F) * 7.36 - var(--K)), max(600px, 78vw)); display:block; min-height:auto; padding:calc(var(--nav-b) + 28px + var(--D) / 2) 0 var(--s7)}
  .hero::after{display:none}
  .hero-title{line-height:.92}
  .hero .cta-row{gap:var(--s3) var(--s5)}
  .hero-globe{--tilt:2; --out:translate3d(0, 8%, 0) scale(.96); top:calc(var(--nav-b) + 14px); right:auto; left:calc(50% - var(--D) / 2); margin-top:0}
  .hero-globe::after{content:""; position:absolute; inset:0; background:linear-gradient(transparent 47%, rgb(9 17 23 / .8) 62%, var(--bg) 80%)}
  .g-lbl, .hero-readout, .hero-rail{display:none}
}
@media (max-width:599.98px){ .hero-sub{max-width:30ch} }
@media (max-width:479.98px){ .hero{--K:878px} }
/* Short phones (a phone browser with its bars showing, under 800 px): the same composition sized by
   the height. A tighter rhythm (16, 16, 20 and 4 px) and a headline bound by the height keep both
   actions in the first screen with a few pixels to spare from about 640 px up (measured at 659, 667,
   739 and 780 px); the globe keeps 240 px at least, with the story in view. */
@media (max-width:1199.98px) and (orientation:portrait) and (max-height:799.98px), (max-width:599.98px) and (max-height:799.98px){
  .hero{--K:760px; --F:clamp(2.5rem, min(14.6vw, 7.4svh - 6px), 5.75rem); --D:clamp(240px, 200svh - var(--F) * 7.36 - var(--K), 460px); padding-top:calc(var(--nav-b) + 20px + var(--D) / 2)}
  .hero-title{margin-top:var(--s4)}
  .hero-sub{margin-top:var(--s4)}
  .hero .cta-row{margin-top:20px; row-gap:4px}
}
@media (max-width:399.98px){ .hero .cta-row .btn{flex:1 1 100%} }

@media print{ .hero-globe{opacity:1 !important; transform:none !important} .ix-screen{display:none !important} .hero::after{display:none} }

/* ===== src/css/source.css ===== */
/* What we source: the numbered plates (Home #source and capabilities.html) and the numbered rows
   of the capabilities page. Owner: sourcing workstream. Nothing is ever printed on a photograph:
   numerals, names, words and metadata sit beside the images. materials.js adds the reveals, the
   sideways settle of the name and the clip; without it everything is at rest. */

/* ---------- Plates: an editorial spread on the page grid ----------
   Wide: the numbering device across the top (oversized italic accent numeral, the name, a caps
   label, on a hairline that runs off the page edge), the macro photograph (4 columns) beside the
   main one (8 columns plus the page margin, so it bleeds off the edge) at 2:1, then the words
   beside the metadata. .flip mirrors the photographs. The page margin (--pad) matches .shell;
   100cqw is the page width without the scrollbar. */
.cats{container-type:inline-size; margin-top:clamp(16px, 2vw, 48px)}
.cat{
  --pad:max(var(--gutter), (100cqw - var(--max)) / 2);
  position:relative; display:grid; grid-template-columns:repeat(12, minmax(0, 1fr)); column-gap:var(--s5);
  grid-template-rows:auto auto auto 1fr;
  grid-template-areas:
    "head head head head head head head head head head head head"
    "macro macro macro macro main main main main main main main main"
    "tag tag tag tag tag tag meta meta meta meta meta meta"
    "body body body body body body meta meta meta meta meta meta";
  padding-inline:var(--pad); overflow-x:clip;
}
.cat.flip{
  grid-template-areas:
    "head head head head head head head head head head head head"
    "main main main main main main main main macro macro macro macro"
    "tag tag tag tag tag tag meta meta meta meta meta meta"
    "body body body body body body meta meta meta meta meta meta";
}
.cat + .cat{margin-top:clamp(80px, 6.5vw, 136px)}

/* The numbering device. materials.js slides the name sideways into place with the scroll
   (transform); the hover nudge uses translate, so the two never fight. */
.cat-head{grid-area:head; display:grid; grid-template-columns:auto minmax(0, 1fr) auto; grid-template-areas:"no title label" "rule rule rule"; align-items:baseline; column-gap:clamp(16px, 2.4vw, 48px)}
.cat-no{grid-area:no; overflow:hidden; padding-right:.08em; font:italic 400 clamp(5rem, 1.5rem + 7.6vw, 13rem)/.86 var(--serif); letter-spacing:-.03em; color:var(--accent); font-variant-numeric:lining-nums}
.cat-no > span{display:inline-block}
/* The name stays below the section h2 (hierarchy); the numeral is the dramatic element. */
.cat-title{grid-area:title; margin:0; font:400 clamp(2.5rem, 1.2rem + 3.6vw, 5.5rem)/.94 var(--serif); letter-spacing:-.025em; color:var(--ink); white-space:nowrap; transition:translate .35s var(--ease)}
.cat-title .it{font-style:italic}
.cat-label{grid-area:label; white-space:nowrap}
.cat-rule{grid-area:rule; position:relative; display:block; height:1px; margin:clamp(14px, 1.4vw, 24px) calc(-1 * var(--pad)) clamp(24px, 2.4vw, 44px) 0; background:var(--line-strong); transform-origin:0 50%}
.flip .cat-rule{margin-right:0; margin-left:calc(-1 * var(--pad)); transform-origin:100% 50%}
.cat-rule::after{content:""; position:absolute; inset:0; background:var(--teal-light); transform:scaleX(0); transform-origin:inherit; transition:transform .35s var(--ease)}

/* Photographs: clean, cropped hard (--pos, --zoom: a CSS crop of the file), the main one bleeding
   off the edge. Images sit out of flow, so only the main frame's 2:1 sets the row height and the
   macro frame fills it. One grade for every photograph so the set sits on the near-black page (a
   little less colour, a little more contrast, highlights brought down) and a fixed fine grain. */
.cat-shot{position:relative; isolation:isolate; overflow:hidden; margin:0; background:var(--bg-2)}
.cat-shot picture, .cat-shot .swap, .cat-shot video{position:absolute; inset:0; display:block}
.cat-shot img, .cat-shot video{width:100%; height:100%; object-fit:cover; object-position:var(--pos, 50% 50%); scale:var(--zoom, 1); transform-origin:var(--pos, 50% 50%); filter:brightness(.9) contrast(1.1) saturate(.8); transition:scale .35s var(--ease)}
.cat-shot::after{content:""; position:absolute; inset:0; z-index:1; pointer-events:none; opacity:.08; mix-blend-mode:overlay; background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='2.4 0 0 0 -.7 2.4 0 0 0 -.7 2.4 0 0 0 -.7 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E") 0 0 / 160px 160px}
.cat-main{grid-area:main; aspect-ratio:2 / 1; margin-right:calc(-1 * var(--pad))}
.flip .cat-main{margin-right:0; margin-left:calc(-1 * var(--pad))}
.cat-macro{grid-area:macro}
.cat-main .clip{opacity:0; transition:opacity .6s var(--ease)}
.cat-main .clip.on{opacity:1}
/* The hover photograph exists only for a fine pointer (display:none keeps a lazy image unloaded). */
.cat-shot .swap{display:none}
/* Reveal veil (materials.js adds and removes it): page-coloured, above the grain, it retracts toward the edge. */
.cat-veil{position:absolute; inset:-1px; z-index:2; background:var(--bg); transform-origin:100% 50%; pointer-events:none}
.flip .cat-veil{transform-origin:0 50%}
/* Focus inside a plate (materials.js adds .seen): everything at rest at once, whatever the reveal. */
.cat.seen :is(.cat-tag, .cat-body, .cat-meta > div, .cat-rule, .cat-no > span, .cat-title .ln > span){opacity:1 !important; transform:none !important}
.cat.seen .cat-veil{display:none}

/* Words beside the metadata. */
.cat-tag{grid-area:tag; margin-top:clamp(28px, 3vw, 52px); max-width:24ch; font:400 clamp(1.5rem, 1.05rem + 1.1vw, 2.375rem)/1.14 var(--serif); letter-spacing:-.01em; color:var(--ink); text-wrap:balance}
.cat-body{grid-area:body; display:grid; justify-items:start; gap:var(--s3); margin-top:var(--s4); max-width:58ch}
.cat-body p{color:var(--fg)}
.cat-meta{grid-area:meta; align-self:start; margin-top:clamp(28px, 3vw, 52px); border-top:1px solid var(--line-strong)}
.cat-meta > div{display:grid; grid-template-columns:minmax(0, 10.5rem) minmax(0, 1fr); gap:var(--s2) var(--s4); padding:var(--s3) 0; border-bottom:1px solid var(--line)}
.cat-meta dt{padding-top:3px; font:600 12px/1.5 var(--sans); letter-spacing:.16em; text-transform:uppercase; color:var(--ink-2)}
.cat-meta dd{font-size:15px; line-height:1.55; color:var(--ink)}

/* capabilities.html: the full approved scope as a table under the main photograph. */
.cat.full{
  grid-template-rows:auto;
  grid-template-areas:
    "head head head head head head head head head head head head"
    "macro macro macro macro main main main main main main main main"
    "tag tag tag tag meta meta meta meta meta meta meta meta";
}
.cat.full.flip{
  grid-template-areas:
    "head head head head head head head head head head head head"
    "main main main main main main main main macro macro macro macro"
    "meta meta meta meta meta meta meta meta tag tag tag tag";
}
.full .cat-meta > div{grid-template-columns:minmax(0, 3fr) minmax(0, 5fr); gap:var(--s2) var(--s5); padding:var(--s5) 0}
.full .cat-meta dd{max-width:56ch; font-size:16px; line-height:1.6; color:var(--fg)}
.full .cat-meta div:last-child dd{color:var(--ink-2)}

@media (hover:hover) and (pointer:fine){
  .cat-shot .swap{display:block; opacity:0; transition:opacity .35s var(--ease)}
  .cat:has(.cat-shot:hover) .swap, .cat:focus-within .swap{opacity:1}
  .cat:has(.cat-shot:hover) .cat-main :is(picture img, video){scale:calc(var(--zoom, 1) * 1.03)}
  .cat:is(:hover, :focus-within) .cat-rule::after{transform:scaleX(1)}
}
@media (hover:hover) and (pointer:fine) and (prefers-reduced-motion:no-preference){
  .cat:is(:hover, :focus-within) .cat-title{translate:.14em 0}
}

/* Narrow: recomposed, not shrunk. The numeral and the label on the hairline, the name below on
   two lines, the main photograph edge to edge at 4:5, then the line and the macro photograph side
   by side (the macro bleeds off the side edge), then the words and the metadata. */
@media (max-width:899.98px){
  .cat, .cat.full{
    grid-template-columns:repeat(6, minmax(0, 1fr)); column-gap:var(--s4); grid-template-rows:none;
    grid-template-areas:
      "head head head head head head"
      "main main main main main main"
      "tag tag tag macro macro macro"
      "body body body body body body"
      "meta meta meta meta meta meta";
  }
  .cat.flip, .cat.full.flip{
    grid-template-areas:
      "head head head head head head"
      "main main main main main main"
      "macro macro macro tag tag tag"
      "body body body body body body"
      "meta meta meta meta meta meta";
  }
  .cat-head{grid-template-columns:auto minmax(0, 1fr); grid-template-areas:"no label" "rule rule" "title title"}
  .cat-label{justify-self:end}
  .cat-no{font-size:clamp(4.5rem, 2.4rem + 9vw, 7rem)}
  .cat-rule{margin:var(--s3) calc(-1 * var(--pad)) var(--s4) 0}
  .flip .cat-rule{margin:var(--s3) 0 var(--s4) calc(-1 * var(--pad))}
  .cat-title{margin-bottom:var(--s5); font-size:clamp(2.5rem, 1.5rem + 4vw, 3.5rem); white-space:normal}
  .cat-main, .flip .cat-main{aspect-ratio:4 / 5; margin-inline:calc(-1 * var(--pad))}
  .cat-macro{aspect-ratio:4 / 5; margin:var(--s4) calc(-1 * var(--pad)) 0 0}
  .flip .cat-macro{margin:var(--s4) 0 0 calc(-1 * var(--pad))}
  .cat-tag{align-self:end; margin:0; font-size:clamp(1.375rem, 1.1rem + 1.2vw, 1.75rem); line-height:1.15}
  .cat-body{margin-top:var(--s6)}
  .cat-meta{margin-top:var(--s6)}
  .cat-meta > div, .full .cat-meta > div{grid-template-columns:1fr; gap:var(--s1); padding:var(--s4) 0}
  .cat + .cat{margin-top:var(--s10)}
}
/* Portrait phones: the main photograph's file is already cut to this frame (source.cjs PORTRAIT). */
@media (max-width:599.98px) and (orientation:portrait){ .cat-main picture img{object-position:50% 50%; scale:1} }
/* Tablets: a 4:5 photograph would fill the screen; landscape phones: keep it near one screen. */
@media (min-width:600px) and (max-width:899.98px){ .cat-main, .flip .cat-main{aspect-ratio:3 / 2} }
@media (max-width:899.98px) and (orientation:landscape){ .cat-main, .flip .cat-main{aspect-ratio:2 / 1} .cat-macro{aspect-ratio:4 / 3} }

/* ---------- capabilities.html: numbered rows with the same device ---------- */
.cat-page{margin:0; padding:var(--sec) 0 0}
.src-rows{list-style:none; margin:var(--s8) 0 0; padding:0; border-top:1px solid var(--line-strong)}
.src-rows li{display:grid; grid-template-columns:repeat(12, minmax(0, 1fr)); column-gap:var(--s5); align-items:baseline; padding:var(--s6) 0; border-bottom:1px solid var(--line)}
.src-no{grid-column:1 / span 2; font:italic 400 clamp(2.5rem, 1.7rem + 1.8vw, 3.75rem)/.9 var(--serif); letter-spacing:-.03em; color:var(--accent); font-variant-numeric:lining-nums}
.src-rows h3{grid-column:3 / span 4; font:400 clamp(1.5rem, 1.15rem + .9vw, 2.25rem)/1.1 var(--serif); letter-spacing:-.01em}
.src-rows p{grid-column:7 / span 6; max-width:54ch; color:var(--fg)}
.src-not{list-style:none; margin:var(--s8) 0 0 calc((100% - 11 * var(--s5)) / 12 * 4 + 4 * var(--s5)); padding:0; border-top:1px solid var(--line-strong)}
/* Short statements (one or two lines) in the serif, marked with a cross; below 900 px the sans. */
.src-not li{display:grid; grid-template-columns:48px minmax(0, 1fr); align-items:center; padding:var(--s5) 0; border-bottom:1px solid var(--line); font:400 clamp(1.375rem, 1.1rem + .7vw, 2rem)/1.2 var(--serif); letter-spacing:-.005em; color:var(--ink)}
.src-not .i{width:18px; height:18px; color:var(--ink-2)}
@media (max-width:899.98px){
  .src-rows li{grid-template-columns:56px minmax(0, 1fr); column-gap:var(--s4); row-gap:var(--s2); padding:var(--s5) 0}
  .src-no{grid-column:1; grid-row:1 / span 2; font-size:2.25rem}
  .src-rows h3, .src-rows p{grid-column:2}
  .src-not{margin-left:0}
  .src-not li{grid-template-columns:32px minmax(0, 1fr); align-items:start; padding:var(--s4) 0; font:500 16px/1.55 var(--sans); letter-spacing:0}
  .src-not .i{margin-top:4px; width:16px; height:16px}
}

@media print{
  .cat-veil, .cat-shot::after{display:none}
  .cat-rule, .cat-title, .cat-no > span, .cat-tag, .cat-body, .cat-meta > div, .src-rows > li, .src-not > li{opacity:1 !important; transform:none !important}
}

/* ===== src/css/geo.css ===== */
/* Sourcing geography: the map plate (tools/geo.cjs), its places, labels and live lines (plate.js),
   the index of places with its readout, and the commercial-focus note. Owner: geography workstream.
   The map speaks the hero globe's language: breathing teal sources with cyan points, a ringed hub
   that pulses at each hand-off, soft halos for the markets, thin cyan lines with travelling lights.
   Inside the map, bottom to top: svg (land, fills, lines) < canvas (lights) < places < labels. */

/* ---------- Section: a deep navy field; the map is the dominant plate, the index sits beside it ---------- */
/* Tighter than the other sections, and the field fades in and out over short bands, so the navy
   starts just above the heading and ends just below the caption row. */
.geo{padding-block:calc(var(--sec) * .6); background:linear-gradient(var(--bg), var(--deep) 64px, var(--deep) calc(100% - 64px), var(--bg))}
/* The map takes what the index leaves, but never more than fits under the navigation, so the
   whole plate can be seen at once (1000 / 735 is the plate's aspect ratio). */
.geo-grid{--map-w:clamp(560px, (100svh - 190px) * 1.3605, 100% - 300px - var(--s8)); display:grid; grid-template-columns:minmax(0, var(--map-w)) minmax(0, 1fr); gap:var(--s6) var(--s8); align-items:start}
.plate{position:relative}
/* A cold light over the hub, so the eye lands on Dubai first. Every label is placed inside the
   map box at every width (checked 320 to 1920 px), so clipping only guards the page edge. */
.map{position:relative; isolation:isolate; overflow:clip; aspect-ratio:var(--ar, 1000 / 735); container-type:inline-size; background:radial-gradient(50% 58% at 44.6% 34%, rgb(33 158 188 / .075), transparent 72%)}
/* The plate frame: land is cut at the frame edge like a printed chart. */
.map::after{content:""; position:absolute; inset:0; z-index:4; border:1px solid var(--line-strong); pointer-events:none}
.map svg{position:absolute; inset:0; width:100%; height:100%; overflow:hidden}
.grat{fill:none; stroke:rgb(214 238 245 / .07); stroke-width:.8px; vector-effect:non-scaling-stroke}
.land{fill:var(--globe-land); stroke:rgb(214 238 245 / .16); stroke-width:.6px; vector-effect:non-scaling-stroke; stroke-linejoin:round}
.src-fill{fill:var(--teal); fill-opacity:.56}
.uae-fill{fill:var(--teal-light)}
.route{fill:none; stroke:var(--teal-light); stroke-opacity:.46; stroke-width:1.2px; vector-effect:non-scaling-stroke; stroke-linecap:round}
.flow{position:absolute; inset:0; z-index:1; width:100%; height:100%; pointer-events:none}

/* ---------- Places: fixed-size symbols at every width (the box is the pointer target) ---------- */
.nd{position:absolute; left:var(--x); top:var(--y); z-index:2; width:40px; height:40px; margin:-20px 0 0 -20px; pointer-events:none}
.nd::before, .nd::after{content:""; position:absolute; left:50%; top:50%; border-radius:50%; translate:-50% -50%; transition:scale .35s var(--ease), border-color .35s var(--ease)}
.nd-src::before{width:9px; height:9px; background:var(--teal-light)}
.nd-src::after{width:22px; height:22px; border:1px solid rgb(127 211 232 / .42)}
.nd-hub::before{width:6px; height:6px; background:var(--ink)}
.nd-hub::after{width:18px; height:18px; border:1.5px solid var(--ink)}
.nd-mkt{--halo:clamp(56px, 13cqi, 140px)}
.nd-mkt::before{width:var(--halo); height:var(--halo); background:radial-gradient(closest-side, rgb(127 211 232 / .34), rgb(127 211 232 / .12) 58%, rgb(127 211 232 / 0))}
.nd-mkt::after{width:7px; height:7px; border:1px solid rgb(214 238 245 / .72)}
/* The chosen place opens its ring a little. */
.nd.is-key::after{scale:1.4}
.nd-src.is-key::after{border-color:var(--teal-light)}
.nd-mkt.is-key::after{border-color:var(--ink)}

/* ---------- Labels: a hairline rule, the name in the display serif, the role in small capitals ---------- */
.lbl{--dx:14px; position:absolute; left:var(--x); top:var(--y); z-index:3; translate:var(--dx) -50%; pointer-events:none}
.lbl > span{display:block; padding-left:10px; border-left:1px solid var(--line-strong); font:400 1.375rem/1.1 var(--serif); color:var(--ink); white-space:nowrap; text-shadow:0 0 10px var(--deep), 0 0 3px var(--deep); transition:border-color .35s var(--ease)}
.lbl small{display:block; margin-top:4px; font:600 12px/1.3 var(--sans); letter-spacing:.14em; text-transform:uppercase; color:var(--ink-2)}
.lbl.is-key > span{border-color:var(--teal-light)}
/* Left of the place, rule on the right. */
.lbl-l{translate:calc(-100% - var(--dx)) -50%}
.lbl-l > span{padding:0 10px 0 0; border-left:0; border-right:1px solid var(--line-strong); text-align:right}
/* Past the coast on a leader (China: the label never sits on the teal fill). */
.lbl-far{--dx:7cqi}
.lbl-far::before{content:""; position:absolute; right:100%; top:50%; width:calc(var(--dx) - 9px); border-top:1px solid var(--line-strong)}
/* A flag above the place: the rule drops to the hub ring. */
.lbl-up{--lift:20px; translate:0 calc(-100% - var(--lift))}
.lbl-up::before{content:""; position:absolute; left:0; top:100%; height:calc(var(--lift) - 10px); border-left:1px solid var(--line-strong)}
.lbl-far.is-key::before, .lbl-up.is-key::before{border-color:var(--teal-light)}
/* Roles only where the map is wide enough to carry them; the index always names the roles. */
@container (max-width:879.98px){
  .lbl small{display:none}
  .lbl > span{font-size:1.1875rem}
}
@container (max-width:519.98px){
  .lbl > span{font-size:1.0625rem; padding-left:8px}
  .lbl-l > span{padding:0 8px 0 0}
  .lbl{--dx:11px}
  .lbl-far{--dx:6.4cqi}
  .lbl-up{--lift:14px}
}

/* Latitude and longitude, inside the frame over open water. */
.grat-lab{position:absolute; inset:0; z-index:1; pointer-events:none; font:400 12px/1 var(--mono); letter-spacing:.04em; color:var(--muted)}
.grat-lab span{position:absolute; white-space:nowrap}
.grat-lab .la{left:0; top:var(--y); translate:0 -50%; padding-left:14px}
.grat-lab .la::before{content:""; position:absolute; left:0; top:50%; width:8px; border-top:1px solid var(--line-strong)}
.grat-lab .lo{left:var(--x); bottom:0; translate:-50% 0; padding-bottom:13px}
.grat-lab .lo::before{content:""; position:absolute; left:50%; bottom:0; height:8px; border-left:1px solid var(--line-strong)}
@container (max-width:599.98px){ .grat-lab{display:none} }

/* ---------- Focus: the chosen chain stays, the rest recedes; the chain lights in flow order ---------- */
.src-fill, .uae-fill, .nd, .lbl{transition:opacity .35s var(--ease)}
.route{--st:0; transition:opacity .35s var(--ease), stroke-opacity .35s var(--ease) calc(var(--st) * 90ms), stroke-width .35s var(--ease) calc(var(--st) * 90ms)}
.route[data-to="dubai"]{--st:1}
.route[data-from="dubai"]{--st:3}
.plate[data-focus] .route{stroke-opacity:.95; stroke-width:1.8px}
.plate .off{opacity:.14}
.plate .lbl.off{opacity:.24}
@media (hover:hover) and (pointer:fine){ .js .nd, .js .lbl{pointer-events:auto; cursor:pointer} }

/* Breathing runs only while the plate is on screen (plate.js sets .is-live; paused, not removed,
   so it resumes where it stopped) and never under reduced motion. */
@media (prefers-reduced-motion:no-preference){
  .js .src-fill{animation:geo-breathe 2.3s var(--ease-io) infinite alternate paused}
  .js .nd-mkt::before{animation:geo-halo 2.6s var(--ease-io) infinite alternate paused}
  .js .nd-mkt[data-node="europe"]::before{animation-delay:-2.6s}
  .plate.is-live .src-fill, .plate.is-live .nd-mkt::before{animation-play-state:running}
}
@keyframes geo-breathe{from{fill-opacity:.42} to{fill-opacity:.66}}
@keyframes geo-halo{from{opacity:.55; scale:.84} to{opacity:1; scale:1}}

/* ---------- Index: the five places as keys, with their map symbols; the readout restates the chain ---------- */
/* Keys at the top edge of the plate, readout at its foot, so the column is framed by the map's
   top and bottom lines at every height. */
.geo-index{align-self:stretch; display:flex; flex-direction:column; justify-content:space-between; gap:var(--s6)}
.keys-title{margin-bottom:var(--s4)}
.keys{list-style:none; margin:0; padding:0; border-top:1px solid var(--line-strong)}
.key{position:relative; display:grid; grid-template-columns:22px minmax(0, 1fr) auto; align-items:center; gap:var(--s2) var(--s4); width:100%; min-height:60px; padding:var(--s3) var(--s2); background:none; border:0; border-bottom:1px solid var(--line); border-radius:0; color:var(--ink); font:inherit; text-align:left; cursor:pointer; transition:background-color .35s var(--ease)}
.key b{font:400 1.5rem/1.1 var(--serif); letter-spacing:-.005em; white-space:nowrap; transition:color .35s var(--ease), transform .35s var(--ease)}
.key small{font:600 12px/1.3 var(--sans); letter-spacing:.14em; text-transform:uppercase; white-space:nowrap; color:var(--ink-2); text-align:right}
/* Pinned: a cyan bar draws down the key's left edge. */
.key::before{content:""; position:absolute; left:0; top:-1px; bottom:-1px; width:2px; background:var(--teal-light); transform:scaleY(0); transform-origin:top center; transition:transform .35s var(--ease)}
.key[aria-pressed="true"]::before{transform:scaleY(1)}
/* The chosen place (from a key, the map or the keyboard): a wash, and the name steps in by a
   transform, never padding, as the category titles do. Pointer hover only where hover is real,
   so a tap never leaves a key tinted. */
.key.is-on{background:rgb(241 238 232 / .045)}
.key.is-on b, .key[aria-pressed="true"] b{transform:translateX(var(--s3)); color:var(--accent)}
@media (hover:hover) and (pointer:fine){
  .key:hover{background:rgb(241 238 232 / .045)}
  .key:hover b{transform:translateX(var(--s3))}
}
.key:focus-visible{outline-offset:-2px}
/* Map symbols as legend swatches. */
.sw{position:relative; width:22px; height:22px}
.sw::before, .sw::after{content:""; position:absolute; left:50%; top:50%; translate:-50% -50%; border-radius:50%}
.sw-src::before{width:18px; height:18px; border-radius:var(--r); background:var(--teal); opacity:.56}
.sw-src::after{width:7px; height:7px; background:var(--teal-light)}
.sw-hub::before{width:5px; height:5px; background:var(--ink)}
.sw-hub::after{width:15px; height:15px; border:1.5px solid var(--ink)}
.sw-mkt::before{width:26px; height:26px; background:radial-gradient(closest-side, rgb(127 211 232 / .62), rgb(127 211 232 / .22) 60%, rgb(127 211 232 / 0))}
.sw-mkt::after{width:6px; height:6px; border:1px solid var(--ink)}
/* Readout: small capitals over serif values. */
.geo-read{border-top:1px solid var(--line-strong)}
.geo-read > div{display:grid; gap:3px; padding:var(--s3) 0; border-bottom:1px solid var(--line)}
.geo-read dt{font:600 12px/1.5 var(--sans); letter-spacing:.14em; text-transform:uppercase; color:var(--ink-2)}
.geo-read dd{margin:0; font:400 1.25rem/1.25 var(--serif); color:var(--ink); transition:color .35s var(--ease)}
.geo-read dd.is-set{color:var(--accent)}

/* ---------- Caption row: one rule across map and index; the qualification under the map (verbatim),
   the line footnote under the index ---------- */
.geo-cap{grid-column:1 / -1; display:grid; grid-template-columns:minmax(0, var(--map-w)) minmax(0, 1fr); gap:var(--s4) var(--s8); align-items:start; padding-top:var(--s5); border-top:1px solid var(--line)}
.geo-note{max-width:88ch; font-size:15px; line-height:1.7; color:var(--ink-2)}
.key-note{display:grid; grid-template-columns:28px minmax(0, 1fr); gap:var(--s3); align-items:start; font-size:14px; line-height:1.55; color:var(--ink-2)}
.key-note svg{margin-top:4px}

/* Mid widths, where the map is narrowest beside the index: compact rows keep the index about
   as tall as the plate. */
@media (min-width:1100px) and (max-width:1399.98px){
  .key{min-height:52px; padding-block:var(--s2)}
  .geo-read > div{padding:var(--s2) 0}
}

/* ---------- Tablet: the map across the shell; keys and readout side by side below it ---------- */
@media (max-width:1099.98px){
  .geo-grid{grid-template-columns:minmax(0, 1fr); gap:var(--s7)}
  .geo-index{display:grid; grid-template-columns:minmax(0, 1fr) minmax(0, 1fr); gap:var(--s5) var(--s7)}
  /* Level with the keys' top rule, below their title (.caps 13px / 1.3 and its margin). */
  .geo-read{align-self:start; margin-top:calc(13px * 1.3 + var(--s4))}
  .geo-cap{grid-template-columns:minmax(0, 1fr)}
}

/* ---------- Phones: the map runs edge to edge; the keys become a compact list ---------- */
@media (max-width:699.98px){
  .plate{margin-inline:calc(var(--gutter) * -1)}
  .map::after{border-inline:0}
  .geo-index{grid-template-columns:minmax(0, 1fr); gap:var(--s6)}
  .geo-read{margin-top:0}
  .key{column-gap:var(--s3); min-height:56px; padding:var(--s2) var(--s1)}
  .key small{letter-spacing:.1em}
  .key b{font-size:1.375rem}
  .geo-read dd{font-size:1.1875rem}
}

/* ---------- Landscape phones: the plate fits the short screen, centred ---------- */
@media (orientation:landscape) and (max-height:600px){
  /* width:100% because a grid item with auto margins shrinks to its content, and the map
     (inline-size container) has none. */
  .plate{width:100%; max-width:calc((100svh - 90px) * 1.3605); margin-inline:auto}
  .map::after{border-inline:1px solid var(--line-strong)}
}

@media print{
  .flow{display:none}
  .route{stroke-dasharray:none !important; stroke-dashoffset:0 !important}
  .g-base, .g-src, .g-hub, .route, .nd, .lbl, .lbl > span, .grat-lab{opacity:1 !important; transform:none !important}
}

/* ===== src/css/process.css ===== */
/* How we work: the supply-chain line on Home, and the stage rail, explorer, responsibilities and
   principles on process.html. Owner: process workstream.
   States: without JavaScript, under reduced motion or on any failure everything is drawn finished
   (numbers filled, line complete). sequence.js adds .live to a line it drives (numbers outlined
   until reached, line empty until it fills) and .pin on the root when it pins the Home track. */

/* ---------- Drawings (Home stations, the rail and the explorer) ---------- */
.dw{overflow:visible; fill:none; stroke:var(--ink); stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round}
.dw .sheet{fill:var(--bg-2)}
.dw .tint{fill:var(--bg-3)}
.dw .heavy{stroke-width:3}
.dw .faint{stroke:var(--muted)}
.dw .acc{stroke:var(--teal)}
.dw .acc-ink{stroke:var(--accent)}
.dw .fold{stroke:var(--accent); stroke-dasharray:4 3}
.dw .dim{stroke:var(--ink-2); stroke-width:1}
.dw text{fill:var(--ink-2); stroke:none; font:600 11px/1 var(--mono)}
.dw .fill-teal{fill:var(--teal); stroke:none}
.dw .fill-navy{fill:var(--ink); stroke:none}
.dw .fill-muted{fill:var(--muted); stroke:none}
.dw .p-grow-x{transform-origin:left center}
.dw .p-grow-y{transform-origin:center top}
.dw .p-pop{transform-origin:center}
.dw g, .dw path, .dw rect{transform-box:fill-box}
.st-art .dw text, .stn-art .dw text{display:none}

/* Outlined numerals that fill from the left once reached (Home stations and the rail). */
.process.live .stn-no, .seq.live .st-no{color:transparent; -webkit-text-stroke:1px color-mix(in oklab, var(--ink) 42%, transparent); background:linear-gradient(90deg, var(--ink) 50%, transparent 50%) 100% 0 / 200% 100% no-repeat; -webkit-background-clip:text; background-clip:text; transition:background-position .9s var(--ease-io)}
.process.live .stn.on .stn-no, .seq.live .st.on .st-no{background-position:0 0}

/* ---------- Home: How we work, a vertical line of stations (phones, reduced motion, no JS) ---------- */
.process .track, .process .track-foot{width:min(100% - 2 * var(--gutter), var(--max)); margin-inline:auto}
.process .track{position:relative}
.track-intro{padding-bottom:var(--s8)}
.track-intro h2{max-width:10ch}
.track-intro h2 .it{font-style:italic}
.track-intro .lead{max-width:44ch}
.stations{position:relative; list-style:none; margin:0; padding:0; border-bottom:1px solid var(--line)}
.stations::before{content:""; position:absolute; left:4px; top:0; bottom:0; width:1px; background:var(--teal-light)}
.stn{position:relative; display:grid; grid-template-columns:minmax(0, 5fr) minmax(0, 7fr); gap:var(--s4) var(--s7); padding:var(--s6) 0 var(--s7) var(--s7); border-top:1px solid var(--line)}
.stn-node{position:absolute; z-index:1; left:0; pointer-events:none; top:calc(var(--s6) + 12px); width:9px; height:9px; background:var(--teal-light); border:1px solid var(--teal-light); transition:background-color .4s var(--ease), border-color .4s var(--ease)}
.stn-head{display:flex; align-items:flex-start; justify-content:space-between; gap:var(--s5)}
.stn-no{font:400 clamp(4rem, 3rem + 3vw, 6.5rem)/.8 var(--serif); letter-spacing:-.02em; color:var(--ink); font-variant-numeric:lining-nums}
.stn-art{flex:none; width:clamp(104px, 60px + 8vw, 168px)}
.stn-art .dw{width:100%; height:auto}
.stn-body{display:grid; align-content:start; gap:var(--s4)}
.stn-name, .stn-text{display:grid; align-content:start; gap:var(--s2)}
.stn h3{font:400 clamp(1.75rem, 1.35rem + 1.2vw, 2.5rem)/1.05 var(--serif); letter-spacing:-.01em}
.stn h3 a{color:var(--ink); text-decoration:none; text-decoration-thickness:1px; text-underline-offset:.16em}
/* The whole station is the link's target; the name carries the focus ring. */
.stn h3 a::after{content:""; position:absolute; inset:0}
.stn h3 a:focus-visible{text-decoration:underline; text-decoration-color:var(--accent)}
.stn-tag{font:600 12px/1.3 var(--sans); letter-spacing:.18em; text-transform:uppercase; color:var(--accent)}
.stn-out{color:var(--fg); max-width:42ch}
.stn-contrib{font-size:15px; line-height:1.6; color:var(--ink-2); max-width:42ch}
.track-foot{display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:var(--s3) var(--s7); padding-top:var(--s5)}
.track-foot .note{margin:0}
@media (min-width:1024px){
  html:not(.pin) .stn{grid-template-columns:minmax(0, 4fr) minmax(0, 8fr)}
  html:not(.pin) .stn-body{grid-template-columns:minmax(0, 1fr) minmax(0, 1fr); gap:var(--s7)}
}
@media (max-width:699.98px){
  .stn{grid-template-columns:minmax(0, 1fr); padding:var(--s5) 0 var(--s6) var(--s6)}
  .stn-node{top:calc(var(--s5) + 10px)}
  .stn-art{width:104px}
}

/* The live line (sequence.js): the rail stays a hairline, the cyan fill and the cargo ride it. */
.line{display:none}
.process.live .stations::before{background:var(--line-strong)}
.process.live .stn-node{background:var(--bg); border-color:var(--line-strong)}
.process.live .stn.on .stn-node{background:var(--teal-light); border-color:var(--teal-light)}
.process.live .line{display:block; position:absolute; left:4px; width:1px; pointer-events:none}
.line-fill{position:absolute; inset:0; background:var(--teal-light); transform-origin:center top; transform:scaleY(0)}
.cargo{position:absolute; z-index:2; top:0; left:0; width:7px; height:16px; margin:-8px 0 0 -3px; background:var(--teal-light); box-shadow:0 0 0 3px var(--bg)}

/* ---------- Home: the pinned track (wide landscape screens with motion; .pin set by sequence.js).
   Portrait tablets keep the vertical line: pinned, their tall screen left the track half empty. ---------- */
@media screen and (min-width:1024px) and (orientation:landscape){
  .pin .process{height:var(--pin-h, 300vh); padding:0; scroll-margin-top:calc(-1 * (var(--nav-top) + var(--nav-h) + var(--s5)))}
  .pin .track-stage{position:sticky; top:0; height:100vh; height:100svh; overflow:hidden; overflow:clip; display:grid; grid-template-columns:minmax(0, 1fr); grid-template-rows:minmax(0, 1fr) auto; padding-top:calc(var(--nav-top) + var(--nav-h) + var(--s3))}
  .pin .process .track{--axis:46%; --above:clamp(20px, 3.6vh, 48px); --below:clamp(22px, 3.8vh, 52px); display:flex; width:max-content; margin:0; padding:0 max(var(--gutter), (100% - var(--max)) / 2); will-change:transform}
  .pin .track-intro{flex:none; width:clamp(400px, 33vw, 620px); display:grid; grid-template-rows:minmax(0, var(--axis)) minmax(0, 1fr); padding:0 clamp(40px, 5vw, 120px) 0 0}
  .pin .track-intro h2{align-self:end; padding-bottom:var(--above)}
  .pin .track-intro .lead{align-self:start; margin:0; padding-top:var(--below); max-width:34ch}
  .pin .stations{flex:none; display:flex; border:0}
  .pin .stations::before{display:none}
  .pin .stn{flex:none; width:clamp(360px, 29vw, 560px); display:grid; grid-template-columns:minmax(0, 1fr); grid-template-rows:minmax(0, var(--axis)) minmax(0, 1fr); gap:0; padding:0 clamp(32px, 3.2vw, 72px) 0 0; border:0}
  .pin .stn-head{align-self:end; align-items:flex-end; justify-content:flex-start; gap:clamp(20px, 2vw, 40px); padding-bottom:var(--above)}
  .pin .stn-no{font-size:clamp(4.5rem, 15vh, 10rem)}
  .pin .stn-art{width:clamp(130px, 20vh, 250px)}
  .pin .stn-body{align-self:start; padding-top:var(--below)}
  .pin .stn h3{font-size:clamp(1.75rem, 1rem + 2.6vh, 3rem)}
  .pin .stn-node{top:var(--axis); left:0; width:11px; height:11px; margin:-5px 0 0 -5px}
  .pin .process .line{left:0; right:0; top:var(--axis); width:auto; height:1px; background:var(--line-strong)}
  .pin .process .line::before, .pin .process .line::after{content:""; position:absolute; top:-6px; width:1px; height:13px; background:var(--line-strong)}
  .pin .process .line::before{left:0}
  .pin .process .line::after{right:0}
  .pin .line-fill{inset:0 auto auto 0; height:1px; transform-origin:left center; transform:scaleX(0)}
  .pin .cargo{width:18px; height:8px; margin:-4px 0 0 -9px}
  .pin .process .track-foot{margin:0 auto; padding:var(--s4) 0 var(--s5); border-top:1px solid var(--line)}
}

/* ---------- How we work page: the five-stage rail (also Contact, as .seq.two) ---------- */
.sequence{padding:var(--sec) 0}
.seq-head h2{max-width:14ch}
.seq-head .lead{max-width:52ch}
.seq{position:relative; list-style:none; margin:var(--s8) 0 0; padding:0; display:grid; grid-template-columns:repeat(5, minmax(0, 1fr))}
.st{position:relative; border-left:1px solid var(--line)}
.st-link{position:relative; display:flex; flex-direction:column; height:100%; padding:0 var(--s5) var(--s6); text-decoration:none; color:inherit}
.st-art{display:block; padding-top:var(--s4)}
.st-art .dw{width:100%; max-width:200px; height:auto}
.st-rail{display:flex; align-items:center; margin:var(--s5) calc(-1 * var(--s5)) 0 calc(-1 * var(--s5) - 5px)}
.st-node{position:relative; z-index:1; flex:none; display:block; width:11px; height:11px; background:var(--bg); border:1px solid var(--teal-light); transition:background-color .3s var(--ease)}
.st-seg{flex:1; height:1px; background:var(--teal-light); transform-origin:left center}
.st:last-child .st-rail{margin-right:0}
.st:last-child .st-seg{position:relative}
.st:last-child .st-seg::after{content:""; position:absolute; right:0; top:-6px; width:1px; height:13px; background:var(--teal-light)}
.st-link:focus-visible .st-node{background:var(--teal-light)}
.st-no{margin-top:var(--s5); font:400 clamp(3rem, 2rem + 2vw, 4.75rem)/.8 var(--serif); letter-spacing:-.02em; color:var(--ink); font-variant-numeric:lining-nums}
.st-name{margin-top:var(--s4); font:400 clamp(1.5rem, 1.1rem + .9vw, 2rem)/1.05 var(--serif); color:var(--ink); text-decoration-thickness:1px; text-underline-offset:.16em}
.st-tag{margin-top:var(--s3); font:600 12px/1.3 var(--sans); letter-spacing:.16em; text-transform:uppercase; color:var(--accent)}
.st-desc{margin-top:var(--s3); font-size:15px; line-height:1.6; color:var(--fg); max-width:30ch}
.st-link:focus-visible .st-name{text-decoration:underline; text-decoration-color:var(--accent)}
.scope-note{margin-top:var(--s7); padding-top:var(--s4); border-top:1px solid var(--line-strong); font-size:15px; color:var(--ink-2)}
.seq.two{grid-template-columns:repeat(2, minmax(0, 1fr))}
.seq.two .st-desc{max-width:34ch}
/* Contact: the first two stages across the whole band, the numeral in the margin of each column
   and the dashed line running on towards the remaining stages. */
@media (min-width:900px){
  .seq.two .st-link{display:grid; grid-template-columns:auto minmax(0, 1fr); grid-template-rows:auto auto auto auto 1fr; column-gap:clamp(24px, 3vw, 56px); align-content:start}
  .seq.two .st-art{grid-column:2; grid-row:1}
  .seq.two .st-rail{grid-column:1 / -1; grid-row:2}
  .seq.two .st-no{grid-column:1; grid-row:3 / span 3; font-size:clamp(4rem, 3rem + 3vw, 7rem)}
  .seq.two .st-name{grid-column:2; grid-row:3; margin-top:var(--s5); font-size:clamp(1.75rem, 1.2rem + 1.2vw, 2.5rem)}
  .seq.two .st-tag{grid-column:2; grid-row:4}
  .seq.two .st-desc{grid-column:2; grid-row:5; max-width:48ch; font-size:16px}
}
.seq.two .st:last-child .st-seg{height:0; background:none; border-top:1px dashed var(--teal-light)}
.seq.two .st:last-child .st-seg::after{display:none}
@media (max-width:1099.98px){ .st-link{padding:0 var(--s4) var(--s6)} .st-rail{margin:var(--s5) calc(-1 * var(--s4)) 0 calc(-1 * var(--s4) - 5px)} .st-desc{font-size:14px} }
@media (max-width:899.98px){
  .seq, .seq.two{grid-template-columns:minmax(0, 1fr); border-bottom:1px solid var(--line)}
  .seq::before{content:""; position:absolute; left:5px; top:0; bottom:0; width:1px; background:var(--teal-light)}
  .st{border-left:0; border-top:1px solid var(--line)}
  .st-seg{display:none}
  .st-rail{grid-column:1; grid-row:1; margin:.45rem 0 0; align-self:start}
  .st-link{display:grid; grid-template-columns:11px 96px minmax(0, 1fr); grid-template-rows:auto auto auto auto; column-gap:var(--s4); padding:var(--s5) 0}
  .st-art{grid-column:2; grid-row:1 / span 4; padding:0}
  .st-art .dw{width:96px; height:auto}
  .st-no{grid-column:3; grid-row:1; margin:0; font-size:2.75rem}
  .st-name{grid-column:3; grid-row:2; margin-top:var(--s3)}
  .st-tag{grid-column:3; grid-row:3}
  .st-desc{grid-column:3; grid-row:4; max-width:none}
}

/* ---------- How we work page: stage explorer (W3C APG tabs, automatic activation) ---------- */
.explorer{padding:var(--sec) 0; border-top:1px solid var(--line)}
.ex{display:grid; grid-template-columns:minmax(0, 3fr) minmax(0, 9fr); gap:var(--s7) var(--s8); margin-top:var(--s7)}
.ex-tabs{position:relative; display:flex; flex-direction:column; align-self:start; border-top:1px solid var(--line-strong)}
.ex-tab{display:grid; grid-template-columns:2.75rem minmax(0, 1fr); align-items:baseline; gap:var(--s3); min-height:72px; padding:var(--s4) var(--s3) var(--s4) var(--s5); background:none; border:0; border-bottom:1px solid var(--line); border-radius:0; text-align:left; color:var(--ink-2); cursor:pointer; transition:color .25s var(--ease)}
.ex-tab .t-no{font:italic 400 1.5rem/1 var(--serif); color:var(--muted); transition:color .25s var(--ease)}
.ex-tab .t-name{font:400 1.5rem/1.12 var(--serif)}
.ex-tab[aria-selected="true"]{color:var(--ink)}
.ex-tab[aria-selected="true"] .t-no{color:var(--accent)}
.ex-ind{position:absolute; left:0; top:0; width:2px; height:72px; background:var(--teal-light); pointer-events:none}
.ex-panel{display:grid; grid-template-columns:minmax(0, 4fr) minmax(0, 5fr); gap:var(--s6) var(--s7); align-items:start}
.ex-panel + .ex-panel{margin-top:var(--s8); padding-top:var(--s8); border-top:1px solid var(--line)}
.js .ex-panel + .ex-panel{margin-top:0; padding-top:0; border-top:0}
.ex-text{display:flex; flex-direction:column; gap:var(--s3)}
.ex-top{display:flex; align-items:flex-end; justify-content:space-between; gap:var(--s5); padding-bottom:var(--s4); margin-bottom:var(--s2); border-bottom:1px solid var(--line-strong)}
.ex-no{font:400 clamp(4rem, 2.8rem + 3vw, 6.5rem)/.8 var(--serif); letter-spacing:-.02em; color:var(--ink); font-variant-numeric:lining-nums}
.ex-art{flex:none; width:clamp(112px, 9vw, 168px)}
.ex-art .dw{width:100%; height:auto; stroke-width:1.3}
.ex-art .dw .heavy{stroke-width:2.4}
.ex-art .dw text{font-size:10px}
.ex-tag{font:600 12px/1.3 var(--sans); letter-spacing:.16em; text-transform:uppercase; color:var(--accent)}
.ex-text h3{font:400 clamp(2.25rem, 1.5rem + 1.8vw, 3.25rem)/1.02 var(--serif); letter-spacing:-.01em}
.ex-text dl{margin-top:var(--s3)}
.ex-text dl > div{padding:var(--s4) 0; border-top:1px solid var(--line)}
.ex-text dt{font:600 12px/1.4 var(--sans); letter-spacing:.16em; text-transform:uppercase; color:var(--ink-2)}
.ex-text dd{margin-top:var(--s2); color:var(--ink); max-width:44ch}
.ex-photo{margin:0; overflow:hidden; aspect-ratio:4 / 3; background:var(--bg-2)}
.ex-photo img{width:100%; height:100%; object-fit:cover}
html:not(.js) .ex-tabs{display:none}
html:not(.js) .ex{grid-template-columns:minmax(0, 1fr)}
@media (max-width:1099.98px){
  .ex{grid-template-columns:minmax(0, 4fr) minmax(0, 8fr); gap:var(--s6)}
  .ex-panel{grid-template-columns:minmax(0, 1fr)}
  .ex-tab .t-name{font-size:1.3125rem}
}
@media (max-width:699.98px){
  .ex{grid-template-columns:minmax(0, 1fr)}
  .ex-tab{min-height:56px; padding-left:var(--s4)}
}

/* ---------- How we work page: responsibilities ---------- */
.explorer + .sec{border-top:1px solid var(--line)}
/* The heading takes the full width ("Responsibilities" never overflows). The statement is set in
   the serif only where it holds to two lines across the full measure; below that, a sans lead. */
.resp-grid{display:grid; grid-template-columns:minmax(0, 1fr); gap:var(--s6) var(--s8); align-items:start}
.resp-grid h2{max-width:none}
.resp-lead{font:500 clamp(1.125rem, 1rem + .45vw, 1.375rem)/1.55 var(--sans); color:var(--ink); max-width:52ch; text-wrap:pretty}
.resp-body{margin-top:var(--s6); padding-top:var(--s5); border-top:1px solid var(--line-strong); max-width:58ch; color:var(--ink-2)}
@media (min-width:1200px){
  .resp-lead{font:400 clamp(1.75rem, 1rem + 1.4vw, 2.5rem)/1.2 var(--serif); letter-spacing:-.005em; max-width:none; text-wrap:balance}
  .resp-body{margin-left:calc(5 / 12 * 100%)}
}

/* ---------- How we work page: four principles, one quadrant each ---------- */
.prin-list{list-style:none; margin:var(--s7) 0 0; padding:0; display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); border-top:1px solid var(--line-strong)}
.prin{display:grid; grid-template-columns:clamp(64px, 6vw, 104px) minmax(0, 1fr); gap:var(--s2) var(--s5); align-content:start; padding:var(--s7) var(--s7) var(--s7) 0}
.prin:nth-child(even){padding:var(--s7) 0 var(--s7) var(--s7); border-left:1px solid var(--line)}
.prin:nth-child(n+3){border-top:1px solid var(--line)}
.prin-no{grid-row:span 2; font:italic 400 clamp(2.5rem, 1.9rem + 1.6vw, 3.75rem)/.9 var(--serif); color:var(--ink-2)}
.prin h3{font:400 clamp(1.5rem, 1.2rem + .8vw, 2rem)/1.1 var(--serif); letter-spacing:-.01em}
.prin p{max-width:48ch; color:var(--ink-2)}
@media (max-width:767.98px){
  .prin-list{grid-template-columns:minmax(0, 1fr)}
  .prin, .prin:nth-child(even){padding:var(--s6) 0; border-left:0}
  .prin + .prin{border-top:1px solid var(--line)}
}

@media print{
  .process .track{transform:none !important}
  .line{display:none !important}
  .stn-body h3, .stn-body p, .st-node, .st-art, .dw .p-sheet, .dw .p-drop, .dw .p-fade, .dw .p-pop{opacity:1 !important; transform:none !important}
  .st-seg, .dw .p-grow-x, .dw .p-grow-y{transform:none !important}
  .process.live .stn-no, .seq.live .st-no{color:var(--ink); background:none; -webkit-text-stroke:0}
  .ex-panel[hidden]{display:grid !important}
  .ex-tabs{display:none !important}
}

/* Hover states only for a fine pointer, so a tap never leaves a stage looking selected. */
@media (hover:hover) and (pointer:fine){
  .stn:hover h3 a{text-decoration:underline; text-decoration-color:var(--accent)}
  .st-link:hover .st-node{background:var(--teal-light)}
  .st-link:hover .st-name{text-decoration:underline; text-decoration-color:var(--accent)}
  .ex-tab:hover{color:var(--ink)}
}

/* ===== src/css/corporate.css ===== */
/* The corporate surface and contact, on Home and the detail pages.
   Owner: design-system workstream. */

/* ---------- Paper: the corporate surface (Home #corporate, the register on corporate.html), in its own
   --paper tokens (base.css). Dark like the rest of the site since 26 Sep 2026, on the regular rhythm. ---------- */
.paper{position:relative; z-index:1; background:var(--paper); color:var(--paper-ink); padding:var(--sec) 0}
.paper h2, .paper h3{color:var(--paper-ink)}
.paper .lead, .paper .note, .paper .record-note, .paper .caps, .paper .coord{color:var(--paper-ink-2)}
.paper .head .lead, .paper .sec-head .lead{border-top-color:var(--paper-line)}
.paper .head h2 .it{color:var(--paper-accent)}
.paper :focus-visible{outline-color:var(--paper-accent)}
.paper ::selection{background:var(--paper-ink); color:var(--paper)}
.paper .text-link{--u:var(--paper-line); color:var(--paper-ink)}
.paper .text-link .i{color:var(--paper-accent)}

/* Five numbered statements: italic serif figures, serif statements, a short plain line beside. */
.about{list-style:none; margin:0; padding:0; border-top:1px solid var(--paper-ink)}
.about li{display:grid; grid-template-columns:minmax(64px, 1fr) minmax(0, 6fr) minmax(0, 5fr); gap:var(--s2) var(--s6); align-items:baseline; padding:var(--s5) 0 var(--s6); border-bottom:1px solid var(--paper-line)}
/* Hover nudges the row's content, not the row, so the hairline stays put (transform only). */
@media (hover:hover) and (pointer:fine) and (prefers-reduced-motion:no-preference){
  .about li > *{transition:transform .35s var(--ease)}
  .about li:hover > *{transform:translateX(var(--s3))}
}
.ab-no{font:italic 400 clamp(2rem, 1.4rem + 1.6vw, 3.25rem)/1 var(--serif); color:var(--paper-accent)}
.about h3{font:400 clamp(1.75rem, 1.3rem + 1.4vw, 2.75rem)/1.05 var(--serif); letter-spacing:-.01em}
.about p{max-width:40ch; color:var(--paper-ink-2)}

/* The six registered particulars as a ruled record: a heavy rule, then cells split by hairlines. */
.corp-reg{margin-top:var(--s9)}
.corp-reg > .caps{display:block; padding-bottom:var(--s3); border-bottom:1px solid var(--paper-ink)}
.corp-facts{display:grid; grid-template-columns:repeat(3, minmax(0, 1fr))}
.corp-facts > div{display:grid; align-content:start; gap:var(--s3); padding:var(--s5) var(--s5) var(--s6); border-bottom:1px solid var(--paper-line); border-left:1px solid var(--paper-line)}
.corp-facts > div:nth-child(3n+1){border-left:0; padding-left:0}
.corp-facts dt{font:600 12px/1.4 var(--sans); letter-spacing:.16em; text-transform:uppercase; color:var(--paper-ink-2)}
.corp-facts dd{font:400 var(--fs-h4)/1.2 var(--serif); letter-spacing:-.005em; color:var(--paper-ink); text-wrap:balance}
.corp-facts dd.num{font:500 1.125rem/1.5 var(--mono); letter-spacing:0}
.paper-foot{display:flex; flex-wrap:wrap; justify-content:space-between; align-items:center; gap:var(--s4); margin-top:var(--s6)}
@media (max-width:1023.98px){
  .corp-facts{grid-template-columns:1fr 1fr}
  .corp-facts > div:nth-child(3n+1){border-left:1px solid var(--paper-line); padding-left:var(--s5)}
  .corp-facts > div:nth-child(2n+1){border-left:0; padding-left:0}
}
@media (max-width:699.98px){
  .about li{grid-template-columns:52px minmax(0, 1fr); padding:var(--s4) 0 var(--s5)}
  .about p{grid-column:2}
  .corp-reg{margin-top:var(--s8)}
  .corp-facts{grid-template-columns:1fr}
  .corp-facts > div, .corp-facts > div:nth-child(3n+1){border-left:0; padding:var(--s4) 0 var(--s5)}
}

/* The register on corporate.html, set on the sheet like a document: serif values, mono figures. */
.paper .register{border-top-color:var(--paper-ink)}
.paper .register > div{border-bottom-color:var(--paper-line)}
.paper .register dt{color:var(--paper-ink-2)}
.paper .register dd{font:400 var(--fs-h4)/1.25 var(--serif); letter-spacing:-.005em; color:var(--paper-ink)}
.paper .register dd.num{font:500 1.125rem/1.5 var(--mono); letter-spacing:0}
/* Values that run past two lines on a phone (the licensed activities) read in the sans. */
.paper .register .long dd{font:500 1.0625rem/1.55 var(--sans); letter-spacing:0}

/* ---------- Contact on Home ---------- */
/* A generous bottom (--sec-b) that the bezel horizon (.echo) fills. */
.contact{--sec-b:var(--sec-l); isolation:isolate; overflow:clip}
/* Same 7/5 split and 64 px gap as .head, so the contact column starts under the lead's rule. */
.contact-grid{display:grid; grid-template-columns:minmax(0, 7fr) minmax(0, 5fr); gap:var(--s8); align-items:start}
.contact h3.caps{margin-bottom:var(--s4)}
.contact .checklist{margin-top:0}
.brief-actions{display:flex; flex-wrap:wrap; gap:var(--s3); margin-top:var(--s6)}
.copy-status{display:flex; align-items:center; gap:var(--s2); min-height:28px; margin-top:var(--s3); font-size:var(--fs-small); font-weight:600}
.copy-status:empty{display:none}
.copy-status.ok{color:var(--accent)}
.copy-status.err{color:var(--ink)}
.copy-status .i{width:18px; height:18px}
.template{display:block; width:100%; min-height:300px; margin-top:var(--s4); padding:var(--s4); border:1px solid var(--edge); border-radius:var(--r); background:var(--bg-2); color:var(--fg); font:400 14px/1.6 var(--mono); resize:vertical}
.contact-card dl{border-top:1px solid var(--line-strong)}
.contact-card dl > div{padding:var(--s4) 0 var(--s5); border-bottom:1px solid var(--line)}
.contact-card dt{font:600 12px/1.4 var(--sans); letter-spacing:.16em; text-transform:uppercase; color:var(--ink-2)}
.contact-card dd{margin-top:var(--s2); color:var(--ink); text-wrap:balance}
.contact-card dd a{display:inline-flex; align-items:center; min-height:44px; color:var(--ink); font:400 clamp(1.5rem, 1.15rem + 1.1vw, 2.25rem)/1.15 var(--serif); letter-spacing:-.01em; text-decoration:underline; text-decoration-color:var(--line-strong); text-decoration-thickness:1px; text-underline-offset:6px; overflow-wrap:anywhere; transition:text-decoration-color .25s var(--ease), color .25s var(--ease)}
@media (hover:hover) and (pointer:fine){ .contact-card dd a:hover{text-decoration-color:var(--accent)} }
/* The globe's bezel again: a horizon that rises only into the section's bottom space (--cap, just
   under the contact's --sec-b), clear of the text, turning on its own clock. The same object,
   abstracted. Styled here in full so hero.css changes cannot reach it. */
.echo{--d:min(92vw, 1320px); --cap:calc(var(--sec-b, var(--sec)) - 8px); position:absolute; z-index:-1; right:calc(var(--gutter) * -1 - 8vw); bottom:calc(var(--cap) - var(--d)); width:var(--d); aspect-ratio:1; pointer-events:none}
.echo .ring{position:absolute; inset:0; width:100%; height:100%; overflow:visible; fill:none; stroke:rgb(214 238 245 / .16); vector-effect:non-scaling-stroke}
.echo .ring text{fill:rgb(214 238 245 / .36); stroke:none; font:400 11px/1 var(--mono); letter-spacing:.08em}
.echo .ring-inner{stroke:rgb(214 238 245 / .1)}
@media (prefers-reduced-motion:no-preference){
  .echo .ring-outer{animation:echo-turn 240s linear infinite}
  .echo .ring-inner{animation:echo-turn 170s linear infinite reverse}
}
@keyframes echo-turn{to{transform:rotate(360deg)}}
@media (max-width:899.98px){
  .contact-grid{grid-template-columns:1fr; gap:var(--s8)}
  .echo{--d:180vw; right:-70vw}
}
@media (max-width:479.98px){ .brief-actions .btn{flex:1 1 100%} }

/* ---------- Contact page: the same columns, with section-level headings ---------- */
.contact-grid h2{font-size:var(--fs-h3); line-height:1.02; max-width:16ch}
.contact-grid h2 + .checklist{margin-top:var(--s6)}
.contact-card h2{margin-bottom:var(--s6)}
