/* ============================================================
   MARNY ENERGY - "HIGH-VOLTAGE INDUSTRIAL", pushed
   The page is a battery: the fixed left rail charges with
   scroll (SOC readout). Type wall hero, ghost words, plates
   with crop marks, gauge wall, verdict board.

   ONE SHAPE RULE: no diagonals, and nothing cut out of a
   photograph. A battery is stamped and folded - tabs, terminals
   and right angles. Photo plates stay whole rectangles; the blue
   crop marks at two opposite corners do the framing.

   Brand: #060F17 · #006DD3 · #E8EBEF · Montserrat.
   ============================================================ */
/* Montserrat comes from Google with display=swap, so the page paints in a
   fallback face and reflows when the real font lands. On a throttled phone that
   was worth 0.19 CLS - the display headings are enormous, so the jump is too.

   This is Arial with Montserrat's metrics stamped onto it: Montserrat runs 9.64%
   wider, so the fallback is scaled to match, and its ascent and descent are
   overridden to Montserrat's 0.968 / 0.251. The swap still happens; nothing moves.
   Every number was measured off the live font, not copied from a table. */
@font-face{
  font-family:"Montserrat fallback";
  src:local("Arial"),local("Helvetica"),local("Liberation Sans");
  size-adjust:109.64%;
  ascent-override:88.29%;
  descent-override:22.89%;
  line-gap-override:0%;
}

:root{
  --ink:#060F17; --ink-2:#0C1723;
  --paper:#E8EBEF; --paper-2:#F5F7F9;
  --line-d:rgba(232,235,239,.14); --line-l:#C9D1D9;
  --fg-d:#EDF2F7; --mut-d:#A3B1BF;
  --fg-l:#060F17; --mut-l:#44525F;
  --blu:#006DD3; --blu-b:#4BA5F2; --blu-d:#0059AC;
  --hdrH:64px; --rail:76px;
  --disp:"Montserrat","Montserrat fallback",system-ui,sans-serif;
  /* labels used to be set in a monospace face; the "technical" read now comes
     from size, letter-spacing and case alone, on the same family as everything else */
  --mono:"Montserrat","Montserrat fallback",system-ui,sans-serif;
  --ease:cubic-bezier(.16,1,.3,1);
  --s1:.5rem; --s2:1rem; --s3:1.5rem; --s4:2rem; --s5:3rem; --s6:4rem;
  --sect:clamp(4.5rem,9vh,6.5rem);
  --headgap:clamp(2.5rem,5vh,3.5rem);
  --colgap:clamp(2rem,4vw,4rem);
}
*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;text-size-adjust:100%;scroll-behavior:smooth;overflow-x:clip}
body{background:var(--ink);color:var(--fg-d);font-family:var(--disp);line-height:1.6;
  -webkit-font-smoothing:antialiased}
img{display:block;max-width:100%}
a{color:inherit}
::selection{background:rgba(0,109,211,.45)}
:focus-visible{outline:2px solid var(--blu-b);outline-offset:3px;border-radius:2px}

/* ================= THE RAIL - a battery charging with scroll ================= */
.rail{position:fixed;z-index:70;inset:0 auto 0 0;width:var(--rail);
  background:var(--ink);border-right:1px solid var(--line-d);
  display:flex;flex-direction:column;align-items:center;justify-content:space-between;
  padding:1rem 0;overflow:clip}
.rail-fill{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,109,211,.34),rgba(0,109,211,.62));
  transform:scaleY(0);transform-origin:50% 100%;pointer-events:none}
@supports (animation-timeline: scroll()){
  .rail-fill{animation:railfill linear both;animation-timeline:scroll(root)}
  @keyframes railfill{from{transform:scaleY(0)}to{transform:scaleY(1)}}
}
.rail-txt{writing-mode:vertical-rl;rotate:180deg;font-family:var(--mono);font-size:.7rem;
  letter-spacing:.22em;text-transform:uppercase;color:var(--mut-d);position:relative}
.rail-soc{font-family:var(--mono);font-size:.72rem;letter-spacing:.08em;color:var(--blu-b);
  position:relative;text-align:center}
.rail-soc b{display:block;font-size:1rem;font-weight:400}
.rail-cap{position:relative;width:22px;height:10px;border:2px solid var(--mut-d);border-bottom:0;
  border-radius:4px 4px 0 0}
.rail-cap::after{content:"";position:absolute;left:50%;top:-6px;transform:translateX(-50%);
  width:10px;height:4px;background:var(--mut-d);border-radius:2px}

/* ================= header (offset past the rail) ================= */
/* the rail only exists on the homepage, so the layout is flush by default and
   only steps aside when a rail is actually there */
.hdr{position:fixed;z-index:60;inset:0 0 auto 0;height:var(--hdrH);
  background:var(--ink);border-bottom:1px solid var(--line-d);display:flex;align-items:center}
.has-rail .hdr{left:var(--rail)}
.hdr-in{width:min(1240px,100%);margin-inline:auto;padding-inline:clamp(1.1rem,3vw,2rem);
  display:flex;align-items:center;gap:2rem}
.brand{display:flex;align-items:center;text-decoration:none}
.brand img{height:48px;width:auto}
.nav{display:flex;gap:1.6rem;margin-left:auto}
.nav a{font-size:.9rem;font-weight:600;color:var(--mut-d);text-decoration:none;
  padding:.3rem 0;border-bottom:2px solid transparent;transition:color .2s,border-color .2s}
.nav a:hover{color:var(--fg-d);border-color:var(--blu)}
/* the header CTA is an accent, not the headline: it must sit below the logo's
   visual mass, not above it. Hero and in-page CTAs keep the full size. */
/* the margin belongs to the pack, not to each cell: on a cell it would open a
   gap down the middle of the control */
.hdr .cta{margin-left:.4rem}
.hdr .btn{padding:.55rem 1rem;font-size:.76rem;letter-spacing:.05em}
.charge{position:absolute;left:0;right:0;bottom:-2px;height:2px;display:none}
.charge i{display:block;height:100%;background:var(--blu-b);transform-origin:0 50%;transform:scaleX(0)}
@supports (animation-timeline: scroll()){
  .charge i{animation:soc linear both;animation-timeline:scroll(root)}
  @keyframes soc{from{transform:scaleX(0)}to{transform:scaleX(1)}}
}
.burger{display:none;margin-left:auto;background:none;border:1px solid var(--line-d);
  border-radius:6px;padding:.55rem .6rem;cursor:pointer}
.burger i{display:block;width:20px;height:2px;background:var(--fg-d);margin:4px 0;
  transition:transform .25s var(--ease),opacity .2s}
/* overflow-y: the page behind is frozen, so without it the last items are
   unreachable on a short screen (phone landscape) */
.menu{position:fixed;inset:var(--hdrH) 0 0 0;z-index:55;background:var(--ink);
  display:none;flex-direction:column;gap:.4rem;padding:2.2rem clamp(1.2rem,6vw,3rem);
  overflow-y:auto;overscroll-behavior:contain}
@media (max-height:560px){.menu a{font-size:1.3rem}}
.menu a{font-weight:800;font-size:1.6rem;text-transform:uppercase;text-decoration:none;
  color:var(--fg-d);padding:.35rem 0;border-bottom:1px solid var(--line-d)}
.menu a:hover{color:var(--blu-b)}
/* Freezing the page under an open menu has to happen on <html>: that is the
   scrolling element here, so overflow:hidden on <body> alone locked nothing and
   the page scrolled away behind the panel. Kept on body too, for the browsers
   that do scroll the body. */
