:root{
  --ink:#00081F; --hull:#000C3C; --hull-2:#001854;
  --beam:#CCD8E4; --signal:#D80000; --paper:#EEF2F7; --dim:#7C8BA5;
  --rule:rgba(204,216,228,.18);
  --display:"Bodoni Moda",Georgia,serif;
  --body:"IBM Plex Sans",system-ui,sans-serif;
  --data:"IBM Plex Mono",ui-monospace,monospace;
  --gutter:clamp(1.25rem,5vw,5rem);
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--ink);color:var(--paper);font-family:var(--body);font-weight:300;line-height:1.65;-webkit-font-smoothing:antialiased}
body::before{content:"";position:fixed;inset:0;pointer-events:none;z-index:0;
  background-image:linear-gradient(var(--rule) 1px,transparent 1px),linear-gradient(90deg,var(--rule) 1px,transparent 1px);
  background-size:88px 88px;opacity:.35}
main,header,footer{position:relative;z-index:1}
a{color:inherit}
:focus-visible{outline:2px solid var(--signal);outline-offset:3px}
.label{font-family:var(--data);font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}

/* ---------- landing: 4K film, the mark composited crisp on top ---------- */
.hero{position:relative;min-height:100svh;display:grid;grid-template-rows:auto 1fr auto;
  padding:clamp(1.25rem,3vw,2rem) var(--gutter) clamp(1.5rem,4vw,3rem);overflow:hidden}
.film{position:absolute!important;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;filter:saturate(.55) brightness(.85);
  /* Slow push-in. The ORIGINAL hero had this in the footage — its camera dollied, and
     that drift is half of why the old clip felt alive. The 2026-09-12 film was generated
     with camera STATIC, so the move has to come from here instead.
     `alternate` is deliberate: a scale that resets to 1 at the loop point snaps. Zooming
     in over one pass and back out over the next never jumps. Period is 2x the film loop
     (9.29s) so the push and the beam stay in step rather than beating against each other. */
  animation:push 18.58s ease-in-out infinite alternate;will-change:transform}
@keyframes push{from{transform:scale(1)}to{transform:scale(1.08)}}
@media (prefers-reduced-motion:reduce){.film{animation:none}}
/* the sea is the ground; this keeps type legible over it without flattening the picture */
.hero::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    radial-gradient(120% 90% at 50% 45%,transparent 30%,rgba(0,0,0,.55) 72%,rgba(0,0,0,.92) 100%),
    linear-gradient(180deg,rgba(0,0,0,.72) 0%,rgba(0,0,0,.12) 38%,rgba(0,0,0,.86) 100%)}
.hero>*:not(.film){position:relative;z-index:2}
.centre{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:clamp(1.4rem,3vw,2.1rem);text-align:center;
  /* Lifted 2026-09-12 for the new film: its lamp sits at x 44.3% / y 47.2% and the
     sky above y~35% is clear, so the wordmark now sits ABOVE the lighthouse instead
     of across it. Measured off the clip, not eyeballed. */
  /* The group sits in the clear sky above the lighthouse, whose lamp is at y 47.2%. */
  /* Centred on the LIGHTHOUSE, not on the viewport. Measured on the rendered page with
     the type hidden: the lamp lands at x 45.8% at 3840x2160 and 1920x1080, 46.4% at
     1440x900, while the wordmark centre sat at 50%. -4.2% closes that gap and holds
     across those sizes because the film is wider than all of them, so object-fit:cover
     crops vertically, not horizontally. */
  transform:translate(-4.2%,-24%)}
@media (max-height:620px){.centre{transform:none}}
.wordmark{position:relative;margin:0;display:flex;flex-direction:column;align-items:center;
  gap:.30em;width:min(92vw,760px)}
.wordmark .name{font-family:"Playfair Display",Georgia,serif;font-weight:600;
  font-size:clamp(2.6rem,7.4vw,6.2rem);line-height:1;letter-spacing:.005em;color:#2B4A9E;
  white-space:nowrap;
  /* the lettering is lit, not painted: a cool rim above, shadow below */
  text-shadow:0 1px 0 rgba(180,205,240,.35), 0 0 30px rgba(120,160,220,.30), 0 10px 34px rgba(0,0,0,.7)}
.wordmark .name em{font-style:normal;color:var(--signal);
  text-shadow:0 1px 0 rgba(255,190,190,.35), 0 0 26px rgba(216,0,0,.45), 0 10px 34px rgba(0,0,0,.7)}
.wordmark .sub{display:flex;align-items:center;gap:.9em;width:88%}
.wordmark .sub i{flex:1;height:1px;background:linear-gradient(90deg,transparent,#5D7CB8)}
.wordmark .sub i:last-child{background:linear-gradient(270deg,transparent,#5D7CB8)}
.wordmark .sub span{font-family:"Playfair Display",Georgia,serif;font-weight:500;
  font-size:clamp(.72rem,1.5vw,1.15rem);letter-spacing:.42em;text-indent:.42em;color:#8FA8D4;
  text-transform:uppercase;white-space:nowrap}

/* hidden until the beam comes round */
.wordmark .name,.wordmark .sub{opacity:0}
/* ...and it STAYS lit once it has been. `strike` sets opacity via animation-fill-mode
   forwards, but `.lit.pass` swaps `catch` onto the same animation property, which
   discards that fill and drops the wordmark back to the base opacity:0 — so the name
   disappeared for good after the first beam pass. Harmless when the hero was a
   curtain-raiser; not harmless now the hero is the landing page and the wordmark is
   the only identity on it. */
.lit .wordmark .name{opacity:1}
/* The sub-line, rule and links follow the NAME rather than arriving with it. `.lit`
   used to set .sub to opacity:1 instantly while .name was still clipped by `strike`,
   so the lockup read headless — SERVICES LLC and the two links visible with no
   company name above them. The wipe finishes 0.63s after the strike fires, so these
   start just after that. `both` holds them at opacity 0 through the delay. */
.lit .wordmark .name{animation:strike 1.15s cubic-bezier(.2,.75,.25,1) forwards}
.lit .wordmark .sub{animation:rise 1.1s cubic-bezier(.16,.9,.24,1) .70s both}
@keyframes strike{
  0%  {opacity:0;clip-path:inset(0 100% 0 0);filter:blur(8px) brightness(.4)}
  55% {opacity:1;clip-path:inset(0 0 0 0);filter:blur(0) brightness(2)}
  100%{opacity:1;clip-path:inset(0 0 0 0);filter:blur(0) brightness(1)}}
/* The catch lights the glyphs via text-shadow, NOT filter:brightness() on .wordmark.
   Over a playing video an animated filter promotes the text to its own GPU layer, and on
   this machine's amdgpu the layer's bounds paint as a lighter rectangle behind the
   lettering while the sub-line drops to grey. text-shadow composites in place.
   The red V carries its own shadow stack, so it needs its own keyframes to pulse with
   the rest — otherwise it sits static while the blue lifts around it. */
/* ⚠ BOTH animations listed, never one replacing the other, and NEVER on the container.
   Two failure modes bracket this line and each fix causes the other if taken alone:
   1. `catch` alone on .name replaces the `animation` shorthand, discarding
      `strike ... forwards`, so the name dips when the glint ends (measured 2026-09-12:
      opacity fell to 0.65 at t=3.04s, recovering by 3.50s).
   2. Moving `catch` to the .wordmark CONTAINER fixes that dip but promotes the container
      to its own GPU layer over the playing video, and on this machine's amdgpu the layer
      BOUNDS paint as a lighter rectangle behind the lettering — the "box between the
      lettering when the beam passes", reported 2026-09-12 and previously seen with the
      old raster wordmark.
   Listing both animations on .name keeps strike's forwards state AND leaves the promoted
   layer tight to the glyphs, where text-shadow composites in place. */
.lit.pass .wordmark .name{animation:strike 1.15s cubic-bezier(.2,.75,.25,1) forwards,
                           catch 1.6s ease-in-out}
.lit.pass .wordmark .name em{animation:catch-v 1.6s ease-in-out}
@keyframes catch{
  0%,100%{text-shadow:0 1px 0 rgba(180,205,240,.35), 0 0 30px rgba(120,160,220,.30), 0 10px 34px rgba(0,0,0,.7)}
  50%    {text-shadow:0 1px 0 rgba(215,232,255,.60), 0 0 48px rgba(160,200,255,.65), 0 10px 34px rgba(0,0,0,.7)}}
@keyframes catch-v{
  0%,100%{text-shadow:0 1px 0 rgba(255,190,190,.35), 0 0 26px rgba(216,0,0,.45), 0 10px 34px rgba(0,0,0,.7)}
  50%    {text-shadow:0 1px 0 rgba(255,215,215,.60), 0 0 42px rgba(255,40,40,.75), 0 10px 34px rgba(0,0,0,.7)}}
/* hairline rules opening outward from the centre, the way a chart rule is drawn */
.rule{width:min(470px,34vw);height:1px;background:linear-gradient(90deg,transparent,var(--beam),transparent);
  opacity:0;transform:scaleX(0)}
.lit .rule{animation:draw 1.4s cubic-bezier(.16,.9,.24,1) .78s forwards}
@keyframes draw{to{opacity:.55;transform:scaleX(1)}}
.tag{margin:0;font-family:var(--data);font-size:clamp(.68rem,1.4vw,.8rem);letter-spacing:.3em;
  text-transform:uppercase;color:#B7C6DA;opacity:0}
.lit .tag{animation:rise 1.4s cubic-bezier(.16,.9,.24,1) .9s forwards}
@keyframes rise{from{opacity:0;transform:translateY(10px)}to{opacity:.95;transform:none}}
.cue{display:flex;flex-direction:column;align-items:center;gap:.5rem;opacity:0}
.lit .cue{animation:rise 1.2s ease-out 1.6s forwards}
.cue span{font-family:var(--data);font-size:.64rem;letter-spacing:.22em;text-transform:uppercase;color:var(--dim)}
.cue i{display:block;width:1px;height:44px;background:linear-gradient(180deg,var(--beam),transparent);
  animation:fall 2.6s ease-in-out infinite}
@keyframes fall{0%,100%{opacity:.25;transform:scaleY(.6)}50%{opacity:.8;transform:scaleY(1)}}
.topbar{display:flex;justify-content:flex-end;align-items:baseline;gap:1rem;flex-wrap:wrap}
.hero-body{display:flex;flex-direction:column;justify-content:center;gap:clamp(1.4rem,3.5vw,2.2rem);padding:clamp(2rem,5vw,3.5rem) 0}
.mark{width:clamp(170px,24vw,280px);height:auto;filter:drop-shadow(0 12px 40px rgba(0,0,0,.6))}
h1{font-family:var(--display);font-weight:400;font-size:clamp(2.2rem,6.2vw,4.6rem);line-height:1.04;letter-spacing:-.015em;margin:0;max-width:17ch}
h1 em{font-style:normal;color:var(--signal)}
.standfirst{max-width:52ch;font-size:clamp(1rem,2vw,1.18rem);color:#C4CEDD;margin:0}
.station{border-top:1px solid var(--rule);padding-top:1rem;display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:1rem 2rem}
.station div{display:flex;flex-direction:column;gap:.3rem}
.station b{font-family:var(--data);font-weight:500;font-size:.95rem;color:var(--beam);letter-spacing:.02em}
.char .fl{color:var(--signal)}

section{padding:clamp(3.5rem,9vw,7rem) var(--gutter);border-top:1px solid var(--rule)}
.sec-head{display:flex;gap:1rem;align-items:baseline;margin-bottom:clamp(1.5rem,4vw,2.5rem);flex-wrap:wrap}
h2{font-family:var(--display);font-weight:400;font-size:clamp(1.7rem,4vw,2.8rem);margin:0;letter-spacing:-.01em;max-width:20ch}
.lede{max-width:58ch;color:#B9C4D4;margin:0 0 clamp(1.8rem,4vw,2.6rem);font-size:clamp(1rem,2vw,1.1rem)}

.grades{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:1px;background:var(--rule);border:1px solid var(--rule)}
.grade{background:var(--ink);padding:clamp(1.4rem,3vw,2rem);display:flex;flex-direction:column;gap:.6rem}
.grade h3{font-family:var(--display);font-weight:400;font-size:1.3rem;margin:0}
.grade p{margin:0;color:#B9C4D4;font-size:.94rem}
.grade .hn{font-family:var(--data);font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;color:var(--dim);border-top:1px solid var(--rule);padding-top:.6rem;margin-top:auto}

/* Signature: the depth chain — what the berth allows decides everything downstream */
.chain{display:grid;gap:1px;background:var(--rule);border:1px solid var(--rule);font-family:var(--data);font-size:.86rem}
.chain>div{background:var(--ink);display:grid;grid-template-columns:1.1fr 1.4fr 1fr;gap:1rem;padding:.85rem clamp(1rem,2vw,1.6rem);align-items:baseline}
.chain .hd{color:var(--dim);font-size:.7rem;letter-spacing:.14em;text-transform:uppercase}
.chain b{font-weight:500;color:var(--beam)}
.chain span:last-child{color:#9FB0C6}
.note{font-size:.82rem;color:var(--dim);margin:.9rem 0 0;max-width:60ch}

.scope{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr));gap:2rem clamp(2rem,5vw,4rem);margin-top:clamp(2rem,5vw,3rem)}
.scope h3{font-family:var(--display);font-weight:400;font-size:1.25rem;margin:0 0 .5rem}
.scope p{margin:0;color:#B9C4D4;font-size:.95rem}

.hail{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:2rem}
.hail a{font-family:var(--data);font-size:1.05rem;color:var(--beam);text-decoration:none;border-bottom:1px solid var(--rule);padding-bottom:.2rem;display:inline-block;word-break:break-word}
.hail a:hover{border-color:var(--signal);color:#fff}
footer{padding:2rem var(--gutter) 3rem;border-top:1px solid var(--rule);display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap}
/* Same credit line the InVenture holding page and the other client sites carry. */
.builder a{color:inherit;text-decoration:none;border-bottom:1px solid rgba(93,124,184,.5);
  transition:color .18s ease,border-color .18s ease}
.builder a:hover,.builder a:focus-visible{color:#F0F3F7;border-bottom-color:#C2001A;outline:none}

@media (max-width:640px){
  .chain>div{grid-template-columns:1fr 1fr;gap:.4rem 1rem}
  .chain span:last-child{grid-column:1/-1}
}
@media (prefers-reduced-motion:reduce){
  .wordmark .name,.wordmark .sub,.lit .wordmark .name,.lit .wordmark .sub{
    animation:none;opacity:1;clip-path:none;filter:none}
  .rule{animation:none;opacity:.55;transform:none}
  .tag,.cue{animation:none;opacity:1}
  .cue i{animation:none}
  .film{display:none}
  .hero{background-image:url('/assets/video/hero-poster.jpg');background-size:cover;background-position:center}
  *{animation-duration:.001ms!important;transition-duration:.001ms!important}
  html{scroll-behavior:auto}
}

/* ---------- operations: engineering section, drawn then worked ---------- */
.ops{background:#020C22}
.drawing{margin-top:clamp(1.5rem,4vw,2.5rem);border:1px solid var(--rule);background:#01091C;
  padding:clamp(.5rem,1.5vw,1rem);overflow:hidden}
.drawing svg{display:block;width:100%;height:auto}
.ops .note{margin-top:1rem}

/* line grammar of a drawing: one weight for structure, lighter for detail */
.hullfill{fill:#020C22;stroke:none}
.ln{fill:none;stroke:#7FA0CE;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;vector-effect:non-scaling-stroke}
.ln.heavy{stroke:#B8CDEA;stroke-width:3}
.ln.thin{stroke:#4E6FA4;stroke-width:1.4}
.ln.dash{stroke-dasharray:12 8}
.wave{fill:none;stroke:#3E6396;stroke-width:2}
.w1{animation:drift1 11s linear infinite}
.w2{animation:drift2 17s linear infinite;opacity:.6}
@keyframes drift1{to{transform:translateX(-160px)}}
@keyframes drift2{to{transform:translateX(120px)}}
.pile{fill:url(#hatch);stroke:#7FA0CE;stroke-width:2;transform-origin:130px 470px;
  animation:heap 16s ease-in-out infinite}
@keyframes heap{0%{transform:scaleY(.25)}70%{transform:scaleY(1)}100%{transform:scaleY(.25)}}

.dim{fill:none;stroke:#7FA0CE;stroke-width:1.4;stroke-dasharray:none}
.t{fill:#B8CDEA;font-family:"IBM Plex Mono",monospace;font-size:19px;letter-spacing:.06em}
.t.sm{fill:#6E8BB8;font-size:13px;letter-spacing:.16em}
.notes .lead{stroke:#4E6FA4}

/* the drawing draws itself when it comes into view */
.draw .ln{stroke-dasharray:2600;stroke-dashoffset:2600}
.ops.seen .draw .ln{animation:ink 2.4s cubic-bezier(.3,.8,.3,1) forwards}
.ops.seen .vessel .ln{animation-delay:.35s}
.ops.seen .gantry .ln{animation-delay:.8s}
@keyframes ink{to{stroke-dashoffset:0}}
.dims,.notes,.cargo,.pile{opacity:0}
.ops.seen .dims{animation:fadein .9s ease-out 2.2s forwards}
.ops.seen .notes{animation:fadein .9s ease-out 2.5s forwards}
.ops.seen .cargo,.ops.seen .pile{animation:fadein .6s ease-out 1.8s forwards}
@keyframes fadein{to{opacity:1}}

/* --- the working cycle: grab lifts from the hold, tracks to the hopper, releases --- */
.trolley{transform:translateX(820px);animation:track 16s cubic-bezier(.45,0,.55,1) infinite}
@keyframes track{
  0%,6%   {transform:translateX(820px)}   /* over the hold */
  24%,30% {transform:translateX(820px)}
  46%     {transform:translateX(210px)}   /* over the hopper */
  58%     {transform:translateX(210px)}
  76%,100%{transform:translateX(820px)}}
.grab{animation:hoist 16s cubic-bezier(.4,0,.5,1) infinite}
@keyframes hoist{
  0%   {transform:translateY(150px)}
  10%  {transform:translateY(370px)}      /* down into the hold */
  20%  {transform:translateY(370px)}      /* close on the cargo */
  34%  {transform:translateY(120px)}      /* hoist clear */
  46%,58%{transform:translateY(150px)}
  64%  {transform:translateY(230px)}      /* lower over hopper */
  72%  {transform:translateY(150px)}
  100% {transform:translateY(150px)}}
.rope{animation:rope 16s cubic-bezier(.4,0,.5,1) infinite}
@keyframes rope{
  0%{transform:scaleY(1)}10%{transform:scaleY(2.5)}20%{transform:scaleY(2.5)}
  34%{transform:scaleY(.8)}46%,58%{transform:scaleY(1)}64%{transform:scaleY(1.55)}
  72%,100%{transform:scaleY(1)}}
.jawL,.jawR{transform-origin:0 0;animation:jaws 16s steps(1,end) infinite}
@keyframes jaws{
  0%,14%   {transform:scaleX(1.25)}       /* open, descending */
  20%,62%  {transform:scaleX(.72)}        /* closed, loaded */
  66%,100% {transform:scaleX(1.25)}}      /* open over the hopper */
.cargo.c1{animation:empty 16s linear infinite}
@keyframes empty{0%{transform:translateY(0)}100%{transform:translateY(56px)}}

/* --- magnet: shorter, offset cycle so the two never move together --- */
.trolley2{transform:translateX(1170px);animation:track2 13s cubic-bezier(.45,0,.55,1) infinite}
@keyframes track2{0%,22%{transform:translateX(1170px)}52%,68%{transform:translateX(390px)}94%,100%{transform:translateX(1170px)}}
.magnet{animation:hoist2 13s cubic-bezier(.4,0,.5,1) infinite}
@keyframes hoist2{
  0%{transform:translateY(150px)}12%{transform:translateY(390px)}
  22%{transform:translateY(390px)}36%{transform:translateY(120px)}
  52%,62%{transform:translateY(150px)}70%{transform:translateY(300px)}
  80%,100%{transform:translateY(150px)}}
.magnet .rope{animation:rope2 13s cubic-bezier(.4,0,.5,1) infinite}
@keyframes rope2{0%{transform:scaleY(1)}12%{transform:scaleY(2.7)}22%{transform:scaleY(2.7)}
  36%{transform:scaleY(.8)}52%,62%{transform:scaleY(1)}70%{transform:scaleY(2)}80%,100%{transform:scaleY(1)}}
.scrap{opacity:0;animation:held 13s steps(1,end) infinite}
@keyframes held{0%,20%{opacity:0}24%,64%{opacity:1}68%,100%{opacity:0}}
.cargo.c2{animation:empty2 13s linear infinite}
@keyframes empty2{0%{transform:translateY(0)}100%{transform:translateY(44px)}}

@media (prefers-reduced-motion:reduce){
  .ops .draw .ln{stroke-dasharray:none;stroke-dashoffset:0;animation:none}
  .dims,.notes,.cargo,.pile{opacity:1;animation:none}
  .trolley,.grab,.rope,.jawL,.jawR,.trolley2,.magnet,.scrap,.w1,.w2,.pile,.cargo{animation:none}
  .jawL,.jawR{transform:scaleX(1)}
}

/* the drawing becomes the thing it describes */
.drawing{position:relative}
.opsfilm{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover}
/* the section drawing survives as the reduced-motion and no-video fallback */
.drawing svg{display:none}
@media (prefers-reduced-motion:reduce){.opsfilm{display:none}.drawing svg{display:block}}
.readout{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1px;
  background:var(--rule);border:1px solid var(--rule);border-top:0}
.readout div{background:#01091C;padding:.85rem clamp(.8rem,2vw,1.4rem);display:flex;flex-direction:column;gap:.3rem}
.readout b{font-family:var(--data);font-weight:500;font-size:.95rem;color:var(--beam)}

/* ---------- paper below the hero ---------- */
/* The trading houses all break to white under the hero; the ops drawing stays dark
   because its line work is drawn light-on-dark and inverting it is a redraw. */
.light{background:var(--paper);color:#0E1830;border-top:1px solid #D3DCE8}
.light h2,.light .grade h3,.light .scope h3{color:#00081F}
.light .lede,.light .grade p,.light .scope p{color:#41506B}
.light .label,.light .note,.light .grade .hn,.light .chain .hd{color:#5C6B87}
.light .grades,.light .chain{background:#D3DCE8;border-color:#D3DCE8}
.light .grade,.light .chain>div{background:#fff}
.light .grade .hn{border-top-color:#D3DCE8}
.light .chain b{color:#00081F}
.light .chain span:last-child{color:#41506B}
.addr{font-family:var(--data);font-size:1rem;color:var(--beam)}
.light .addr{color:#00081F}
.light .hail a{color:#00081F;border-bottom-color:#C3CEDE}
.light .hail a:hover{color:var(--signal);border-color:var(--signal)}

/* ================= buildout: reference-grade sections ================= */

/* --- station bar: sticky index, reads as a chart legend not a nav --- */
.deck{position:sticky;top:0;z-index:40;display:flex;gap:clamp(.8rem,2.4vw,2rem);align-items:center;
  padding:.55rem var(--gutter);background:rgba(0,8,31,.86);backdrop-filter:blur(10px);
  border-bottom:1px solid var(--rule);overflow-x:auto;scrollbar-width:none}
.deck::-webkit-scrollbar{display:none}
.deck a{font-family:var(--data);font-size:.66rem;letter-spacing:.18em;text-transform:uppercase;
  color:#8FA0B8;text-decoration:none;white-space:nowrap;padding:.25rem 0;border-bottom:1px solid transparent}
.deck a:hover,.deck a[aria-current="true"]{color:var(--beam);border-bottom-color:var(--signal)}
.deck b{font-family:var(--data);font-weight:500;font-size:.66rem;letter-spacing:.18em;color:var(--signal-lit);
  text-transform:uppercase;white-space:nowrap;margin-right:auto}

/* --- section numbering --- */
.sec-head .no{font-family:var(--data);font-size:.7rem;letter-spacing:.16em;color:var(--signal)}
.light .sec-head .no{color:var(--signal)}

/* --- the two halves --- */
/* two columns of one argument, divided by a rule — not two cards */
.halves{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));gap:0;
  background:none;border:none;border-top:1px solid var(--rule)}
.half{background:none;padding:clamp(1.3rem,3vw,1.9rem) clamp(1.4rem,3vw,2.4rem)
  clamp(1.3rem,3vw,1.9rem) 0;display:flex;flex-direction:column;gap:1rem}
.half + .half{border-left:1px solid var(--rule);padding-left:clamp(1.4rem,3vw,2.4rem)}
.light .halves{background:none;border-top-color:#C9D3E0}
.light .half{background:none}
.light .half + .half{border-left-color:#DCE3EC}
@media (max-width:700px){
  .half + .half{border-left:none;border-top:1px solid var(--rule);padding-left:0}
  .light .half + .half{border-top-color:#DCE3EC}
}
.half h3{font-family:var(--display);font-weight:400;font-size:clamp(1.3rem,2.6vw,1.7rem);margin:0}
.half p{margin:0;color:#B9C4D4;font-size:.97rem}
.light .half p{color:#41506B}
.half ul{margin:.2rem 0 0;padding-left:1.05rem;color:#B9C4D4;font-size:.93rem;display:grid;gap:.35rem}
.light .half ul{color:#41506B}
.half .hn{font-family:var(--data);font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim);border-top:1px solid var(--rule);padding-top:.7rem;margin-top:auto}
.light .half .hn{border-top-color:#D3DCE8;color:#5C6B87}
.joint{margin:clamp(1.6rem,4vw,2.4rem) 0 0;font-size:clamp(1rem,2vw,1.14rem);max-width:64ch;color:#C4CEDD}
.light .joint{color:#2A3852}
.joint b{color:var(--beam);font-weight:400}
.light .joint b{color:#00081F;font-weight:500}

/* --- cargo reference --- */
.filters{display:flex;flex-wrap:wrap;gap:0 1.5rem;margin:0 0 clamp(.9rem,2vw,1.2rem);
  border-bottom:1px solid #DCE3EC}
.chip{font-family:var(--data);font-size:.68rem;letter-spacing:.13em;text-transform:uppercase;
  /* filters read as a register index line, not a row of pills */
  padding:.3rem 0 .34rem;border:none;border-bottom:2px solid transparent;background:transparent;
  color:#4B5B78;cursor:pointer;transition:color .15s,border-color .15s}
.chip:hover{color:#00081F;border-bottom-color:#B9C6D8}
.chip[aria-pressed="true"]{background:transparent;color:#00081F;border-bottom-color:#C2001A}
.chip:focus-visible{outline:2px solid #C2001A;outline-offset:3px}
/* Cargo register — a ruled ledger, not a card grid. Rows share one column
   grid so every figure lines up down the page; hairline rules do the dividing,
   no fills, no boxes. Line numbers count VISIBLE rows only, so filtering
   renumbers the register (hidden rows are display:none, so the counter skips). */
.cargo-grid{display:block;background:none;border:none;border-top:1px solid #B9C6D8;
  counter-reset:ln}
.cg{background:none;border-bottom:1px solid #DCE3EC;animation:cgin .28s ease-out both}
.cg:nth-child(5n){border-bottom-color:#B9C6D8}
@keyframes cgin{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion:reduce){.cg{animation:none}}
.cg[hidden]{display:none}
/* one line per grade; the detail lives in the grade's spec sheet PDF, last column */
.cg{display:grid;
  grid-template-columns:2.6rem minmax(0,16rem) minmax(0,1fr) minmax(0,16rem) 6.4rem;
  column-gap:1.4rem;align-items:baseline;padding:.62rem 0}
.cg:hover{background:#E7EDF5}
.cg::before{counter-increment:ln;content:counter(ln,decimal-leading-zero);
  font-family:var(--data);font-size:.7rem;color:#94A2B8;font-variant-numeric:tabular-nums}
.cg .dl{font-family:var(--data);font-size:.66rem;letter-spacing:.06em;text-align:right;
  white-space:nowrap}
.cg .dl a{color:#C2001A;text-decoration:none;border-bottom:1px solid rgba(194,0,26,.35)}
.cg .dl a:hover{border-bottom-color:#C2001A}
.cg .dl a:focus-visible{outline:2px solid #C2001A;outline-offset:2px}
.cg .nm{font-family:var(--display);font-weight:400;font-size:1.06rem;color:#00081F;
  display:flex;align-items:baseline;gap:.5rem;flex-wrap:wrap}
.cg .sz,.cg .dn,.cg .hn{font-family:var(--data);font-size:.72rem;color:#4B5B78;line-height:1.4}
.cg .dn{font-variant-numeric:tabular-nums}
.cg .hn{color:#5C6B87;border-left:2px solid #C2001A;padding-left:.55rem;
  text-transform:uppercase;letter-spacing:.08em;font-size:.62rem}
.cg .det{display:grid;grid-template-columns:2.6rem minmax(0,15rem) minmax(0,1fr);
  column-gap:1.4rem;padding:0 0 1rem}
.cg .det dl{grid-column:2}
.cg .det .carr{grid-column:3;margin-top:.7rem;padding-top:.6rem;border-top:1px solid #DCE3EC}
.cg .det .carr .imp{margin:.2rem 0 0}
/* IMSBC group reads as a marginal annotation, not a pill */
.grp{font-family:var(--data);font-size:.62rem;letter-spacing:.12em;white-space:nowrap;
  border:none;background:none;padding:0}
.grp.a{color:#8A1D00}
.grp.b{color:#7A4A00}
.grp.c{color:#4B5B78}
.cg dl{margin:0;display:grid;grid-template-columns:4.6rem 1fr;gap:.1rem .7rem;
  font-family:var(--data);font-size:.74rem;color:#41506B}

/* product-family headings: a buyer scans these before reading any card */
.subh{font-family:var(--display);font-weight:400;font-size:1.5rem;color:#00081F;margin:3rem 0 .6rem}
.refbox{border-top:1px solid #00081F;margin-top:2.4rem}
.refbox > summary.subh{list-style:none;cursor:pointer;margin:0;padding:1rem 0;
  display:flex;justify-content:space-between;align-items:baseline}
.refbox > summary.subh::-webkit-details-marker{display:none}
.refbox > summary.subh i{font-style:normal;font-family:var(--data);font-size:.72rem;
  color:#4B5B78;font-variant-numeric:tabular-nums}
.refbox > summary.subh i::after{content:" +";color:#C2001A}
.refbox[open] > summary.subh i::after{content:" \2212"}
.refbox > summary.subh:hover{color:#C2001A}
.refbox > summary.subh:focus-visible{outline:2px solid #C2001A;outline-offset:3px}
.refbox[open] > summary.subh{color:#C2001A}
.stow-grid,.ref-grid{margin-top:1.2rem;border-top:1px solid #00081F}
.ref-grid .rh,.ref-grid .rr{display:grid;
  grid-template-columns:minmax(0,11rem) minmax(0,15rem) minmax(0,1fr);
  column-gap:1.4rem;padding:.62rem 0;border-bottom:1px solid #DCE3EC;align-items:baseline}
.ref-grid .rh{font-family:var(--data);font-size:.66rem;letter-spacing:.11em;text-transform:uppercase;color:#4B5B78}
.ref-grid .rr .r1{font-family:var(--display);font-size:1rem;color:#00081F}
.ref-grid .rr span:not(.r1){font-family:var(--data);font-size:.72rem;color:#41506B;line-height:1.5}
.ref-grid .rr .r2{font-variant-numeric:tabular-nums;color:#16233C}
.ref-grid .rr em{display:block;font-style:normal;color:#8A1D00;margin-top:.2rem;font-size:.68rem}
@media (max-width:900px){
  .ref-grid .rh{display:none}
  .ref-grid .rr{grid-template-columns:1fr;gap:.2rem}
}
.stow-grid .sh,.stow-grid .sr{display:grid;
  grid-template-columns:minmax(0,11rem) minmax(0,6rem) minmax(0,8rem) minmax(0,9rem) minmax(0,1fr);
  column-gap:1.2rem;padding:.6rem 0;border-bottom:1px solid #DCE3EC;align-items:baseline}
.stow-grid .sh{font-family:var(--data);font-size:.66rem;letter-spacing:.11em;text-transform:uppercase;color:#4B5B78}
.stow-grid .sr .c1{font-family:var(--display);font-size:1rem;color:#00081F}
.stow-grid .sr span:not(.c1){font-family:var(--data);font-size:.72rem;color:#41506B;line-height:1.5}
.stow-grid .sr .c3,.stow-grid .sr .c4{font-variant-numeric:tabular-nums;color:#16233C}
@media (max-width:900px){
  .stow-grid .sh{display:none}
  .stow-grid .sr{grid-template-columns:1fr;gap:.15rem}
  .stow-grid .sr .c2,.stow-grid .sr .c3,.stow-grid .sr .c4{display:inline-block;margin-right:1rem}
}
.cgroup{border:none}
.cgroup[hidden]{display:none}
.cgh{list-style:none;cursor:pointer;grid-column:1/-1;margin:1.9rem 0 0;padding:0 0 .5rem;
  font-family:var(--data);font-size:.68rem;font-weight:400;letter-spacing:.16em;
  text-transform:uppercase;color:#00081F;border-bottom:1px solid #00081F;
  display:flex;justify-content:space-between;align-items:baseline}
.cgh:first-child{margin-top:0}
.cgh::-webkit-details-marker{display:none}
.cgh i{font-style:normal;color:#4B5B78;font-variant-numeric:tabular-nums}
.cgh i::after{content:" +";color:#C2001A}
.cgroup[open] .cgh i::after{content:" \2212"}
.cgh:hover{color:#C2001A}
.cgh:focus-visible{outline:2px solid #C2001A;outline-offset:3px}
.cgh[hidden]{display:none}
/* what the buyer has to state, and how it moves */
.cg .trade,.cg .ospec{grid-column:3;margin-top:.7rem;padding-top:.6rem;border-top:1px solid #DCE3EC}
.cg .ospec .tv em{font-style:normal;color:#00081F;background:linear-gradient(transparent 78%,rgba(194,0,26,.16) 0)}
.cg .tl{font-family:var(--data);font-size:.62rem;letter-spacing:.11em;text-transform:uppercase;color:#94A2B8}
.cg .tv{margin:.2rem 0 .5rem;font-family:var(--data);font-size:.74rem;line-height:1.5;color:#16233C}
.cg .tv:last-child{margin-bottom:0}
.cg dt{color:#94A2B8;letter-spacing:.06em;font-size:.66rem;text-transform:uppercase;padding-top:.1rem}
.cg dd{margin:0;color:#16233C;font-variant-numeric:tabular-nums}
.cg .imp{margin:0;font-size:.9rem;line-height:1.52;color:#41506B}
.cg .orig{grid-column:3;margin-top:.7rem;padding-top:.6rem;border-top:1px solid #DCE3EC}
.cg .ol{font-family:var(--data);font-size:.62rem;letter-spacing:.11em;text-transform:uppercase;color:#94A2B8}
.cg .ov{margin:.2rem 0 0;font-family:var(--data);font-size:.74rem;line-height:1.5;color:#16233C}
.cg .ov em{display:block;margin-top:.3rem;font-family:var(--body);font-style:normal;
  font-size:.84rem;color:#5C6B87}
@media (max-width:900px){
  /* below 900 the line stacks: number in column 1, everything else in column 2 */
  .cg{grid-template-columns:2.2rem minmax(0,1fr);column-gap:1rem;row-gap:.25rem}
  .cg .sz,.cg .dn,.cg .hn,.cg .dl{grid-column:2}
  .cg .dl{text-align:left;margin-top:.15rem}
}
.count{font-family:var(--data);font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;color:#5C6B87;
  margin:.9rem 0 0}

/* --- explainer panels --- */
.panels{display:grid;grid-template-columns:1fr;gap:clamp(1.5rem,4vw,2.6rem);margin-top:clamp(2rem,5vw,3rem)}
@media (min-width:860px){.panels{grid-template-columns:1fr 1fr;gap:clamp(2rem,4vw,3.4rem)}}
.panel h3{font-family:var(--display);font-weight:400;font-size:1.24rem;margin:0 0 .5rem;color:#00081F}
.panel p{margin:0 0 .6rem;color:#41506B;font-size:.95rem}
.panel .key{font-family:var(--data);font-size:.74rem;letter-spacing:.1em;color:#00081F;
  border-left:2px solid var(--signal);padding-left:.7rem;display:block}

/* --- calculator --- */
.calc{display:grid;grid-template-columns:minmax(0,320px) minmax(0,1fr);gap:1px;background:var(--rule);
  border:1px solid var(--rule)}
.calc>*{background:#01091C;padding:clamp(1.2rem,3vw,1.9rem)}
@media (max-width:820px){.calc{grid-template-columns:1fr}}
.ctrl{display:grid;gap:1.35rem;align-content:start}
.ctrl label{display:grid;gap:.45rem;font-family:var(--data);font-size:.7rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--dim)}
.ctrl output{font-family:var(--data);font-size:1.5rem;color:var(--beam);letter-spacing:.01em}
input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:2px;background:#26405F;outline:none}
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;background:var(--signal);
  border:2px solid #00081F;cursor:pointer;border-radius:0}
input[type=range]::-moz-range-thumb{width:14px;height:14px;background:var(--signal);border:2px solid #00081F;
  cursor:pointer;border-radius:0}
/* A grid, not a flex row. Flex gave two bad outcomes in turn: dividing the row evenly
   crushed five material labels to zero padding, and letting them wrap stretched the
   odd one out into a full-width bar of its own. Equal grid tracks that reflow keep
   every button the same size whether the row holds two or five. */
.seg{display:grid;grid-template-columns:repeat(auto-fit,minmax(2.9rem,1fr));gap:1px;
  background:#26405F;border:1px solid #26405F}
.seg button{width:100%;background:#01091C;border:0;color:#8FA0B8;font-family:var(--data);
  font-size:.74rem;padding:.55rem .25rem;cursor:pointer;white-space:nowrap;letter-spacing:0}
.seg button[aria-pressed="true"]{background:var(--signal);color:#fff}
.seg button:disabled{opacity:.4;cursor:not-allowed}
.verdict{margin:0;font-size:.95rem;color:#B9C4D4;border-top:1px solid var(--rule);padding-top:1rem}
.verdict b{color:var(--beam);font-weight:400}
.curve{display:block;width:100%;height:auto}
.curve .axis{stroke:#26405F;stroke-width:1}
.curve .gridl{stroke:#152C4A;stroke-width:1}
.curve .path{fill:none;stroke:#7FA0CE;stroke-width:2.5;vector-effect:non-scaling-stroke}
.curve .path.ghost{stroke:#33507F;stroke-width:1.5;stroke-dasharray:5 5}
.curve .marker{fill:var(--signal)}
.curve text{font-family:var(--data);font-size:13px;fill:#6E8BB8}
.curve text.big{fill:#B8CDEA;font-size:15px}
.outs{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:1px;background:var(--rule);
  border:1px solid var(--rule);border-top:0}
.outs div{background:#01091C;padding:.85rem clamp(.8rem,2vw,1.3rem);display:flex;flex-direction:column;gap:.28rem}
.outs b{font-family:var(--data);font-weight:500;font-size:1.05rem;color:var(--beam)}
.outs b.warn{color:var(--signal)}

/* --- occupancy split bar --- */
.split{display:flex;height:56px;border:1px solid #D3DCE8;margin-top:clamp(1.4rem,3vw,2rem);overflow:hidden}
.split div{display:flex;align-items:center;justify-content:center;font-family:var(--data);font-size:.72rem;
  letter-spacing:.08em;color:#fff;position:relative}
.split .s1{background:#B9C4D4;color:#16233C}
.split .s2{background:#7C8BA5}
.split .s3{background:#0E3A63}
.split .s4{background:#8A1D00}
.splitkey{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,190px),1fr));gap:1rem 2rem;
  margin-top:1.1rem}
.splitkey div{display:flex;gap:.6rem;align-items:flex-start;font-size:.88rem;color:#41506B}
.splitkey i{width:10px;height:10px;margin-top:.35rem;flex:0 0 auto}

/* --- ledger table (productivity worked example) --- */
.ledger{width:100%;border-collapse:collapse;font-family:var(--data);font-size:.86rem;
  margin-top:clamp(1.4rem,3vw,2rem)}
.ledger th,.ledger td{border-bottom:1px solid #D3DCE8;padding:.62rem .7rem;text-align:right}
.ledger th:first-child,.ledger td:first-child{text-align:left;font-family:var(--body);font-weight:400}
.ledger thead th{color:#5C6B87;font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;font-weight:500}
.ledger tr.rule-row td{border-top:1px solid #00081F;font-weight:500;color:#00081F}
.ledger td.up{color:#0E5B2E}.ledger td.down{color:#8A1D00}
.scrollx{overflow-x:auto}
.form{display:grid;grid-template-columns:1fr 1fr;gap:1.1rem 1.4rem;margin-top:clamp(1.6rem,4vw,2.4rem);
  max-width:760px}
.form .wide{grid-column:1/-1}
.form label{display:grid;gap:.4rem;font-family:var(--data);font-size:.68rem;letter-spacing:.14em;
  text-transform:uppercase;color:#5C6B87}
.form input,.form select,.form textarea{font-family:var(--body);font-size:1rem;color:#0E1830;
  background:#fff;border:1px solid #C3CEDE;padding:.72rem .8rem;width:100%;border-radius:0;
  transition:border-color .15s}
.form textarea{min-height:132px;resize:vertical;line-height:1.55}
.form input:focus,.form select:focus,.form textarea:focus{outline:none;border-color:var(--signal)}
.form .hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.form .file{grid-column:1/-1;display:grid;gap:.5rem}
.form .file input[type=file]{position:absolute;left:-9999px}
.form .file .pick{justify-self:start;font-family:var(--data);font-size:.7rem;letter-spacing:.14em;
  text-transform:uppercase;border:1px solid #C3CEDE;background:#fff;color:#00081F;padding:.7rem 1.3rem;
  cursor:pointer;transition:border-color .15s,color .15s}
.form .file .pick:hover{border-color:var(--signal);color:var(--signal)}
.form .file input[type=file]:focus-visible + .pick{outline:2px solid var(--signal);outline-offset:3px}
.form .files{list-style:none;margin:0;padding:0;display:grid;gap:.3rem;font-family:var(--data);
  font-size:.76rem;color:#41506B}
.form .files li{display:flex;gap:.6rem;align-items:baseline}
.form .files b{font-weight:400;color:#00081F;word-break:break-all}
.form .files button{all:unset;cursor:pointer;color:#8A1D00;font-size:.7rem;letter-spacing:.1em;
  text-transform:uppercase;padding:0}
.form .files button:hover{text-decoration:underline}
.form button{justify-self:start;font-family:var(--data);font-size:.74rem;letter-spacing:.18em;
  text-transform:uppercase;background:#00081F;color:#EEF2F7;border:1px solid #00081F;
  padding:.85rem 1.9rem;cursor:pointer;transition:background .15s,color .15s}
.form button:hover{background:var(--signal);border-color:var(--signal)}
.form button[disabled]{opacity:.55;cursor:default}
.formnote{grid-column:1/-1;font-size:.86rem;color:#41506B;margin:.2rem 0 0}
.formstat{grid-column:1/-1;font-family:var(--data);font-size:.8rem;letter-spacing:.08em;margin:.2rem 0 0;
  padding-left:.75rem;border-left:2px solid #C3CEDE;color:#41506B;min-height:1.2em}
.formstat.ok{border-color:#0E5B2E;color:#0E5B2E}
.formstat.err{border-color:var(--signal);color:#8A1D00}
@media (max-width:620px){.form{grid-template-columns:1fr}}
/* --- contrast fixes: light-paper components reused inside dark sections --- */
:root{--signal-lit:#FF6B63}          /* the red, lifted to stay legible on navy */
.ops .sec-head .no,.ops .step .n{color:var(--signal-lit)}
.ops .note,.ops .splitkey div{color:#9FAEC6}
.ops .splitkey b{color:var(--beam);font-weight:400}
.ops .split{border-color:#26405F}
.ops .split .s1{background:#B9C4D4;color:#0E1830}
.ops .split .s2{background:#7C8BA5;color:#0B1425}
.ops .split .s3{background:#16456F;color:#E8F0F8}
.ops .split .s4{background:#8A1D00;color:#FFE7E1}
.ops .ledger th,.ops .ledger td{border-bottom-color:#26405F;color:#C4CEDD}
.ops .ledger thead th{color:#9FAEC6}
.ops .ledger tr.rule-row td{border-top-color:#7FA0CE;color:var(--beam)}
.ops .ledger td.up{color:#6FD08C}
.ops .ledger td.down{color:#FF8F86}
.ops .outs b.warn{color:var(--signal-lit)}
.ops .verdict{color:#C4CEDD}
.cg dt{color:#5C6B87}

/* ---------- berth section: drawing-office plate, drawn to scale ---------- */
.bs{display:grid;grid-template-columns:minmax(0,300px) minmax(0,1fr);gap:1px;background:var(--rule);
  border:1px solid var(--rule);margin-top:clamp(1.5rem,4vw,2.4rem)}
.bs>*{background:#01091C;padding:clamp(1.1rem,2.6vw,1.7rem)}
@media (max-width:900px){.bs{grid-template-columns:1fr}}
.bs-ctrl{display:grid;gap:1.15rem;align-content:start}
.bs-ctrl label{display:grid;gap:.4rem;font-family:var(--data);font-size:.68rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--dim)}
.bs-ctrl label[hidden]{display:none}
.bs-ctrl output{font-family:var(--data);font-size:1.35rem;color:var(--beam)}
.bs-draw{padding:0;background:#010A1E}
/* On a phone a 1600x900 plate scales down to about 200 px tall and the labels die.
   Give the drawing a minimum width and let the visitor pan it, the way you would
   move a paper drawing under your eye. The PAGE still never scrolls sideways. */
@media (max-width:700px){
  .bs-draw{overflow-x:auto;-webkit-overflow-scrolling:touch}
  #berthSvg{min-width:820px}
  .bs-draw.has-section::after{content:"DRAG THE PLATE SIDEWAYS";position:sticky;left:0;display:block;
    padding:.4rem .8rem;font-family:var(--data);font-size:.6rem;letter-spacing:.14em;color:#6E8BB8}
}
#berthSvg{display:block;width:100%;height:auto}
#berthSvg[hidden]{display:none}
.bs-model{position:relative;width:100%;aspect-ratio:16/9;background:#01091C}
/* On a phone a 16:9 model is a 200 px strip. Give it portrait proportions so the
   terminal actually reads, since this is the first thing a visitor meets. */
@media (max-width:700px){.bs-model{aspect-ratio:4/5}}
.bs-model[hidden]{display:none}
.bs-model canvas{display:block;width:100%;height:100%;touch-action:pan-y pinch-zoom}
.bs-touch-controls{display:flex;flex-wrap:wrap;gap:8px;padding:12px}
.bs-touch-controls[hidden],#modelStill[hidden]{display:none}
.bs-touch-controls button,#bsLightweight,#bsView button{min-height:48px;min-width:48px}
.bs-touch-controls button,#bsLightweight{font:inherit;font-size:.85rem;color:#E4EDF8;
  background:#142A49;border:1px solid #6E8BB8;padding:10px 14px;cursor:pointer}
.bs-touch-controls button:focus-visible,#bsLightweight:focus-visible{outline:2px solid #E4EDF8;outline-offset:3px}
#bsExplore[aria-pressed="true"]{background:#24405F}
#bsLightweight{display:block;margin:0 12px 12px;max-width:calc(100% - 24px)}
.bs-model .hint{position:absolute;left:14px;right:14px;bottom:12px;font-family:var(--data);font-size:.66rem;
  letter-spacing:.08em;text-transform:uppercase;color:#B9CCE6;pointer-events:none}
.bs-model .fallback{position:absolute;inset:0;display:grid;place-items:center;padding:2rem;
  text-align:center;font-family:var(--data);font-size:.8rem;color:#8FA0B8}
#modelStill{margin:0;display:block}
#modelStill img{display:block;width:100%;height:auto}
#modelStill figcaption{font-family:var(--data);font-size:.66rem;letter-spacing:.14em;
  text-transform:uppercase;color:#6E8BB8;padding:.6rem .9rem}
/* line grammar: one weight for structure, one for detail, one for dimensions */
#berthSvg .ln{fill:none;stroke:#8FB0DC;stroke-width:1.7;stroke-linejoin:miter;vector-effect:non-scaling-stroke}
#berthSvg .ln.heavy{stroke:#D7E5F6;stroke-width:2.6}
#berthSvg .hair{stroke:#3F5E8C;stroke-width:1;fill:none;vector-effect:non-scaling-stroke}
#berthSvg .dim{stroke:#7E93B4;stroke-width:1;vector-effect:non-scaling-stroke}
#berthSvg .axis{stroke:#5A7398;stroke-width:1;vector-effect:non-scaling-stroke}
#berthSvg .tide{stroke:#2F5580;stroke-width:1;stroke-dasharray:7 6;vector-effect:non-scaling-stroke}
#berthSvg .datum{stroke:#C9553F;stroke-width:1.3;stroke-dasharray:14 6;vector-effect:non-scaling-stroke}
#berthSvg .wlline{stroke:#7FB6E8;stroke-width:1.6;vector-effect:non-scaling-stroke}
#berthSvg .sea{fill:#07203C;opacity:.55}
#berthSvg .bed{fill:#0C1B30;stroke:none}
#berthSvg .fill{fill:#0A1526;stroke:none}
#berthSvg .hullfill{fill:#020C1F;stroke:none}
#berthSvg .cargo{fill:#24405F;opacity:.85}
#berthSvg .coam{fill:#33507F;opacity:.9}
#berthSvg .fender{fill:#31465F}
#berthSvg .flag.ok{fill:#4FA86B}
#berthSvg .tb{fill:#020F22;stroke:#5A7398;stroke-width:1}
#berthSvg .want{stroke:var(--signal-lit);stroke-width:1.4;stroke-dasharray:10 6;vector-effect:non-scaling-stroke}
#berthSvg .clashfill{fill:url(#clashHatch)}
#berthSvg .bt.clash{fill:#FF6B63;font-size:13px;letter-spacing:.12em}
#berthSvg .boot{stroke:#6E4A46;stroke-width:1.2;vector-effect:non-scaling-stroke}
#berthSvg .envelope{fill:none;stroke:#4E7DB5;stroke-width:1.2;stroke-dasharray:6 7;vector-effect:non-scaling-stroke;opacity:.85}
#berthSvg .digline{stroke:#4E7DB5;stroke-width:1.2;stroke-dasharray:12 6;vector-effect:non-scaling-stroke}
#berthSvg .hitzone{fill:url(#hitHatch);stroke:#4E7DB5;stroke-width:1;stroke-dasharray:5 5}
#berthSvg .ukcband{fill:#2E7D53;opacity:.30;stroke:#4FA86B;stroke-width:1}
/* a live sea: three wave trains drifting at different rates */
#berthSvg .swell{fill:none;stroke:#7FB6E8;stroke-width:1.2;vector-effect:non-scaling-stroke}
#berthSvg .swell.s1{opacity:.55;animation:drift1 19s linear infinite}
#berthSvg .swell.s2{opacity:.38;animation:drift2 13s linear infinite}
#berthSvg .swell.s3{opacity:.24;animation:drift3 8s linear infinite}
@keyframes drift1{to{transform:translateX(-150px)}}
@keyframes drift2{to{transform:translateX(88px)}}
@keyframes drift3{to{transform:translateX(-52px)}}
@media (prefers-reduced-motion:reduce){#berthSvg .swell{animation:none}}
#berthSvg .bed{fill:url(#bedHatch)}
#berthSvg .flag.bad{fill:var(--signal-lit)}
#berthSvg .bt{font-family:var(--data);font-size:15px;fill:#AFC3DD;letter-spacing:.04em}
#berthSvg .bt.val{font-size:20px;fill:#E4EDF8}
#berthSvg .bt.sm{font-size:12.5px;fill:#7E93B4;letter-spacing:.14em}
.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}

/* --- stacking diagrams --- */
/* four stacking methods as a plate row: rules divide them, nothing boxes them */
.methods{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:0;
  background:none;border:none;border-top:1px solid #C9D3E0;border-bottom:1px solid #C9D3E0;
  margin-top:clamp(1.4rem,3vw,2rem)}
.method{background:none;padding:1.2rem 1.25rem 1.2rem 0;display:flex;flex-direction:column;gap:.65rem}
.method + .method{border-left:1px solid #DCE3EC;padding-left:1.25rem}
@media (max-width:700px){
  .method + .method{border-left:none;border-top:1px solid #DCE3EC;padding-left:0}
}
.method h3{font-family:var(--display);font-weight:400;font-size:1.15rem;margin:0;color:#00081F}
.method p{margin:0;font-size:.9rem;color:#41506B}
.method svg{display:block;width:100%;height:auto;background:none;border:none;
  border-bottom:1px solid #DCE3EC}
.method .hn{font-family:var(--data);font-size:.66rem;letter-spacing:.11em;text-transform:uppercase;
  color:#5C6B87;border-top:1px solid #E4EAF2;padding-top:.55rem;margin-top:auto}
.lay{fill:none;stroke-width:3;vector-effect:non-scaling-stroke;stroke-linecap:round}
.lay.a{stroke:#0E3A63}.lay.b{stroke:#8FA8D4}.lay.c{stroke:#D80000;opacity:.75}
.ground{stroke:#B9C4D4;stroke-width:2}

/* --- dust classes --- */
.classes{display:grid;gap:1px;background:#D3DCE8;border:1px solid #D3DCE8;
  font-family:var(--data);font-size:.84rem;margin-top:clamp(1.4rem,3vw,2rem)}
.classes>div{background:#fff;display:grid;grid-template-columns:70px 1.3fr 1.6fr;gap:1rem;
  padding:.75rem clamp(.9rem,2vw,1.4rem);align-items:baseline}
.classes .hd{color:#5C6B87;font-size:.68rem;letter-spacing:.14em;text-transform:uppercase}
.classes b{color:#00081F;font-weight:500}
.classes span:last-child{color:#41506B;font-family:var(--body);font-size:.9rem}
@media (max-width:640px){.classes>div{grid-template-columns:56px 1fr}.classes span:last-child{grid-column:1/-1}}

/* --- engagement steps --- */
.steps{display:grid;gap:1px;background:var(--rule);border:1px solid var(--rule);
  margin-top:clamp(1.6rem,4vw,2.4rem)}
.step{background:var(--ink);display:grid;grid-template-columns:auto 1fr;gap:clamp(1rem,3vw,2.2rem);
  padding:clamp(1.2rem,3vw,1.9rem) clamp(1.2rem,3vw,2rem)}
.step .n{font-family:var(--data);font-size:.72rem;letter-spacing:.16em;color:var(--signal);padding-top:.25rem}
.step h3{font-family:var(--display);font-weight:400;font-size:1.22rem;margin:0 0 .4rem}
.step p{margin:0;color:#B9C4D4;font-size:.95rem;max-width:70ch}
.step .out{font-family:var(--data);font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--dim);margin-top:.6rem;display:block}

/* --- reveal on scroll --- */
.rv{opacity:0;transform:translateY(14px);transition:opacity .7s cubic-bezier(.16,.9,.24,1),transform .7s cubic-bezier(.16,.9,.24,1)}
.rv.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.rv{opacity:1;transform:none;transition:none}
  .cg{animation:none}}

/* ---------- two-door root + track header ---------- */
.doors{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,22rem),1fr));
  gap:1px;background:#B9C6D8;border:1px solid #B9C6D8;margin:2rem 0 1.4rem}
.door{background:#F0F3F7;padding:2rem 1.8rem 1.6rem;text-decoration:none;display:flex;
  flex-direction:column;gap:.7rem;transition:background .18s ease}
.door:hover,.door:focus-visible{background:#E7EDF5;outline:none}
.door:focus-visible{box-shadow:inset 0 0 0 2px #C2001A}
.door .dnum{font-family:var(--data);font-size:.66rem;letter-spacing:.14em;color:#4B5B78}
.door h3{font-family:var(--display);font-weight:400;font-size:1.9rem;color:#00081F;margin:0}
.door p{margin:0;color:#41506B;line-height:1.55;max-width:34rem}
.door .proof{font-family:var(--data);font-size:.68rem;line-height:1.6;color:#5C6B87;
  border-top:1px solid #DCE3EC;padding-top:.7rem;margin-top:.3rem}
.door .go{font-family:var(--data);font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;
  color:#C2001A;display:flex;align-items:center;gap:.5rem;margin-top:auto;padding-top:.8rem}
.door .go i{width:1.6rem;height:1px;background:#C2001A;transition:width .18s ease}
.door:hover .go i{width:2.6rem}
/* Three tracks so the middle one is CENTRED ON THE BAR, not merely between its
   neighbours: with space-between, a wide nav would push the clocks off-centre and the
   two pages would disagree with each other. 1fr/auto/1fr keeps them aligned. */
header.bar{position:sticky;top:0;z-index:60;display:grid;
  grid-template-columns:1fr auto 1fr;align-items:center;gap:1.5rem;
  padding:.7rem 1.6rem;background:#00081F;color:#F0F3F7}
/* ⚠ All three are pinned to ROW 1. Auto-placement fills forward only: the nav takes
   column 3 first (it precedes the widget in the DOM), and the widget then cannot go
   back to column 2 of the same row, so it dropped to a second row and the bar grew from
   ~52px to 98px. Measured, not guessed. */
header.bar>.markh{grid-column:1;grid-row:1;justify-self:start}
header.bar>.clocks,header.bar>.fx{grid-column:2;grid-row:1;justify-self:center}
header.bar>.track{grid-column:3;grid-row:1;justify-self:end}
header.bar .mark{text-decoration:none;color:#F0F3F7;display:flex;align-items:baseline;gap:.6rem}
/* ⚠ OPEN DEFECT, 2026-09-12: this h1's box does not contain its own content. The grid
   item computes to 170px while the .mark flex inside runs to 280px — 110px outside its
   own box at 1440, 27px at tablet. It does NOT collide today only because column 2 starts
   further right, so moving anything in this bar could expose it. `width:max-content` was
   tried and the used width stayed 170px, so the clamp is somewhere else and needs proper
   investigation rather than a guess. The overspill probe is pointed away from header.bar
   until this is fixed — see SPILL_IN in tools/ui-check.py. */
header.bar .markh{margin:0;font-weight:400;font-size:inherit;line-height:1}
header.bar .mark .name{font-family:var(--display);font-size:1.05rem}
header.bar .mark .name em{font-style:normal;color:#C2001A}
header.bar .mark .sub{font-family:var(--data);font-size:.6rem;letter-spacing:.14em;
  text-transform:uppercase;color:#94A2B8}
header.bar .track{display:flex;gap:1.2rem;font-family:var(--data);font-size:.66rem;
  letter-spacing:.11em;text-transform:uppercase}
header.bar .track .on{color:#F0F3F7;border-bottom:2px solid #C2001A;padding-bottom:2px}
header.bar .track a{color:#94A2B8;text-decoration:none;padding-bottom:2px;
  border-bottom:1px solid transparent}
header.bar .track a:hover,header.bar .track a:focus-visible{color:#F0F3F7;border-bottom-color:#F0F3F7}
/* --- header desk clocks (terminals) and USD reference rates (commodities) --- */
.clocks,.fx{display:flex;flex-wrap:wrap;align-items:baseline;gap:.8rem;
  font-family:var(--data);font-size:.5rem;letter-spacing:.08em;color:#94A2B8}
.clk,.fxq{display:inline-flex;align-items:baseline;gap:.35rem;white-space:nowrap;
  font-variant-numeric:tabular-nums;color:#C3CEDE}
.clk i,.fxq i{font-style:normal;color:#7E8DA8;font-size:.46rem}
/* a desk that is closed reads dimmer — the time is still true, the desk is not staffed.
   ⚠ #5C6B87 measures 3.71:1 on this bar and fails WCAG AA for small text; #7E8DA8 is
   5.94:1. axe caught the first attempt, 4 nodes per viewport. */
.clk.off{color:#7E8DA8}
.fxl{color:#7E8DA8}
/* one clean row; the source and timestamp live on the title/aria-label instead */
.fxrow{display:flex;flex-wrap:wrap;align-items:baseline;gap:.8rem;justify-content:center}
@media (max-width:900px){.clocks,.fx{gap:.5rem;font-size:.48rem}}
/* the provenance line stays at every width: it is what stops the row reading as a
   live market feed. It was hidden below 520px in the first cut — wrong call. */

/* At 360px the wordmark and both business links do not fit one row: the bar is a
   no-wrap flex, so the track ran 18px past the viewport and the whole page scrolled
   sideways. Tighten the gutters and let the bar wrap onto a second row. */
@media (max-width:420px){
  /* below 420 the three-track grid cannot hold: stack to two rows, mark and nav on the
     first, the clocks/rates spanning underneath. */
  header.bar{grid-template-columns:1fr auto;gap:.4rem .9rem;padding:.6rem 1rem}
  /* ⚠ grid-row MUST be reset here. The base rules pin all three children to grid-row:1;
     overriding only grid-column left the rates/clocks strip spanning 1/-1 on ROW ONE, i.e.
     printed underneath the wordmark and the nav. On a phone that rendered as three layers
     of text on top of each other — reported from a real handset 2026-09-12, and missed by
     the desktop sweep because it tests overflow, not collision. */
  header.bar>.markh{grid-column:1;grid-row:1}
  header.bar>.track{grid-column:2;grid-row:1}
  header.bar>.clocks,header.bar>.fx{grid-column:1/-1;grid-row:2;justify-self:start}
  header.bar .track{gap:.9rem;font-size:.6rem;letter-spacing:.08em;flex-wrap:wrap}
  header.bar .mark .sub{font-size:.55rem;letter-spacing:.1em}
}

/* ---------- hero entries: the tagline is the door ---------- */
/* positioned off the hero, not off the wordmark block: growing a child of .centre
   pushed the whole centred block up and clipped the wordmark off the top. */
.hero .entries{position:static;margin:0;opacity:0;
  /* 2026-09-12: was absolutely positioned at top:78%, which made .centre's transform
     its containing block — lifting .centre dragged the links across the tower, and
     chasing it with offsets put them through the wordmark. Back in normal flow, so
     the wordmark and links are ONE centred group and the gap does the spacing. */
  display:flex;align-items:baseline;justify-content:center;gap:1rem;flex-wrap:wrap}
.hero .entries a{font-family:var(--display);font-size:clamp(1.05rem,2.2vw,1.6rem);
  color:#C6D2E2;text-decoration:none;padding-bottom:3px;
  border-bottom:1px solid transparent;transition:color .18s ease,border-color .18s ease;
  /* the beam washes straight through this line — hold the glyphs off the glare */
  text-shadow:0 1px 2px rgba(0,0,0,.85), 0 0 18px rgba(0,0,0,.65)}
.hero .entries a:hover,.hero .entries a:focus-visible{color:#F0F3F7;border-bottom-color:#C2001A;outline:none}
.hero .entries .sep{color:#5D7CB8;font-family:var(--display)}
/* Links last: the name lands on the beam, everything else follows it in. */
.lit .entries{animation:rise 1.1s cubic-bezier(.16,.9,.24,1) .90s both}
@media (prefers-reduced-motion:reduce){.hero .entries{opacity:1;animation:none}}
@media (max-width:560px){.hero .entries{flex-direction:column;gap:1.5rem;top:72%}
  .hero .entries .sep{display:none}}

/* root is the hero and nothing else — no scroll, no furniture below it */
body.gate,html:has(body.gate){height:100%;overflow:hidden}
body.gate .hero{height:100dvh;min-height:100dvh}

/* origins under sanction — marked wherever they appear in an origin list */
.unav{white-space:nowrap}
.unav i{font-style:normal;font-family:var(--data);font-size:.58rem;letter-spacing:.08em;
  text-transform:uppercase;color:#8A1D00;border:1px solid #D8A9A0;border-radius:2px;
  padding:1px 4px;margin-left:.35rem;vertical-align:2px;white-space:nowrap}

/* ---------- register view switch ----------
   One register, three column sets. The switch rewrites columns 3 and 4 rather than
   hiding duplicates, so the widths have to move with the content: prose in the
   Properties view, short figures under Stowage, a code plus a standards list under
   Classification. The family heading doubles as the column header. */
.views{display:flex;flex-wrap:wrap;gap:1px;margin:1.6rem 0 0;background:#C3CEDE;
  border:1px solid #C3CEDE;width:max-content;max-width:100%}
.vsw{font-family:var(--data);font-size:.68rem;letter-spacing:.13em;text-transform:uppercase;
  background:#fff;border:0;color:#4B5B78;padding:.6rem 1.1rem;cursor:pointer;
  transition:color .15s,background .15s}
.vsw:hover{color:#00081F}
.vsw[aria-pressed="true"]{background:#00081F;color:#EEF2F7}
.vsw:focus-visible{outline:2px solid #C2001A;outline-offset:2px}
.vnote{margin-top:.9rem}
.vnote[hidden]{display:none}

/* the group heading names the columns of the lines beneath it, so its track list must
   stay identical to .cg — the two are read as one table */
/* col 5 is a FIXED track in both grids: .cgh and .cg are separate grid formatting
   contexts, so a max-content track sized by different content (a count vs a link)
   shifts every track before it and the header stops naming the column below it. */
.cgh{display:grid;
  grid-template-columns:2.6rem minmax(0,16rem) minmax(0,1fr) minmax(0,16rem) 6.4rem;
  column-gap:1.4rem;align-items:baseline}
.cgh b{grid-column:2;font-weight:400}
.cgh .ch3{grid-column:3}
.cgh .ch4{grid-column:4}
.cgh i{grid-column:5;text-align:right;white-space:nowrap}
.cgh .ch3,.cgh .ch4{font-size:.62rem;letter-spacing:.11em;color:#4B5B78}

@media (max-width:900px){
  /* No column labels below 900, so the desktop track list only squeezes the family
     name against a 6.4rem count track and wraps it over three lines. Two tracks:
     the name takes the room, the count takes what it needs. */
  .cgh .ch3,.cgh .ch4{display:none}
  /* first track stays 2.2rem, the same as .cg, so the family name starts on the same
     left edge as the grade names under it rather than flush against the page */
  .cgh{grid-template-columns:2.2rem minmax(0,1fr) max-content;column-gap:1rem}
  .cgh b{grid-column:2}
  .cgh i{grid-column:3}
}

/* download link in the row detail — not in the summary, where a nested link fights
   the disclosure toggle for the click and confuses screen readers */
.cg .det .dl{grid-column:3;margin:.7rem 0 0}
.cg .det .dl a{font-family:var(--data);font-size:.7rem;letter-spacing:.09em;
  text-transform:uppercase;color:#00081F;text-decoration:none;
  border-bottom:1px solid #C2001A;padding-bottom:.15rem}
.cg .det .dl a:hover{color:#C2001A}
.cg .det .dl a:focus-visible{outline:2px solid #C2001A;outline-offset:3px}
/* Must come AFTER the .dl rule above: a media query adds no specificity, so the
   later declaration wins regardless of viewport. Setting grid-column:2 up at line 437
   had no effect and left a third column on mobile, overflowing .det by 20px. */
@media (max-width:900px){
  .cg .det .dl{grid-column:2}
}

/* Port discharge photo strip (terminals, stockyard section). Four images on one row at
   desk width, two up on a phone. Fixed aspect so a portrait frame cannot stretch the row. */
.pstrip{margin:34px 0 0;padding:0}
.pstrip img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block;border-radius:2px}
.pstrip{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}
.pstrip figcaption{grid-column:1/-1;margin-top:10px;font-size:13px;line-height:1.45;opacity:.72}
@media (max-width:760px){.pstrip{grid-template-columns:repeat(2,1fr)}}

/* equipment landscape — ownership lineage list (terminals.html #yard) */
.lineage{margin-top:clamp(1.6rem,4vw,2.4rem);max-width:720px}
.lineage ul{list-style:none;margin:.6rem 0 0;padding:0}
.lineage li{display:grid;grid-template-columns:5.5rem 1fr;gap:1rem;padding:.7rem 0;border-bottom:1px solid #D3DCE8;color:#41506B;font-size:.95rem}
.lineage b{font-family:var(--data);font-weight:400;color:#00081F}