html:has(body.menu-open){overflow:hidden}
body.menu-open{overflow:hidden}
body.menu-open .menu{display:flex}
body.menu-open .burger i:nth-child(1){transform:translateY(6px) rotate(45deg)}
body.menu-open .burger i:nth-child(2){opacity:0}
body.menu-open .burger i:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

/* ================= language switcher =================
   two cells side by side, the live one charged blue: the same
   battery figure the rail and the CTA already use. */
/* no overflow:hidden - it clipped the keyboard focus ring off the two cells.
   The end cells round themselves instead. */
.lang{display:flex;align-items:center;margin-left:-.6rem;
  border:1px solid var(--line-d);border-radius:4px}
.lang-a{font-family:var(--mono);font-size:.72rem;letter-spacing:.08em;line-height:1;
  text-decoration:none;color:var(--mut-d);padding:.44rem .6rem;
  transition:color .2s,background .2s}
.lang-a:first-child{border-radius:3px 0 0 3px}
.lang-a:last-child{border-radius:0 3px 3px 0}
.lang-a+.lang-a{border-left:1px solid var(--line-d)}
.lang-a:hover{color:var(--fg-d);background:rgba(232,235,239,.07)}
.lang-a.cur{background:var(--blu);color:#fff}
.lang-a.cur:hover{background:var(--blu);color:#fff}
/* the full language name is there for screen readers, the code is there for eyes */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}

/* off-screen until focused, then it lands over the header */
.skip{position:fixed;left:1rem;top:-100px;z-index:100;
  background:var(--blu);color:#fff;font-weight:800;font-size:.85rem;
  padding:.7rem 1.1rem;border-radius:4px;text-decoration:none;
  transition:top .18s var(--ease)}
.skip:focus-visible{top:1rem}

/* ============ credentials channel - top row of the hero instrument panel ============
   Same hairline grammar as the figures below it. The track is duplicated and
   set running by JS only when the list is wider than the strip, so it never
   scrolls for the sake of scrolling. */
/* Four credentials, read as the four cells of a pack. The company's whole
   identity is a battery - the logo is a stack of plates, the rail charges with
   scroll, every CTA has a positive terminal - so the awards charge too. */
.awd-strip{padding-block:.7rem;border-bottom:1px solid var(--line-d)}
/* four EQUAL cells - a pack is symmetrical - but the group is only as wide as it
   needs to be: width:max-content stops 1fr from stretching them across 1240px,
   and the equal flex factors still size every cell to the widest one */
.awd-list{position:relative;min-width:0;list-style:none;
  display:grid;grid-template-columns:repeat(4,1fr);gap:.55rem;
  width:max-content;max-width:100%;margin-inline:auto}
.awd-list li{position:relative;min-width:0;
  padding:.42rem .6rem .46rem;border:1px solid var(--line-d);border-radius:3px}
/* every cell carries its own positive terminal, sitting in the gap to the next
   one: cells in series, which is what a pack is */
.awd-list li::after{content:"";position:absolute;left:100%;top:50%;
  transform:translateY(-50%);width:5px;height:44%;
  background:var(--line-d);border-radius:0 3px 3px 0}
/* the charge itself: one flat level, with the charge line along the bottom edge.
   How far it fills is how far the company actually got in that competition -    full only where the prize was won outright. */
.awd-list li::before{content:"";position:absolute;inset:0 auto 0 0;
  width:var(--charge,100%);border-radius:2px 0 0 2px;
  transform-origin:0 50%;background:rgba(0,109,211,.17);
  box-shadow:inset 0 -2px 0 var(--blu)}
.awd-list li[style*="--charge:100%"]::before{border-radius:2px}
.awd-list li b,.awd-list li span{position:relative;display:block}
.awd-list li b{font-weight:400;font-size:.58rem;letter-spacing:.08em;color:var(--blu-b)}
.awd-list li span{font-size:.8rem;font-weight:700;color:var(--fg-d);
  line-height:1.25;margin-top:.12rem;overflow-wrap:anywhere}
@media (prefers-reduced-motion: no-preference){
  /* cells charge in sequence; with motion off they are simply already charged */
  .awd-list li::before{animation:cellcharge .85s var(--ease) both;
    animation-delay:calc(.55s + var(--i) * .13s)}
  @keyframes cellcharge{from{transform:scaleX(0)}to{transform:none}}
}

/* ================= buttons ================= */
.btn{display:inline-flex;align-items:center;gap:.5rem;font-weight:800;font-size:.9rem;
  letter-spacing:.06em;text-transform:uppercase;text-decoration:none;
  padding:.8rem 1.3rem;border-radius:4px;
  transition:background .2s,color .2s,border-color .2s,transform .2s var(--ease)}
.btn:hover{transform:translateY(-2px)}
.btn-blu{background:var(--blu);color:#fff;position:relative}
/* stripes are viewport-anchored (background-attachment:fixed) so the pattern flows
   continuously from the body into the terminal nub - separate boxes, one current */
.btn-blu:hover{background:repeating-linear-gradient(-45deg,#1E86EC 0 12px,var(--blu) 12px 24px);
  background-attachment:fixed}
/* the CTA is a battery - positive terminal on its right end */
.btn-blu::after{content:"";position:absolute;left:100%;top:50%;transform:translateY(-50%);
  width:6px;height:46%;background:var(--blu);border-radius:0 3px 3px 0}
.btn-blu:hover::after{background:repeating-linear-gradient(-45deg,#1E86EC 0 12px,var(--blu) 12px 24px);
  background-attachment:fixed}
.btn-ghost-d{border:1px solid var(--line-d);color:var(--fg-d)}
.btn-ghost-d:hover{border-color:var(--blu-b);color:var(--blu-b)}

/* ============ contact CTA: one button, then a choice ============
   Writing and calling are the same intent taken two ways, so the page shows ONE
   call to action and asks which channel only after the click.

   Progressive enhancement: the trigger ships as a plain mailto link, so with no
   JavaScript it still writes an email. main.js upgrades it into a menu button. */
.cta{position:relative;display:inline-block}
/* fixed, not absolute: the hero clips its children (overflow:clip, for the
   parallax photo) so an absolutely positioned panel is sliced off at the section
   edge. Fixed escapes every clipping ancestor; main.js places it against the
   button and flips it up or pulls it in when it would leave the viewport. */
.cta-menu{position:fixed;z-index:80;
  min-width:250px;background:var(--ink-2);border:1px solid var(--line-d);
  border-radius:6px;padding:.4rem;box-shadow:0 20px 44px -14px rgba(0,0,0,.6)}
.cta-menu[hidden]{display:none}
.cta-menu a{display:flex;flex-direction:column;gap:.15rem;padding:.6rem .75rem;
  border-radius:4px;text-decoration:none;color:var(--fg-d);
  font-weight:700;font-size:.9rem;letter-spacing:0;text-transform:none}
.cta-menu a:hover,.cta-menu a:focus-visible{background:rgba(232,235,239,.07);color:var(--blu-b)}
.cta-menu small{color:var(--mut-d);font-weight:500;font-size:.8rem;
  letter-spacing:0;text-transform:none;font-variant-numeric:tabular-nums}
@media (prefers-reduced-motion: no-preference){
  .cta-menu{animation:ctaIn .18s var(--ease) both}
  @keyframes ctaIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
}

/* ================= layout primitives ================= */
main{margin-left:0}
.has-rail main{margin-left:var(--rail)}
.wrap{width:min(1240px,100%);margin-inline:auto;padding-inline:clamp(1.1rem,3vw,2rem)}
.mono{font-family:var(--mono);font-weight:700;font-size:.74rem;letter-spacing:.09em;text-transform:uppercase}
.gridbg{background-image:radial-gradient(rgba(6,15,23,.07) 1px,transparent 1.5px);
  background-size:26px 26px}
h1,h2,h3{text-transform:uppercase;line-height:1.02;letter-spacing:-.015em;
  text-wrap:balance;font-weight:800}
.sect{padding-block:var(--sect)}
.sect-head{max-width:56ch;margin-bottom:var(--headgap);position:relative}
.sect-head h2{font-size:clamp(1.9rem,3.4vw,2.9rem)}
/* the lead is a component: it is also used on articles and error pages, which
   have no .sect-head around them */
.lead{margin-top:var(--s2);font-size:clamp(1rem,1.25vw,1.12rem)}
.cols{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--colgap);align-items:center}
.c5{grid-column:span 5}.c6{grid-column:span 6}.c7{grid-column:span 7}

/* plates: full rectangles, marked at two corners - ONE image system.
   The photo is never cut into: the blue crop marks do the framing, so the
   picture stays whole and the shape language stays square everywhere. */
.fig{margin:0;position:relative}
/* cutout plate: melts into the section so a transparent product PNG floats on it */
.fig .ph.cut{background:var(--ink)}
.fig .ph.wide{aspect-ratio:3/2}
.fig .ph{aspect-ratio:4/3;overflow:clip;background:var(--ink-2);
  transition:transform .35s var(--ease);will-change:transform}
/* translateZ(0) puts the photo on its own GPU layer from the first paint, so the
   hover transform above never triggers a full repaint of the image. */
.fig img{width:100%;height:100%;object-fit:cover;transform:translateZ(0)}
.fig::before,.fig::after{content:"";position:absolute;width:16px;height:16px;pointer-events:none;z-index:2}
.fig::before{left:-6px;top:-6px;border-left:2px solid var(--blu-b);border-top:2px solid var(--blu-b)}
/* the 2.2rem clears the caption row below the photo - a figure without a caption
   has nothing to clear, and the mark would otherwise float inside the picture */
.fig::after{right:-6px;bottom:calc(2.2rem - 6px);border-right:2px solid var(--blu-b);border-bottom:2px solid var(--blu-b)}
.fig:not(:has(figcaption))::after{bottom:-6px}
.paper .fig::before{border-color:var(--blu-d)}
.paper .fig::after{border-color:var(--blu-d)}
.fig figcaption{display:flex;justify-content:space-between;gap:1rem;height:2.2rem;
  align-items:flex-end}
.fig figcaption span{font-family:var(--mono);font-size:.72rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--mut-d)}
.paper .fig figcaption span{color:var(--mut-l)}

/* reveals */
@media (prefers-reduced-motion: no-preference){
  @supports (animation-timeline: view()){
    .rv{animation:rvUp .8s var(--ease) both;animation-timeline:view();animation-range:entry 0% entry 42%}
    @keyframes rvUp{from{opacity:.001;transform:translateY(30px)}to{opacity:1;transform:none}}
  }
  .in{animation:in .9s var(--ease) both}
  /* same stagger, no vertical travel: for anything sitting flush on a section
     seam, where a 24px offset would show as a clipped edge */
  .in-lit{animation:inLit .9s var(--ease) both}
  .in.d1,.in-lit.d1{animation-delay:.08s}
  .in.d2,.in-lit.d2{animation-delay:.16s}
  .in.d3,.in-lit.d3{animation-delay:.26s}
  @keyframes in{from{transform:translateY(24px)}to{transform:none}}
  @keyframes inLit{from{opacity:0}to{opacity:1}}
}

/* ============ HERO - the photograph IS the hero ============ */
.hero{position:relative;min-height:100svh;display:flex;flex-direction:column;overflow:clip}
/* image is pre-sized 110% so the parallax is TRANSLATE-ONLY - a scroll-driven scale()
   forces the GPU to stretch a stale raster and the photo goes blurry while scrolling */
.hero-bg{position:absolute;left:0;top:-10%;width:100%;height:110%;object-fit:cover;object-position:52% 60%}
@media (prefers-reduced-motion: no-preference){
  @supports (animation-timeline: view()){
    .hero-bg{animation:heroPar linear both;animation-timeline:view();
      animation-range:exit 0% exit 100%}
    @keyframes heroPar{to{transform:translateY(9.1%)}}
  }
}
/* vignette: gentle falloff around the embossed logo so the macro keeps its natural depth */
.hero-tint{position:absolute;inset:0;background:radial-gradient(135% 115% at 52% 62%,rgba(6,15,23,0) 36%,rgba(6,15,23,.34) 74%,rgba(6,15,23,.7) 100%)}
.hero-scrim{position:absolute;inset:0;background:
  linear-gradient(72deg,rgba(6,15,23,.94) 0%,rgba(6,15,23,.62) 40%,rgba(6,15,23,.14) 68%,rgba(6,15,23,.02) 100%),
  linear-gradient(to top,rgba(6,15,23,.82) 0%,rgba(6,15,23,0) 30%),
  linear-gradient(to bottom,rgba(6,15,23,.6) 0%,rgba(6,15,23,0) 14%)}
/* padding-top clears the fixed header: on a short phone the hero content is
   taller than the viewport and margin-top:auto stops protecting it */
.hero-body{position:relative;z-index:2;width:100%;margin-top:auto;
  padding-top:calc(var(--hdrH) + var(--s2));
  padding-bottom:clamp(2.2rem,5vh,3.6rem)}
/* the motto: the first thing on the page, but plainly not the headline -    it names the process, the h1 names the product */
.motto{display:block;margin-bottom:clamp(.9rem,2vh,1.4rem);
  font-size:clamp(.72rem,.95vw,.86rem);letter-spacing:.2em;color:#C7D2DD}
.motto span+span::before{content:"·";margin-inline:.62rem;
  color:var(--mut-d);letter-spacing:0}
.motto .hl{color:var(--blu-b)}
.hero h1{font-size:clamp(2.2rem,4.2vw,3.9rem);line-height:1;max-width:16ch}
.hero h1 span{display:block}
.hero h1 .ln2{color:#fff}
.hero h1 .ln3{color:var(--blu-b)}
.hero .sub{margin-top:var(--s3);color:#C7D2DD;font-size:clamp(1rem,1.25vw,1.12rem);max-width:42ch}
.hero .sub b{color:#fff;font-weight:700}
.h-ctas{display:flex;gap:.8rem;flex-wrap:wrap;margin-top:var(--s4)}
/* spec strip fused to the hero's bottom edge - functional glass.
   This one does NOT slide in. Its bottom edge sits exactly on the seam with the
   light section below, so any downward offset either clips its last row or makes
   the dark bar look like it is climbing out of the white. It powers on instead,
   which also suits an instrument panel better than a slide. */
.hero-specs{position:relative;z-index:2;background:var(--ink);
  border-top:1px solid var(--line-d)}
.specs{display:grid;grid-template-columns:repeat(3,1fr)}
/* the solution pages reuse this bar with 2 or 3 figures: a class, not an inline
   style, so the mobile breakpoint below can still override it */
.specs--2{grid-template-columns:repeat(2,1fr)}
.spec{padding:var(--s3) var(--s4);border-left:1px solid var(--line-d)}
.spec:first-child{border-left:0;padding-left:0}
.spec b{font-weight:800;font-size:clamp(1.5rem,2.6vw,2.2rem);line-height:1.1;
  font-variant-numeric:tabular-nums;display:block}
.spec .unit{color:var(--blu-b);font-size:.6em;font-weight:800;margin-left:.25rem}
.spec small{display:block;margin-top:.3rem;color:var(--mut-d)}

/* ============ one-line diagram - current flows in the wires ============ */
.sld{margin-bottom:var(--headgap)}
.sld svg{width:100%;height:auto;display:block}
/* Two drawings of the same circuit, one per shape of screen. The labels are 11
   units inside the viewBox, so they scale with the container: fine at 1160 units
   across a desktop, 3.4px once that width is squeezed onto a phone. The portrait
   twin is 360 units across, which lands near 1:1 on a phone and keeps the type
   the size it was drawn. Only one is ever displayed; the wrapper carries the
   role and the label, so neither is announced twice. */
/* scoped to .sld so these outrank the `.sld svg{display:block}` above */
.sld .sld-tall{display:none}
@media (max-width:1099px){
  .sld .sld-wide{display:none}
  .sld .sld-tall{display:block;max-width:360px;margin-inline:auto}
}
.sld .wire{stroke:var(--line-l);stroke-width:2;fill:none}
.sld .cur{stroke:var(--blu);stroke-width:2;fill:none;stroke-dasharray:8 14}
@media (prefers-reduced-motion: no-preference){
  .sld .cur{animation:flow 1.1s linear infinite}
  @keyframes flow{to{stroke-dashoffset:-22}}
}
.sld .node{stroke:var(--mut-l);stroke-width:2;fill:var(--paper-2)}
.sld .cell{fill:var(--blu)}
.sld text{font-family:var(--mono);font-size:11px;letter-spacing:.08em;fill:var(--mut-l);text-transform:uppercase}
.sld .accent{fill:var(--blu-d)}

/* ================= SECTION JOINS - the drawer =================
   A section does not begin at full width. It slides in NARROWER, and the section
   above frames it down both sides for the first few centimetres before it seats
   and widens to the full page. A module going into a rack.

   Why this and not a cut: nothing is removed and nothing is invented. The edge
   is still a right angle, the shape is the section's own body arriving, and it
   reads as depth - one plane in front of another - which a flat notch, a
   diagonal, a comb or a rule can never do.

   Two layers on the incoming section: a band the colour of the section above,
   and inside it the section's own colour, inset on both sides. The inset is a
   rail width, not a percentage, so it stays the same physical distance at every
   viewport instead of drifting with the window. */
:root{--rack:clamp(1.6rem,5vw,5.5rem); --seat:clamp(1.9rem,4vh,3.4rem)}
/* the colour of the section immediately above, named once and used by whichever
   layer needs it - which swaps between the two directions below */
.from-ink{--prev:var(--ink)}
.from-ink2{--prev:var(--ink-2)}
.from-paper{--prev:var(--paper)}

.drawer{position:relative}
.drawer > *{position:relative;z-index:2}
.drawer::before,.drawer::after{content:"";position:absolute;top:0;
  height:var(--seat);z-index:1;pointer-events:none}
.drawer::before{left:0;width:100%}
.drawer::after{left:var(--rack);right:var(--rack)}

/* ---- direction 1: the new section slides UP into the one above ----
   Middle = the new section's own face, rising between two rails of the old
   colour. The contact runs round the protruding face (top and sides) and returns
   along the rails (the band's bottom edge, visible only where the face does not
   cover it). Bottom of the face is open: that is where it continues into itself. */
.drawer::before{background:var(--prev);box-shadow:inset 0 -3px 0 var(--blu)}
.drawer::after{background:inherit;
  box-shadow:inset 0 3px 0 var(--blu), inset 3px 0 0 var(--blu), inset -3px 0 0 var(--blu)}

/* ---- direction 2: the old section reaches DOWN into the new one ----
   The same shape turned over: middle = a tongue of the OLD colour descending,
   rails = the new section arriving early on both sides. Every boundary alternates
   between the two, so no two joins on the page are the same stamp. */
.drawer-rev::before{background:inherit;box-shadow:inset 0 3px 0 var(--blu)}
.drawer-rev::after{background:var(--prev);
  box-shadow:inset 0 -3px 0 var(--blu), inset 3px 0 0 var(--blu), inset -3px 0 0 var(--blu)}

/* on a phone the rails eat the width the content needs */
@media (max-width:640px){
  .drawer::before,.drawer::after{display:none}
}

/* ================= paper sections ================= */
.paper{background:var(--paper);color:var(--fg-l)}
.paper .mono{color:var(--mut-l)}
.paper .lead{color:var(--mut-l)}
/* the angled seams that used to wedge between the dark and paper sections are
   gone: both transitions are now straight edges */
.overline{font-family:var(--mono);font-size:.8rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--blu-d);margin-bottom:var(--s2)}
/* no overflow:clip - the photo plate has to hang past this section's bottom edge */
.shelter{position:relative;overflow:clip}
.shelter .cols{position:relative;z-index:1}
.shelter h2{font-size:clamp(1.9rem,3.4vw,2.9rem)}
.body-txt{margin-top:var(--s3);font-size:clamp(1rem,1.25vw,1.12rem);max-width:52ch}
/* first thing in its column: no phantom gap above it */
.cols > div > .body-txt:first-child{margin-top:0}
.shelter .ssp{margin-top:var(--s3);font-weight:800;text-transform:uppercase;
  font-size:clamp(1.05rem,1.6vw,1.35rem);letter-spacing:.01em;color:var(--blu-d)}

/* ================= gauge wall ================= */
/* no border-top: the step above this section is the boundary now, and a grey
   hairline underneath it read as a leftover */
.gauges{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--colgap);
  border-block:1px solid var(--line-l);padding-block:var(--s5)}
.gauge b{font-weight:900;font-size:clamp(2.1rem,4.4vw,3.8rem);line-height:1;
  letter-spacing:-.01em;font-variant-numeric:tabular-nums;display:inline-block}
.gauge .unit{font-size:clamp(1rem,1.8vw,1.5rem);color:var(--blu-d);font-weight:800;margin-left:.3rem}
.meter{margin-top:var(--s3);height:16px;border:1px solid var(--line-l);border-radius:3px;
  overflow:clip;background:var(--paper-2);position:relative}
.meter i{display:block;height:100%;width:0;
  background:repeating-linear-gradient(90deg,var(--blu) 0 12px,transparent 12px 16px)}
.on .meter i{width:var(--fill);transition:width 1.4s var(--ease)}
.meter i{margin-left:var(--from,0%)}
.gauge small{display:block;margin-top:.6rem;color:var(--mut-l);
  font-family:var(--mono);font-size:.74rem;letter-spacing:.06em;text-transform:uppercase}
.grid-sect .twocol{display:grid;grid-template-columns:1fr 1fr;gap:var(--colgap);
  margin-top:var(--headgap)}
.grid-sect .twocol p{max-width:52ch;font-size:clamp(.98rem,1.2vw,1.08rem)}
.grid-sect .twocol p + p{color:var(--mut-l)}
@media (prefers-reduced-motion: reduce){.on .meter i{transition:none}}

/* ================= SOLUTIONS - manifest panels ================= */
.sol{background:var(--ink);position:relative;overflow:clip}
.sol .sect-head{padding-top:var(--sect)}
/* the two panels are two surfaces (ink-2 / ink), so the boundary between them
   is a drawer like every other one - it used to be the only full-bleed blue
   rule on the page, which made it the odd one out once the drawers arrived */
.panel{padding-block:var(--sect);position:relative}
.panel.p-a{background:var(--ink)}
/* the head and the first panel are ONE section - the blue rule only separates the two panels */
.sol .panel:first-of-type{padding-top:calc(var(--sect) * .55)}
.panel.p-b{background:var(--ink-2)}
/* the plate label belongs to the component, not to the panel it first appeared
   in - the solution pages use it outside any .panel */
.plate{color:var(--blu-b);display:flex;align-items:center;gap:.8rem;margin-bottom:var(--s2)}
.plate::after{content:"";flex:1;height:1px;background:var(--line-d)}
.panel h3{font-size:clamp(2rem,3.6vw,3.2rem)}
.panel .ptag{margin-top:var(--s1);font-weight:800;text-transform:uppercase;
  letter-spacing:.04em;font-size:.95rem;color:var(--blu-b)}
.panel .pdesc{margin-top:var(--s3);color:var(--mut-d);max-width:46ch;font-size:clamp(.98rem,1.2vw,1.08rem)}
.panel .pdesc b{color:var(--fg-d);font-weight:700}
.chips{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:var(--s3)}
.chips span{font-family:var(--mono);font-size:.7rem;letter-spacing:.05em;text-transform:uppercase;
  border:1px solid var(--line-d);color:var(--mut-d);padding:.32rem .6rem;border-radius:999px}
.plink{display:inline-flex;align-items:center;gap:.6rem;margin-top:var(--s4);
  font-weight:800;font-size:.95rem;letter-spacing:.05em;text-transform:uppercase;
  text-decoration:none;color:var(--blu-b)}
.plink em{font-style:normal;transition:transform .25s var(--ease)}
.plink:hover em{transform:translateX(6px)}
.panel .fig .ph img{transition:transform .8s var(--ease)}
.panel:hover .fig .ph img{transform:scale(1.03)}

/* ================= EXPERTS ================= */
/* likewise: the step marks this boundary, so the old full-width blue rule went */
.experts{background:var(--ink-2);color:var(--fg-d)}
.experts .lead{color:var(--mut-d)}
.exp-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(2.5rem,5vw,5rem);margin-top:var(--headgap)}
.exp{display:flex;flex-direction:column}
.exp .portrait{position:relative;max-width:400px;aspect-ratio:1/1;overflow:clip;
  background:var(--ink)}
.exp .portrait img{width:100%;height:100%;object-fit:cover;transform:translateZ(0)}
.exp .portrait::before{content:"";position:absolute;left:-6px;top:-6px;width:16px;height:16px;z-index:2;
  border-left:2px solid var(--blu-b);border-top:2px solid var(--blu-b)}
.exp-role{margin-top:var(--s4);font-family:var(--mono);font-size:.78rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--blu-b);display:flex;align-items:center;gap:.7rem}
.exp-role::after{content:"";flex:1;height:1px;background:var(--line-d);max-width:130px}
.exp h3{margin-top:var(--s2);font-size:clamp(1.5rem,2.6vw,2.1rem);text-transform:uppercase;letter-spacing:-.01em}
.exp-desc{margin-top:var(--s1);color:var(--mut-d);max-width:36ch}

/* ================= the news feed: articles, press, video =================
   One card shape for all three. Only the badge and the destination differ, so
   the section reads as one feed rather than three lists side by side. */
.ntype{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem .8rem;
  margin-top:var(--s2);color:var(--blu-b)}
/* the kind is the loud part, the date and the publication are context.
   Padded in em so it tracks the font size, and NOT symmetrically: the label is
   all caps, so its ink stops at the cap height and the empty descender space
   sits below it. Equal padding therefore reads as the word hugging the top of
   the box. The extra .1em on top puts the ink in the optical middle. */
.ntype-b{border:1px solid currentColor;border-radius:3px;
  padding:.42em .55em .32em;line-height:1}
.ntype time,.ntype-src{color:var(--mut-d);letter-spacing:.08em}
.ntype-src::before{content:"· "}
.paper .ntype time,.paper .ntype-src{color:var(--mut-l)}

/* A video frame is 16/9 and a photograph here is 4/3, so one plate shape cannot
   serve both without either cropping or padding. Both were tried and both are
   worse than this: filling the 4/3 plate throws away the sides, and these
   thumbnails carry their title across the full width, while centring the frame
   leaves two bands of dead plate.

   The video plate simply takes the shape of its own content. Video cards come
   out shorter than article cards, which is what a mixed feed looks like when
   nothing is being distorted to hide it.

   YouTube's hqdefault is that 16/9 frame letterboxed into a 480x360 file, so the
   plate's own crop removes exactly the black bars and nothing else. */
.ncard[data-type="video"] .ph{aspect-ratio:16/9;
  /* A 4/3 plate is 3/4 of the width tall and a 16/9 one is 9/16, so a video card
     runs exactly 3/16 of the width shorter. Handing that difference to the gap
     BELOW the frame puts every badge and headline back on one line across the
     row. The space ends up in the same place the eye already expects space,
     instead of split into two bands hugging the picture. */
  margin-bottom:calc(var(--s3) + 18.75%)}
/* play badge: a right-angle plate with a triangle, not a floating round button */
.play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:2;
  width:56px;height:40px;border-radius:4px;background:rgba(6,15,23,.72);
  border:2px solid var(--blu-b);transition:background .2s,transform .2s var(--ease)}
.play::after{content:"";position:absolute;left:52%;top:50%;transform:translate(-50%,-50%);
  border-left:13px solid var(--fg-d);border-top:8px solid transparent;
  border-bottom:8px solid transparent}
.ncard a:hover .play{background:var(--blu);transform:translate(-50%,-50%) scale(1.06)}

/* filter tabs: real links, so each one is an address that can be shared */
.nfilter{display:flex;flex-wrap:wrap;gap:.5rem;margin-bottom:var(--headgap)}
.nfilter a{text-decoration:none;color:var(--mut-d);border:1px solid var(--line-d);
  border-radius:4px;padding:.45rem .8rem;line-height:1;transition:color .2s,border-color .2s,background .2s}
.nfilter a:hover{color:var(--fg-d);border-color:var(--blu)}
.nfilter a[aria-current]{background:var(--blu);border-color:var(--blu);color:#fff}
.paper .nfilter a{color:var(--mut-l);border-color:var(--line-l)}
.paper .nfilter a:hover{color:var(--fg-l);border-color:var(--blu)}
.paper .nfilter a[aria-current]{background:var(--blu);border-color:var(--blu);color:#fff}


/* ================= NEWS teaser - same rhythm as Experts, one section later ================= */
/* News and Contact are ONE dark closing block, not two dark sections in a row.
   Inserting any section between the light Results board and the dark closing
   would break the page's light/dark alternation somewhere; making it part of the
   closing block keeps the alternation intact and ends the page on one surface.
   The two are separated by a hairline, the way everything else on this site is. */
.newsteaser{background:var(--ink);color:var(--fg-d)}
.newsteaser .lead{color:var(--mut-d)}
.newsteaser-all{margin-top:var(--headgap)}

/* ================= RESULTS - the verdict board ================= */
.res{position:relative;overflow:clip}
.score{display:grid;grid-template-columns:1fr 1fr;gap:var(--colgap);align-items:start}
.side .tag{font-family:var(--mono);font-size:.78rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--mut-l);display:flex;align-items:center;gap:.8rem}
.side .tag::after{content:"";flex:1;height:1px;background:var(--line-l)}
.side .big{font-weight:900;text-transform:uppercase;line-height:1;
  font-size:clamp(3.2rem,8.2vw,7rem);letter-spacing:-.02em;margin-top:var(--s3);
  position:relative;display:inline-block;font-variant-numeric:tabular-nums}
/* muted, but it is still a real figure a buyer reads: #9AA7B4 measured 2.05:1 on
   the paper background, under the 3:1 WCAG floor for large text. This is 3.57:1. */
.side.lose .big{color:#6E7C8A}
.side.lose .big::after{content:"";position:absolute;left:-3%;right:-3%;top:50%;height:5px;
  background:var(--blu);transform:rotate(-5deg)}
.side.win .big{color:var(--blu)}
.side dl{margin-top:var(--s4);border-top:1px solid var(--line-l)}
.side .drow{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;
  padding:.85rem 0;border-bottom:1px solid var(--line-l)}
.side .drow dt{font-family:var(--mono);font-size:.74rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--mut-l)}
.side .drow dd{font-weight:800;font-size:clamp(1.1rem,1.8vw,1.5rem);font-variant-numeric:tabular-nums}
.side.win .drow dd{color:var(--blu-d)}
.res-note{margin-top:var(--s5);color:var(--mut-l);font-family:var(--mono);font-size:.78rem;
  letter-spacing:.05em;text-transform:uppercase;display:flex;align-items:center;gap:.7rem}
.res-note::before{content:"";width:10px;height:10px;background:var(--blu);border-radius:2px;flex:none}

/* ================= CLOSING ================= */
.close{padding-block:var(--s6) var(--s4);position:relative}
/* THE PAGE ENDS LIGHT. Adding the News section flipped the parity of everything
   after it, and two dark sections landed next to each other. Rather than hide
   that by merging News into the footer, the closing block changes surface: the
   page opens on a dark photograph and closes on paper, and the light/dark
   alternation holds all the way down. */
.close{background:var(--paper);color:var(--fg-l)}
.close h2{font-size:clamp(1.5rem,3vw,2.4rem)}
.close h2 span{display:block}
.close h2 .hv{color:var(--blu-d)}
.close .sub{margin-top:var(--s2);color:var(--mut-l);max-width:52ch;font-size:.95rem}
.close .sub b{color:var(--fg-l);font-weight:700}
.mail{display:inline-block;margin-top:var(--s4);font-weight:800;
  font-size:clamp(1.05rem,1.8vw,1.5rem);text-decoration:none;color:var(--fg-l);
  border-bottom:3px solid var(--blu);padding-bottom:.2rem;transition:color .2s;overflow-wrap:anywhere}
.mail:hover{color:var(--blu-d)}
/* the phone sits one step below the email: the email is the block's single call
   to action and keeps the blue rule under it, while this stays a plain tappable
   line rather than a second competing button */
.tel{display:inline-block;margin-top:var(--s2);font-weight:700;font-size:1.05rem;
  text-decoration:none;color:var(--fg-l);transition:color .2s;
  font-variant-numeric:tabular-nums}
.tel:hover{color:var(--blu-d)}
.close-meta{display:flex;flex-wrap:wrap;align-items:center;gap:1rem 2.2rem;
  margin-top:var(--s4);color:var(--mut-l)}
.close-meta a{text-decoration:none;color:var(--mut-l)}
.close-meta a:hover{color:var(--blu-d)}
/* icon and word are one link, so they move together on hover */
.soc{display:inline-flex;align-items:center;gap:.5rem}
.soc-i{width:17px;height:17px;flex:none;fill:currentColor;
  transition:transform .2s var(--ease)}
.soc:hover .soc-i{transform:translateY(-1px)}
.foot{margin-top:var(--s5);border-top:1px solid var(--line-l);padding-top:var(--s3);
  display:flex;flex-wrap:wrap;gap:.8rem 2rem;justify-content:space-between;align-items:center;color:var(--mut-l)}
.foot img{height:34px;width:auto;opacity:.9}

/* ============ FINISH PASS: grain · scrollbar · grade · micro · SLD · orientation · film ============ */
/* (9) film grain over everything + custom scrollbar */
.grain{position:fixed;inset:0;z-index:200;pointer-events:none;opacity:.05;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='280' height='280'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:280px 280px}
html{scrollbar-color:#24374B var(--ink)}
::-webkit-scrollbar{width:12px}
::-webkit-scrollbar-track{background:var(--ink)}
::-webkit-scrollbar-thumb{background:#24374B;border:3px solid var(--ink);border-radius:6px}
::-webkit-scrollbar-thumb:hover{background:var(--blu)}

/* (8) micro-interactions: magnetic buttons, press state, logo charge sweep */
.btn{transform:translate(var(--mx,0px),var(--my,0px));
  transition:transform .18s var(--ease),background .25s,border-color .25s,color .25s}
.btn:hover{transform:translate(var(--mx,0px),var(--my,0px)) translateY(-2px)}
.btn:active{transform:translate(var(--mx,0px),var(--my,0px)) translateY(0) scale(.965)}
.brand{position:relative}
.brand::after{content:"";position:absolute;left:0;right:0;bottom:-8px;height:2px;
  background:linear-gradient(90deg,var(--blu),var(--blu-b));transform:scaleX(0);
  transform-origin:0 50%;transition:transform .45s var(--ease)}
.brand:hover::after{transform:scaleX(1)}

/* (7) unified colour grade over every photo plate */
.fig .ph{position:relative}
.ph img{filter:saturate(.92) contrast(1.05)}
.ph:not(.cut)::after{content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  background:linear-gradient(160deg,rgba(0,109,211,.10),rgba(6,15,23,.16) 70%);mix-blend-mode:multiply}
.exp .portrait img{filter:saturate(.92) contrast(1.05)}
.exp .portrait::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(160deg,rgba(0,109,211,.10),rgba(6,15,23,.16) 70%);mix-blend-mode:multiply}

/* (5) SLD draws itself on scroll, then the current starts flowing */
@media (prefers-reduced-motion: no-preference){
  @supports (animation-timeline: view()){
    .sld .wire{stroke-dasharray:1;stroke-dashoffset:1;
      animation:sldDraw linear both;animation-timeline:view();animation-range:entry 10% entry 65%}
    @keyframes sldDraw{to{stroke-dashoffset:0}}
    .sld .cur{animation:flow 1.1s linear infinite, sldFade linear both;
      animation-timeline:auto, view();animation-range:normal, entry 60% entry 80%}
    .sld .node,.sld text,.sld .cell{animation:sldFade linear both;
      animation-timeline:view();animation-range:entry 0% entry 40%}
    @keyframes sldFade{from{opacity:0}}
  }
}

/* (2) orientation: section numbers, scrollspy nav, rail ticks */
.secno{font-family:var(--mono);font-size:.78rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--blu-d);margin-bottom:var(--s1)}
.sol .secno,.experts .secno{color:var(--blu-b)}
.nav a.cur{color:var(--fg-d);border-color:var(--blu)}

/* ================= Solutions dropdown =================
   the two detail pages, one hover away from the nav item that already
   points at their overview section */
.nav-item{position:relative}
.nav-item > a[aria-expanded]{display:inline-flex;align-items:center;gap:.4rem}
.nav-item > a[aria-expanded]::after{content:"";width:5px;height:5px;flex:none;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:translateY(-2px) rotate(45deg);opacity:.55;transition:transform .2s var(--ease)}
.nav-item:hover > a[aria-expanded]::after,
.nav-item:focus-within > a[aria-expanded]::after{transform:translateY(0) rotate(45deg)}
/* .drop is the hoverable region - it starts flush against the nav item with
   NO margin, so there is no dead strip of header background for the pointer
   to cross. The visual gap is padding-top instead of margin: padding is still
   inside the box, so hovering it keeps the whole thing open. Only the inner
   .drop-panel is invisible/offset when closed; the bridge itself never moves. */
.drop{position:absolute;left:50%;top:100%;transform:translateX(-50%);
  padding-top:15px;visibility:hidden;pointer-events:none;transition:visibility .18s}
.nav-item:hover .drop,.nav-item:focus-within .drop{visibility:visible;pointer-events:auto}
.drop-panel{min-width:230px;background:var(--ink-2);border:1px solid var(--line-d);
  border-radius:6px;padding:.4rem;box-shadow:0 20px 44px -14px rgba(0,0,0,.6);
  opacity:0;transform:translateY(-4px);transition:opacity .18s var(--ease),transform .18s var(--ease)}
.nav-item:hover .drop-panel,.nav-item:focus-within .drop-panel{opacity:1;transform:none}
.drop a{display:flex;flex-direction:column;gap:.2rem;padding:.6rem .75rem;border-radius:4px;
  text-decoration:none;color:var(--fg-d);font-weight:700;font-size:.86rem;
  letter-spacing:0;text-transform:none}
.drop a:hover{background:rgba(232,235,239,.07);color:var(--blu-b)}
/* a plain subtitle, not another shouting label - one all-caps chip per menu
   item (the nav word itself) is enough */
.drop-plate{color:var(--mut-d);font-weight:500;font-size:.78rem;line-height:1.3}
@media (prefers-reduced-motion: reduce){.drop,.drop-panel{transition:none}}

/* mobile full-screen menu: the two solution pages sit indented under Solutions,
   always visible - there is no hover on touch */
.menu-sub{display:flex;flex-direction:column;padding-left:1.4rem;
  border-bottom:1px solid var(--line-d)}
/* these are real destinations on touch, not hover hints, so they sit one clear
   step below the parent rather than nearly half its size: 32/16.8 read as a
   different kind of thing, not a level of the same menu */
.menu-sub a{font-size:1.15rem;font-weight:600;text-transform:none;
  padding:.5rem 0;border-bottom:0;color:var(--mut-d)}
.menu-sub a:hover{color:var(--blu-b)}

/* ================= responsive ================= */
/* the switcher costs the header a chunk of width: buy it back from the gaps
   before anything has to wrap */
@media (max-width:1319px){
  .hdr-in{gap:1.2rem}
  .nav{gap:1.15rem}
}
@media (max-width:1199px){
  /* no room for the rail: the thin charge line under the header takes over,
     but still only where a rail would have been (the homepage) */
  .rail{display:none}
  .has-rail main{margin-left:0}
  .has-rail .hdr{left:0}
  .has-rail .charge{display:block}
}
@media (max-width:1023px){
  .cols{grid-template-columns:1fr;gap:var(--s5)}
  .c5,.c6,.c7{grid-column:auto}
  .hero .fig .ph{aspect-ratio:16/10}
  .grid-sect .twocol{grid-template-columns:1fr}
  .gauges{grid-template-columns:1fr;gap:var(--s4)}
  .score{grid-template-columns:1fr;gap:var(--s6)}
  .exp-grid{grid-template-columns:1fr;gap:var(--s6)}
  .exp .portrait{max-width:340px}
  .panel .cols .fig{order:-1}
  .bgword{font-size:clamp(5rem,20vw,9rem)}
  /* the full header stops fitting well before 820px: logo + six nav items +
     the switcher + the CTA overflow between 821 and 1023 */
  .nav,.hdr .cta{display:none}
  .lang{margin-left:auto;flex:none}
  .burger{display:block;margin-left:0}
  /* nothing in the header may be smaller than a fingertip */
  .lang-a{min-height:44px;display:flex;align-items:center;justify-content:center;padding:0 .8rem}
  .burger{padding:.75rem .8rem}
  .menu-sub a{padding:.6rem 0}
}
@media (max-width:820px){
  .specs,.specs--2{grid-template-columns:1fr}
  /* one row per figure: value left, label right. Inline-flowed labels wrapped
     mid-phrase and left orphans hanging in the middle of the bar. */
  .spec{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
    border-left:0;border-top:1px solid var(--line-d);padding:.85rem 0}
  .spec:first-child{border-top:0}
  /* the strip's bottom edge IS the seam with the light section below it, and the
     rows carry no margin of their own: without this the last label sat 8px from
     the boundary and the ink ran out under the text rather than around it */
  .hero-specs{padding-bottom:1rem}
  .spec b{font-size:1.25rem;display:inline;flex:none}
  .spec small{display:block;margin-left:0;text-align:right;font-size:.7rem;
    letter-spacing:.05em;line-height:1.35}
  .bgword{display:none}
  .coords{flex-direction:column;gap:.3rem}
  .awd-list{grid-template-columns:repeat(2,1fr);row-gap:.5rem;width:auto}
}
/* Phones short enough that the hero does not fit.
   "The photograph IS the hero", but on a 390x844 screen the copy and the
   instrument panel filled all 844px and the photograph never appeared at all,
   while the same page on a 430x932 left 158px of it breathing. Height, not
   width, is the thing that runs out: a 430x932 is wider AND taller, so keying
   this to max-width alone would punish the phone that is already fine.
   Everything below buys vertical room back without shrinking any type. */
@media (max-width:640px) and (max-height:880px){
  /* trimmed to pay for the strip's new bottom margin without giving the
     photograph back the space it just got */
  .hero-body{padding-bottom:clamp(.9rem,2.2vh,1.4rem)}
  .motto{margin-bottom:clamp(.55rem,1.2vh,.85rem)}
  /* two buttons that wrap to their own lines look accidental when one is 148px
     and the other 222px; matched full width reads as a decision */
  .h-ctas .btn{flex:1 1 100%;justify-content:center}
  .awd-strip{padding-block:.45rem}
  .awd-list li{padding:.32rem .5rem .36rem}
  .spec{padding:.5rem 0}
}
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

/* ============================================================
   APP PAGES - News, article, errors, subpage footer.
   Same tokens, same plate/mono language as the homepage.
   ============================================================ */

/* the dark lead used on ink sections (was an inline style in the demo) */
.lead-d{color:var(--mut-d)}

/* subpages have no full-bleed hero, so they clear the fixed header themselves */
.subpage{padding-top:var(--hdrH)}
/* ================= the consent bar =================
   A panel that slides up from the bottom edge, with the same blue seam the
   sections use where they meet. It sits above everything, but it does not cover
   the page: the reader can go on reading while deciding. */
.consent{position:fixed;left:0;right:0;bottom:0;z-index:80;
  background:var(--ink-2);border-top:2px solid var(--blu);
  box-shadow:0 -18px 40px rgba(6,15,23,.55);
  transform:translateY(100%);transition:transform .38s cubic-bezier(.2,.8,.2,1)}
.consent.in{transform:translateY(0)}
.consent-in{display:flex;align-items:center;gap:var(--s4);
  padding-top:var(--s3);padding-bottom:var(--s3);flex-wrap:wrap}
.consent-txt{flex:1 1 22rem;margin:0;color:var(--mut-d);font-size:.95rem;line-height:1.55}
.consent-txt a{color:var(--blu-b);white-space:nowrap}
.consent-txt a:hover{color:#fff}
.consent-acts{display:flex;gap:var(--s2);flex:0 0 auto}

/* Both buttons are the same size and one click deep. Making "no" smaller or
   quieter than "yes" is the most common way a consent bar ends up collecting
   consent that does not count. */
.cbtn{font-family:var(--mono);font-size:.78rem;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;padding:.85rem 1.6rem;border:1px solid transparent;
  cursor:pointer;min-width:9.5rem;
  transition:background .18s,border-color .18s,color .18s}
.cbtn-yes{background:var(--blu);color:#fff}
.cbtn-yes:hover{background:var(--blu-d)}
.cbtn-no{background:transparent;border-color:var(--line-d);color:var(--fg-d)}
.cbtn-no:hover{border-color:var(--blu-b);color:var(--blu-b)}

@media (max-width:640px){
  .consent-in{gap:var(--s3)}
  .consent-acts{width:100%}
  .cbtn{flex:1 1 0;min-width:0;padding:.85rem .8rem}
}
@media (prefers-reduced-motion:reduce){
  .consent{transition:none}
}

/* ================= pages that are only words =================
   Legal notice and privacy. Held to a reading measure rather than the full grid:
   these are read start to finish, not scanned. */
.prose{max-width:68ch}
.prose h2{font-size:clamp(1.1rem,1.9vw,1.35rem);margin-top:var(--s5);
  text-transform:none;letter-spacing:-.005em}
.prose h2:first-child{margin-top:0}
.prose p{margin-top:var(--s2);color:var(--mut-d)}
.prose a{color:var(--blu-b)}
.prose a:hover{color:#fff}
/* a definition list of company particulars: label above value, so a long
   registered address never squeezes its own label into one word per line */
.legal-dl{margin-top:var(--s3);display:grid;gap:var(--s3);
  grid-template-columns:repeat(auto-fill,minmax(220px,1fr))}
.legal-dl dt{font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--blu-b)}
.legal-dl dd{margin-top:.3rem;color:var(--fg-d)}
/* a gap the company still has to fill, marked so it cannot ship unnoticed */
.todo-field{color:#F0B429;border-bottom:1px dashed currentColor}

.legal-links{display:flex;flex-wrap:wrap;gap:1rem 2.2rem;margin-top:var(--s3)}
.legal-links a{color:var(--mut-l);text-decoration:none}
.legal-links a:hover{color:var(--blu-d)}

.sub-hero{background:var(--ink);color:var(--fg-d);min-height:52svh}
.sub-hero h1{font-size:clamp(2rem,4.6vw,3.4rem)}
.sub-hero .sect-head{margin-bottom:var(--headgap)}
.empty{color:var(--mut-d);border:1px dashed var(--line-d);padding:var(--s5);text-align:center}

/* news index */
.news-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));
  gap:var(--colgap) clamp(1.5rem,3vw,2.5rem)}
.ncard a{display:block;text-decoration:none;color:inherit}
/* 4/3 like every other plate on the site - that is the ratio the photographs are
   shot in, so a card shows the whole frame instead of shaving 11% off it */
.ncard .ph{aspect-ratio:4/3;overflow:clip;background:var(--ink-2);margin-bottom:var(--s3);
  position:relative}
.ncard .ph img{width:100%;height:100%;object-fit:cover;transform:translateZ(0);
  filter:saturate(.92) contrast(1.05);transition:transform .6s var(--ease)}
.ncard .ph::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(160deg,rgba(0,109,211,.10),rgba(6,15,23,.16) 70%);mix-blend-mode:multiply}
.ncard a:hover .ph img{transform:scale(1.03)}
.ndate{color:var(--blu-b);letter-spacing:.1em}
.ncard h2{margin-top:var(--s2);font-size:clamp(1.2rem,2vw,1.6rem)}
.nexcerpt{margin-top:var(--s2);color:var(--mut-d);max-width:46ch}
.ncard .plink{font-size:.85rem}

/* article */
.backlink{display:inline-block;margin-bottom:var(--s4);color:var(--mut-d);text-decoration:none}
.backlink:hover{color:var(--blu-b)}
.article-head{max-width:62ch}
/* the cover illustrates the article, it does not replace it: hold it to the text
   column so the opening paragraphs stay close.

   No ratio override here on purpose. It used to be 16/9, which cut 25% off the
   top and bottom of a 4:3 photograph - a quarter of the picture, gone. The plate
   ratio from .fig .ph (4/3) is the one the photographs are actually shot in, so
   the cover shows the whole frame and matches the card the reader just clicked. */
.article-cover{margin-block:var(--headgap);max-width:min(100%,760px)}
/* solution page header: name and numbers are one block, not two sections.
   Top padding is a page's worth of breathing room, not a section's. */
.solhead{background:var(--ink);color:var(--fg-d);
  padding-top:clamp(1.5rem,4vh,2.4rem);border-bottom:1px solid var(--line-d)}
.solhead .backlink{margin-bottom:var(--s3)}
.solhead h1{font-size:clamp(2rem,4.6vw,3.4rem)}
.solhead .specs{margin-top:clamp(1.6rem,4vh,2.6rem);border-top:1px solid var(--line-d)}
.sol-tagline{margin-top:var(--s2);font-weight:800;text-transform:uppercase;
  letter-spacing:.01em;font-size:clamp(1.05rem,1.6vw,1.35rem);color:var(--blu-b)}
.article-body{max-width:68ch;margin-top:var(--headgap);font-size:clamp(1rem,1.25vw,1.12rem)}
.article-body > * + *{margin-top:var(--s3)}
.article-body h2{margin-top:var(--s5);font-size:clamp(1.4rem,2.6vw,2rem)}
.article-body blockquote{border-left:3px solid var(--blu);padding-left:var(--s3);
  color:var(--fg-d);font-weight:600}
.article-body .fig{margin-block:var(--s5)}

/* solution detail pages: the spec sheet reuses the verdict board's dl/drow,
   without the two-sided score - one column of facts, not a comparison. Held
   to a fixed width so rows read as a short list, not a row stretched edge to
   edge with the value stranded far from its label. */
.specsheet{margin-top:var(--s4);border-top:1px solid var(--line-d)}
.specsheet .drow{display:flex;align-items:baseline;gap:1.4rem;
  padding:.95rem 0;border-bottom:1px solid var(--line-d)}
.specsheet dt{flex:0 0 30%;font-size:.72rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--mut-d)}
.specsheet dd{flex:1;min-width:0;font-weight:700;font-size:1rem;text-align:left}
.solcta{display:flex;flex-wrap:wrap;align-items:center;gap:1.6rem;max-width:640px;
  margin-top:var(--s5);padding-top:var(--s4);border-top:1px solid var(--line-d)}
/* .plink carries its own margin-top for when it follows a paragraph - inside
   this flex row that margin only pushed it off-centre from the button */
.solcta .plink{margin-top:0}

/* error + placeholder pages */
.errpage{display:flex;align-items:center;min-height:60svh}
.errpage h1{margin-top:var(--s2)}
.errpage .lead{margin-top:var(--s3);max-width:48ch}
.errcta{margin-top:var(--s5)}

/* compact footer on subpages: no giant closing headline above it */
/* the same handover on every subpage: content ends, the closing block begins */
.subfoot{padding-block:var(--s5) var(--s4);border-top:2px solid var(--blu)}
.subfoot .mail{margin-top:0}

@media (max-width:1023px){
  .news-grid{grid-template-columns:1fr}
}
