/* ═══════════════════════════════════════════════════════════════════
   ORBIT — Renus Tech production stylesheet
   Built from the two brand colours in the vector mark. The violet is
   their interpolation and only ever appears inside a gradient.
   No all-caps anywhere: wide tracking belongs to the logo, not labels.
   ═══════════════════════════════════════════════════════════════════ */

:root{
  --magenta:#D60D82; --magenta-deep:#B50A6D; --magenta-lift:#F2559F;
  --cyan:#0086A1; --cyan-deep:#00697F; --cyan-lift:#2FB8D4;
  --violet:#6E4A93;
  --ink:#16111F; --body-c:#4B4359; --mute:#877E96;
  --line:#EAE6EF; --sunk:#F7F5F9; --paper:#FFFFFF;
  --field:#0B0716; --field-1:#150E24;

  --r-block:56px; --r-card:28px; --r-tile:14px; --r-pill:999px;
  --plane:1200px;
  --f-display:'Jost','Century Gothic',system-ui,sans-serif;
  --f-body:'IBM Plex Sans',system-ui,sans-serif;
  --f-data:'IBM Plex Mono',ui-monospace,monospace;

  --bg:var(--paper); --tx:var(--ink); --tx-soft:var(--body-c); --tx-mute:var(--mute);
  --surface:var(--sunk); --hair:var(--line);
  --accent:var(--magenta-deep); --accent-flat:var(--magenta); --cool:var(--cyan-deep);
  --c-prov:#0086A1; --c-act:#D60D82;
}
/* Single-theme by choice: the mark is drawn for white, and the site commits
   to that ground in every viewer preference. One logo file, everywhere.
   (The dark chart palette #159FBE/#E22D93 stays validated in tools/ if a
   dark surface is ever reintroduced.) */

/* ── base ── */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:var(--bg);color:var(--tx);
  font-family:var(--f-body);font-size:18px;line-height:1.67;
  overflow-x:hidden;-webkit-font-smoothing:antialiased}
.plane{max-width:var(--plane);margin:0 auto;padding:0 32px}
img{max-width:100%}
a{color:var(--accent)}

h1,h2,h3{font-family:var(--f-display);font-weight:300;margin:0;text-wrap:balance;letter-spacing:.005em;color:var(--tx)}
h1{font-size:clamp(40px,5.4vw,60px);line-height:1.14;font-weight:200}
h2{font-size:clamp(32px,4vw,44px);line-height:1.18}
h3{font-size:clamp(21px,2.2vw,27px);line-height:1.28;font-weight:400}
p{margin:0;max-width:62ch}
.eyebrow{display:block;font-family:var(--f-data);font-size:12.5px;font-weight:500;
  letter-spacing:.06em;color:var(--accent);margin-bottom:18px}
.lede{font-size:20px;line-height:1.6;color:var(--tx-soft);max-width:52ch}
.muted{color:var(--tx-mute);font-size:16px}
.small{font-size:15px;color:var(--tx-mute);line-height:1.6}

section{padding:104px 0}
/* a section that continues the one above it, rather than starting a new
   idea -- 104px of separation instead of 208px */
.pt-0{padding-top:0}
.stack{display:flex;flex-direction:column;gap:26px}
.mt-1{margin-top:14px}.mt-2{margin-top:22px}.mt-3{margin-top:36px}.mt-4{margin-top:48px}

/* ── buttons ──
   Every CTA shares one glassy hover: a translucent fill lifted over a
   backdrop blur, a light top-edge highlight, and a sheen that sweeps
   across on entry. backdrop-filter is progressive — where it is not
   supported the button still gets the tint, lift and highlight, just
   without the blur. */
.btn{position:relative;overflow:hidden;isolation:isolate;
  display:inline-block;font-family:var(--f-body);font-size:16px;font-weight:600;
  padding:15px 32px;border-radius:var(--r-pill);text-decoration:none;border:2px solid transparent;
  cursor:pointer;
  transition:transform .22s ease,box-shadow .22s ease,background .22s ease,
             color .22s ease,border-color .22s ease,backdrop-filter .22s ease}
.btn:focus-visible{outline:none;box-shadow:0 0 0 4px rgba(214,13,130,.3)}

/* the sweep: a soft highlight that crosses once per hover */
.btn::after{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;
  background:linear-gradient(105deg,transparent 30%,rgba(255,255,255,.38) 50%,transparent 70%);
  transform:translateX(-120%);transition:transform .55s cubic-bezier(.22,1,.36,1)}
.btn:hover::after,.btn:focus-visible::after{transform:translateX(120%)}

/* the glass: an inset top highlight that only shows on hover */
.btn::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.55),inset 0 -1px 0 rgba(255,255,255,.12);
  opacity:0;transition:opacity .22s ease}
.btn:hover::before,.btn:focus-visible::before{opacity:1}

.btn-primary{background:var(--accent-flat);color:#fff}
.btn-primary:hover{transform:translateY(-2px);
  background:color-mix(in srgb,var(--accent-flat) 82%,transparent);
  backdrop-filter:blur(10px) saturate(150%);-webkit-backdrop-filter:blur(10px) saturate(150%);
  box-shadow:0 14px 34px -14px var(--magenta),0 0 0 1px rgba(255,255,255,.25) inset}

.btn-ghost{border-color:currentColor;color:var(--tx);background:transparent}
.btn-ghost:hover{transform:translateY(-2px);color:var(--tx);
  background:color-mix(in srgb,var(--tx) 8%,transparent);
  backdrop-filter:blur(10px) saturate(140%);-webkit-backdrop-filter:blur(10px) saturate(140%);
  border-color:color-mix(in srgb,var(--tx) 45%,transparent);
  box-shadow:0 12px 30px -16px rgba(22,17,31,.5)}

.btn-on-colour{background:#fff;color:var(--ink)}
.btn-on-colour:hover{transform:translateY(-2px);
  background:rgba(255,255,255,.82);
  backdrop-filter:blur(10px) saturate(150%);-webkit-backdrop-filter:blur(10px) saturate(150%);
  box-shadow:0 14px 34px -14px rgba(0,0,0,.45)}

.btn-sm{padding:10px 22px;font-size:14.5px}
/* ── nav ── */
.nav{position:sticky;top:0;z-index:300;background:color-mix(in srgb,var(--bg) 88%,transparent);
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  border-bottom:1px solid var(--hair)}
.nav-in{display:flex;align-items:center;gap:26px;height:84px}
.nav-logo{display:flex;align-items:center;flex-shrink:0;text-decoration:none}
.nav-logo img{height:70px;width:auto;display:block}

.nav-links{display:flex;gap:8px;align-items:center;flex:1;justify-content:center}
.nav-group{position:relative}
.nav-top{display:inline-flex;align-items:center;gap:6px;font-family:var(--f-body);
  font-size:15px;font-weight:500;color:var(--tx-soft);text-decoration:none;white-space:nowrap;
  padding:9px 16px;border-radius:var(--r-pill);border:0;background:none;cursor:pointer;
  transition:color .15s,background .15s}
.nav-top:hover{color:var(--tx);background:var(--surface)}
.nav-top.on{color:var(--accent);font-weight:600}
.nav-top .caret{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round;transition:transform .2s}
.nav-group.open .nav-top .caret{transform:rotate(180deg)}
/* The 10px gap between button and panel is a hover dead zone: the panel is
   positioned outside .nav-group's box, so travelling across the gap fires
   mouseleave and shuts the menu before the pointer arrives. This invisible
   bridge spans the gap and belongs to the menu, keeping the pointer inside
   the group's subtree the whole way. */
.nav-menu::before{content:"";position:absolute;top:-12px;left:0;right:0;height:12px}
.nav-menu{position:absolute;top:calc(100% + 10px);left:50%;transform:translateX(-50%) translateY(-6px);
  min-width:300px;background:var(--bg);border:1px solid var(--hair);border-radius:20px;
  box-shadow:0 24px 60px -28px rgba(22,17,31,.4),0 2px 6px -2px rgba(22,17,31,.08);
  padding:10px;display:flex;flex-direction:column;gap:2px;
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .18s ease,transform .18s ease,visibility .18s}
.nav-group.open .nav-menu{opacity:1;visibility:visible;pointer-events:auto;transform:translateX(-50%) translateY(0)}
.nav-menu a{display:flex;flex-direction:column;gap:2px;padding:11px 16px;border-radius:14px;
  text-decoration:none;transition:background .15s}
.nav-menu a:hover{background:var(--surface)}
.nav-menu a b{font-size:15px;font-weight:600;color:var(--tx)}
.nav-menu a span{font-size:13px;color:var(--tx-mute);line-height:1.4}
.nav-menu a.on b{color:var(--accent)}
.nav-cta{flex-shrink:0}
.nav-burger{display:none;background:none;border:0;cursor:pointer;padding:8px;flex-shrink:0}
.nav-burger span{display:block;width:22px;height:2px;background:var(--tx);border-radius:2px;margin:5px 0;transition:.2s}

/* ── heroes ── */
.hero{padding:88px 0 96px;overflow:hidden;position:relative}
.hero-centre{position:relative;text-align:center;display:flex;flex-direction:column;align-items:center}
.hero-centre > *:not(.hero-ring){position:relative;z-index:1}
.hero-centre h1{max-width:17ch}
.hero-centre .lede{margin-top:22px;max-width:58ch}
/* Button rows behave the same everywhere; only the hero centres them.
   Previously only .hero .btns was styled, so every other CTA block
   carried the same three declarations inline. */
.btns{display:flex;gap:14px;flex-wrap:wrap}
.hero .btns{margin-top:34px;justify-content:center}
.page-hero{padding:88px 0 64px}
.page-hero .lede{margin-top:20px}

/* ── hero ring ──
   The supplied Ring.svg tumbling about ITS OWN long axis.

   Why the nesting. The artwork is a flattened ellipse whose long axis runs
   at about -29.8deg (from 15,210 up to 342,23), and it already has
   perspective baked into the drawing. Spinning that flat picture about the
   viewport Y axis just squashes it horizontally — it reads as a turning
   card, not a ring. To tumble like a real ring it has to rotate about the
   axis it was drawn around, so the transform is composed:

     A · B · C  =  rotate(-29.8deg) · rotateX(t) · rotate(29.8deg)

   C swings the long axis onto the horizontal, B tumbles about that
   horizontal (which is now the ring's own axis), A puts the whole thing
   back at its drawn angle. Each step needs its own element because CSS
   composes a single transform per element.

   It sits ABOVE the copy (z-index 2) so it genuinely passes in front of the
   headline, and opacity is keyed to the same 26s timeline as the tumble:
   most solid when face-on and crossing the text, faint when edge-on.

   pointer-events:none throughout — a decorative layer over live text must
   never eat a click on the CTA beneath it. */
.hero-ring{position:absolute;left:50%;top:50%;
  width:min(780px,100vw);aspect-ratio:358/234;
  transform:translate(-50%,-56%);z-index:2;pointer-events:none;
  perspective:1500px;perspective-origin:50% 48%;
  animation:ring-in 1.5s cubic-bezier(.22,1,.36,1) both}
@keyframes ring-in{from{opacity:0}to{opacity:1}}

.ring-axis{position:absolute;inset:0;transform-style:preserve-3d;
  transform:rotate(-29.8deg)}                     /* A — back to drawn angle */
.ring-spin{position:absolute;inset:0;transform-style:preserve-3d;
  animation:ring-tumble 26s linear infinite, ring-face 26s ease-in-out infinite}
.ring-align{position:absolute;inset:0;transform-style:preserve-3d;
  transform:rotate(29.8deg)}   /* C — long axis to horizontal */
.hero-ring svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}

/* B — tumble about the ring's own axis */
@keyframes ring-tumble{
  from{transform:rotateX(0deg)}
  to  {transform:rotateX(360deg)}
}
/* face-on at 0/180 (sweeping across the text) -> solid; edge-on -> faint */
@keyframes ring-face{
  0%{opacity:.42} 25%{opacity:.13} 50%{opacity:.42} 75%{opacity:.13} 100%{opacity:.42}
}
/* ── ribbon divider (the mark's tapered stroke) ── */
.ribbon{display:block;width:100%;height:34px;overflow:visible;pointer-events:none;margin:8px 0}
.ribbon.flip{transform:scale(-1,-1)}

/* ── full-bleed colour blocks ──
   Each carries the mark as a large, very low-opacity watermark bleeding off
   the right edge. It is decorative only (the real logo lives in nav and
   footer), so it is a background-image rather than an <img> — nothing for a
   screen reader to announce, and it cannot be mistaken for a second brand. */
.bleed{border-radius:var(--r-block);margin:0 32px;padding:96px 0;color:#fff;
  position:relative;overflow:hidden;isolation:isolate}
.bleed::after{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  right:-70px;top:50%;width:min(460px,46%);aspect-ratio:566/417;
  transform:translateY(-50%);
  background:var(--wm) center/contain no-repeat;
  opacity:.10;
  animation:wm-drift 26s ease-in-out infinite}
@keyframes wm-drift{
  0%,100%{transform:translateY(-50%) scale(1) rotate(0deg)}
  50%    {transform:translateY(-54%) scale(1.04) rotate(-2deg)}
}
.bleed .plane{padding:0 64px;position:relative;z-index:1}
.bleed h2,.bleed h3{color:#fff}
.bleed p{color:rgba(255,255,255,.87)}
.bleed .eyebrow{color:rgba(255,255,255,.75)}
.bleed .muted,.bleed .small{color:rgba(255,255,255,.65)}
.bleed-magenta{background:var(--magenta)}
.bleed-cyan{background:var(--cyan)}
.bleed-ink{background:var(--field)}

/* ── cards ── */
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:24px}
.cards-2{display:grid;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));gap:24px}
.card{background:var(--surface);border-radius:var(--r-card);padding:38px 34px;
  display:flex;flex-direction:column;gap:0;
  transition:transform .28s cubic-bezier(.2,.7,.3,1),box-shadow .28s cubic-bezier(.2,.7,.3,1)}
.card:hover{transform:translateY(-5px);box-shadow:0 16px 38px rgba(23,21,26,.09)}

/* A single flex gap spaced every child equally, which is the wrong model:
   a heading and the line under it are one unit, while an eyebrow above it
   and a second paragraph below are not. Everything sat at the same 14px
   and the heading floated away from its own supporting line.
   Gap is zero and each relationship is stated once, here, for every card
   on the site.
   The values are BOX gaps and deliberately unequal, because half-leading
   differs per element (span 4.4px, h3 2.9px, p 5.0px at these sizes) and
   equal box values do not read as equal. Optically these land at roughly
   11px, 13px and 21px. */
.card .ic{margin-bottom:14px}
.card .n + *{margin-top:4px}     /* eyebrow/number belongs to what follows */
.card h3 + p{margin-top:5px}     /* heading and its supporting line: one unit */
.card p + p{margin-top:11px}     /* separate paragraphs: genuinely separate */
.card a.more{margin-top:auto;padding-top:16px}

/* One compact card, not four. The step lists and short definition cards
   had drifted to 22x28, 24x28 and 22x26 across four pages via inline
   styles -- close enough to look accidental rather than deliberate,
   which is exactly how it read. Only the padding differs; the internal
   rhythm above is shared. */
.card.compact{padding:22px 28px}
/* Column counts and the tight gap that goes with a stacked list. */
.cards-one{grid-template-columns:1fr}
.cards-two{grid-template-columns:1fr 1fr}
.cards-tight{gap:14px}
@media (max-width:620px){ .cards-two{grid-template-columns:1fr} }
.card p{font-size:16px;line-height:1.62;color:var(--tx-soft)}
.card .n{font-family:var(--f-data);font-size:13px;letter-spacing:.02em;color:var(--accent)}
.card a.more{font-size:15px;font-weight:600;text-decoration:none;margin-top:auto}
.bleed .card{background:rgba(255,255,255,.13)}
.bleed .card p{color:rgba(255,255,255,.85)}
.bleed .card .n{color:rgba(255,255,255,.75)}

/* icon chip on a card */
.ic{width:48px;height:48px;border-radius:15px;display:flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--accent-flat) 12%,transparent);color:var(--accent)}
.ic.cool{background:color-mix(in srgb,var(--cyan) 12%,transparent);color:var(--cool)}
.ic svg{width:24px;height:24px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.bleed .ic{background:rgba(255,255,255,.16);color:#fff}

/* ── split / stats / steps ── */
.split{display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:center}
.stats{display:flex;gap:56px;flex-wrap:wrap}
.stat b{display:block;font-family:var(--f-data);font-size:46px;font-weight:500;line-height:1;
  font-variant-numeric:tabular-nums;color:var(--accent)}
.stat.cool b{color:var(--cool)}
.stat span{display:block;font-family:var(--f-data);font-size:13px;letter-spacing:.02em;
  color:var(--tx-mute);margin-top:10px}
.bleed .stat b{color:#fff}
.bleed .stat span{color:rgba(255,255,255,.72)}

.taper-list{list-style:none;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:10px}
.taper-list li{font-family:var(--f-data);font-size:13.5px;padding:8px 16px;border-radius:var(--r-pill);
  border:1px solid var(--hair);color:var(--tx-mute)}
.chip-row{display:flex;flex-wrap:wrap;gap:10px}
.chip-row .chip{font-family:var(--f-data);font-size:13.5px;padding:8px 16px;border-radius:var(--r-pill);
  background:var(--surface);color:var(--tx-soft)}

/* ── comparison table ── */
.cmp-wrap{overflow-x:auto;border:1px solid var(--hair);border-radius:var(--r-card)}
.cmp{width:100%;border-collapse:collapse;font-size:15.5px;min-width:560px}
.cmp th,.cmp td{text-align:left;padding:16px 22px;border-bottom:1px solid var(--hair)}
.cmp th{font-family:var(--f-data);font-size:13px;font-weight:500;color:var(--tx-mute);background:var(--surface)}
.cmp tr:last-child td{border-bottom:0}
.cmp td:first-child{color:var(--tx-mute);font-size:14px}
.cmp td{color:var(--tx-soft)}
.cmp td b{color:var(--tx)}

/* ── forms ── */
.form{display:flex;flex-direction:column;gap:20px;max-width:560px}
.field{display:flex;flex-direction:column;gap:8px}
.field label{font-family:var(--f-data);font-size:13px;color:var(--tx-mute)}
.field input,.field textarea{font-family:var(--f-body);font-size:16px;color:var(--tx);
  background:var(--surface);border:1px solid var(--hair);border-radius:var(--r-tile);padding:13px 18px}
.field textarea{min-height:130px;resize:vertical}
.field input:focus,.field textarea:focus{outline:none;border-color:var(--accent-flat);
  box-shadow:0 0 0 3px rgba(214,13,130,.25)}

/* ── dashboard (homepage banner) ──
   Series colours validated for CVD: deutan separation sits in the marginal
   band, so identity never rides on hue alone — provisioned is dashed,
   actual is solid over a fill, the unused gap is hatched, all labelled. */
.banner{position:relative;margin-top:64px;padding:0 32px}
/* inside a .plane, which already pads horizontally -- padding again
   would inset it twice */
.banner-inset{margin-top:8px;padding:0}
.dash{position:relative;z-index:1;max-width:1120px;margin:0 auto;
  background:var(--bg);border:1px solid var(--hair);border-radius:20px;
  box-shadow:0 40px 90px -50px rgba(22,17,31,.45),0 2px 8px -2px rgba(22,17,31,.08);overflow:hidden}
.dash-bar{display:flex;align-items:center;gap:14px;padding:13px 18px;
  border-bottom:1px solid var(--hair);background:var(--surface)}
.dots{display:flex;gap:6px}
.dots i{width:9px;height:9px;border-radius:50%;background:var(--hair);display:block}
.dash-title{font-family:var(--f-data);font-size:13px;color:var(--tx)}
.dash-range{margin-left:auto;font-family:var(--f-data);font-size:12px;color:var(--tx-mute);
  border:1px solid var(--hair);border-radius:999px;padding:4px 12px;display:flex;align-items:center;gap:7px}
.dash-range::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--accent-flat);
  animation:live 2.4s ease-in-out infinite}
@keyframes live{0%,100%{opacity:.35}50%{opacity:1}}
.dash-body{display:grid;grid-template-columns:148px 1fr 210px;gap:0}
.dash-nav{display:flex;flex-direction:column;gap:2px;padding:18px 12px;border-right:1px solid var(--hair)}
.dash-nav a{font-size:13.5px;color:var(--tx-mute);text-decoration:none;padding:8px 12px;border-radius:999px}
.dash-nav a.on{background:var(--accent-flat);color:#fff}
.dash-main{padding:20px 22px}
.tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:20px}
.tile{background:var(--surface);border-radius:14px;padding:14px 16px}
.tile b{display:block;font-family:var(--f-data);font-size:26px;font-weight:500;line-height:1.1;
  color:var(--tx);font-variant-numeric:tabular-nums}
.tile span{display:block;font-size:12.5px;color:var(--tx-mute);margin-top:4px}
.tile.hot b{color:var(--accent)}
.plot-head{display:flex;align-items:baseline;gap:16px;flex-wrap:wrap;margin-bottom:10px}
.plot-head h4{margin:0;font-family:var(--f-display);font-weight:400;font-size:16px;color:var(--tx)}
.keys{display:flex;gap:14px;margin-left:auto;flex-wrap:wrap}
.key{font-family:var(--f-data);font-size:11.5px;color:var(--tx-mute);display:inline-flex;align-items:center;gap:6px}
.key::before{content:"";width:16px;height:0;display:block}
.key-prov::before{border-top:2px dashed var(--c-prov)}
.key-act::before{border-top:2px solid var(--c-act)}
.key-gap::before{height:9px;border:1px solid var(--c-prov);opacity:.5;
  background:repeating-linear-gradient(45deg,var(--c-prov) 0 1px,transparent 1px 5px)}
.chart{width:100%;height:auto;display:block}
.chart .grid{stroke:var(--hair);stroke-width:1}
.chart .ax{font-family:var(--f-data);font-size:9px;fill:var(--tx-mute)}
.chart .ln-prov{fill:none;stroke:var(--c-prov);stroke-width:2;stroke-dasharray:5 4;stroke-linecap:round}
.chart .ln-act{fill:none;stroke:var(--c-act);stroke-width:2;stroke-linecap:round}
.chart .dot-prov{fill:var(--c-prov)}
.chart .dot-act{fill:var(--c-act)}
/* draw-in: lines sweep left→right once the panel enters the viewport.
   pathLength=1 on both lines makes the dash maths trivial. The dashed
   provisioned line keeps its dash pattern; the draw happens on a wrapper
   group's clip instead of dashoffset for that one. Simpler: actual line
   draws by dashoffset; provisioned + fills fade up after. */
.dash .ln-act{stroke-dasharray:1;stroke-dashoffset:1}
.dash .ln-prov,.dash .fill-a,.dash .fill-g,.dash .dot-prov,.dash .dot-act{opacity:0}
.dash.in .ln-act{animation:draw 1.5s .25s cubic-bezier(.4,0,.2,1) forwards}
.dash.in .ln-prov{animation:fadeup .7s 1.1s forwards}
.dash.in .fill-a{animation:fadeup .8s 1.35s forwards}
.dash.in .fill-g{animation:fadeup .8s 1.6s forwards}
.dash.in .dot-prov,.dash.in .dot-act{animation:fadeup .5s 1.8s forwards}
@keyframes draw{to{stroke-dashoffset:0}}
@keyframes fadeup{to{opacity:1}}
.dash-side{padding:20px 18px;border-left:1px solid var(--hair)}
.side-h{font-family:var(--f-data);font-size:12.5px;color:var(--tx-mute);margin:0 0 14px}
.find{margin-bottom:14px;opacity:0;transform:translateX(10px);transition:opacity .5s ease,transform .5s ease}
.dash.in .find{opacity:1;transform:none}
.dash.in .find:nth-child(2){transition-delay:.9s}
.dash.in .find:nth-child(3){transition-delay:1.15s}
.dash.in .find:nth-child(4){transition-delay:1.4s}
.find p{font-size:13px;line-height:1.5;color:var(--tx-soft);margin:5px 0 0;max-width:none}
.pill{font-family:var(--f-data);font-size:10.5px;padding:2px 9px;border-radius:999px;border:1px solid currentColor}
.pill.crit{color:#C4362B}.pill.warn{color:#B26A00}.pill.ok{color:#0F8A5F}

.chip-float{position:absolute;z-index:2;font-family:var(--f-data);font-size:12.5px;
  padding:9px 16px;border-radius:999px;color:#fff;white-space:nowrap;
  box-shadow:0 12px 26px -12px rgba(22,17,31,.5)}
.chip-a{background:var(--magenta);left:6%;top:22%}
.chip-b{background:var(--field);right:5%;bottom:16%}

/* ── locations map ── */
/* ── scroll-rotated globe ──
   The canvas is drawn by assets/globe.js: scroll position through the
   section drives the globe's longitude, so offices rotate into view as
   part of the sphere rather than sitting on top of a flat map. */
.globe-wrap{background:var(--surface);border-radius:var(--r-card);padding:34px;
  display:grid;grid-template-columns:1.25fr .75fr;gap:40px;align-items:center;overflow:hidden}
.globe-stage{width:100%;max-width:560px;margin-inline:auto;aspect-ratio:1/1;position:relative}
.globe-stage canvas{display:block;width:100%;height:100%}

.globe-lbl{font-family:var(--f-data);font-size:13px;color:var(--tx-mute);margin:0 0 20px}
.globe-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:18px}
.globe-list li{display:grid;grid-template-columns:10px 1fr;column-gap:14px;row-gap:2px;align-items:baseline}
.globe-list i{grid-row:1/3;width:9px;height:9px;border-radius:50%;background:var(--cool);
  display:block;transform:translateY(4px)}
.globe-list i.hq{background:var(--accent-flat);box-shadow:0 0 0 4px color-mix(in srgb,var(--accent-flat) 18%,transparent)}
.globe-list b{font-size:17px;font-weight:600;color:var(--tx)}
.globe-list span{grid-column:2;font-family:var(--f-data);font-size:13px;color:var(--tx-mute)}

@media (max-width:900px){
  .globe-wrap{grid-template-columns:1fr;gap:26px;padding:24px}
  .globe-stage{max-width:420px}
}

/* ── who we've worked with ──
   Typographic wordmarks, not client logo files: we do not hold usage rights
   or artwork for these brands. Swap each .cl span for an <img> once real
   logos and written permission are in hand. Marquee duplicates the row and
   translates by exactly -50%, so the loop is seamless. */
.clients{padding:56px 0;border-block:1px solid var(--hair);overflow:hidden}
.clients-lbl{font-family:var(--f-data);font-size:13px;color:var(--tx-mute);text-align:center;margin:0 auto 30px}
.marquee{display:flex;width:max-content;animation:marquee 42s linear infinite}
.clients:hover .marquee{animation-play-state:paused}
@keyframes marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.marquee-row{display:flex;align-items:center;gap:60px;padding-right:60px;flex:none}
.cl{font-family:var(--f-display);font-size:26px;font-weight:400;letter-spacing:.04em;
  color:var(--tx-mute);white-space:nowrap;opacity:.72;transition:opacity .2s,color .2s}
.cl:hover{opacity:1;color:var(--tx)}
.clients-note{font-size:14px;color:var(--tx-mute);text-align:center;margin:28px auto 0}

/* ── media panel ──
   Holds either a generated brand visual or a supplied photograph; both
   fill the same frame, so a slot can be swapped without touching layout. */
.media{border-radius:var(--r-card);overflow:hidden;background:var(--surface);
  display:block;width:100%;aspect-ratio:4/3}
.media svg{display:block;width:100%;height:100%}
.media .photo{display:block;width:100%;height:100%;object-fit:cover}
.media-tall{aspect-ratio:3/4}
.media-wide{aspect-ratio:16/7}

/* ── reveal ── */
.reveal{opacity:0;transform:translateY(26px);transition:opacity .7s ease,transform .7s ease}
.reveal.in{opacity:1;transform:none}
/* children stagger in after their container, so a card row arrives as a
   sequence rather than a slab */
.reveal.stagger > *{opacity:0;transform:translateY(18px) scale(.985);
  transition:opacity .6s cubic-bezier(.2,.7,.3,1),transform .6s cubic-bezier(.2,.7,.3,1)}
.reveal.stagger.in > *{opacity:1;transform:none}
.reveal.stagger.in > *:nth-child(1){transition-delay:.06s}
.reveal.stagger.in > *:nth-child(2){transition-delay:.16s}
.reveal.stagger.in > *:nth-child(3){transition-delay:.26s}
.reveal.stagger.in > *:nth-child(4){transition-delay:.36s}
.reveal.stagger.in > *:nth-child(5){transition-delay:.46s}
.reveal.stagger.in > *:nth-child(6){transition-delay:.56s}

/* ── footer ── */
footer{padding:88px 0 64px;border-top:1px solid var(--hair);margin-top:24px}
.foot-grid{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:40px}
.foot-name{font-family:var(--f-data);font-size:13px;letter-spacing:.02em;color:var(--tx);margin:0 0 14px}
footer address{font-style:normal;line-height:1.75;color:var(--tx-mute);font-size:16px}
footer .foot-links a{display:block;font-size:15.5px;color:var(--tx-mute);text-decoration:none;margin-bottom:10px}
footer .foot-links a:hover{color:var(--accent)}
footer a{color:var(--accent);text-decoration:none}
footer a:hover{text-decoration:underline}
.foot-logo{height:88px;width:auto;display:block;margin-bottom:16px}
.foot-bar{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
  margin-top:52px;padding-top:26px;border-top:1px solid var(--hair)}
.foot-bar p{font-size:13.5px;color:var(--tx-mute)}

/* ── responsive ── */
@media (max-width:1020px){
  .dash-body{grid-template-columns:1fr}
  .dash-nav{flex-direction:row;overflow-x:auto;border-right:0;border-bottom:1px solid var(--hair)}
  .dash-side{border-left:0;border-top:1px solid var(--hair)}
  .chip-float{display:none}
  .banner{padding:0 16px}
}
@media (max-width:1040px){
  .nav-links{display:none}
  .nav-links.open{display:flex;flex-direction:column;position:absolute;top:72px;left:0;right:0;
    background:var(--bg);border-bottom:1px solid var(--hair);padding:18px 24px;gap:6px;
    align-items:stretch;max-height:calc(100vh - 72px);overflow-y:auto}
  .nav-burger{display:block}
  .nav-cta{display:none}
  .nav-in{height:72px}
  .nav-logo img{height:58px}
  /* dropdowns become plain stacked sections — no hover, no overlay */
  .nav-group{position:static}
  .nav-top{width:100%;justify-content:space-between}
  .nav-menu{position:static;transform:none;min-width:0;box-shadow:none;border:0;
    background:transparent;padding:0 0 8px 12px;opacity:1;visibility:visible;pointer-events:auto;
    max-height:0;overflow:hidden;transition:max-height .25s ease}
  .nav-group.open .nav-menu{transform:none;max-height:420px}
  .nav-menu a span{display:none}
  .split{grid-template-columns:1fr;gap:40px}
  .bleed{margin:0 16px;padding:72px 0;border-radius:36px}
  .bleed .plane{padding:0 28px}
  section{padding:76px 0}
  body{font-size:17px}
  .foot-grid{grid-template-columns:1fr 1fr}
}
@media (max-width:620px){
  .foot-grid{grid-template-columns:1fr}
  .tiles{grid-template-columns:1fr}
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition:none!important}
  .reveal{opacity:1;transform:none}
  .dash .ln-act,.dash .ln-prov,.dash .fill-a,.dash .fill-g,.dash .dot-prov,.dash .dot-act{opacity:1;stroke-dashoffset:0}
  .find{opacity:1;transform:none}
  .reveal.stagger > *{opacity:1;transform:none}
  .marquee{animation:none;width:auto;flex-wrap:wrap;justify-content:center;gap:40px}
  .marquee-row:nth-child(2){display:none}
}

/* ── cookie consent ──
   Sits bottom-left, not as a full-width bar and never as a modal: this
   site sets no non-essential cookies until someone opts in, so blocking
   the page to ask would be theatre. Decline is a real button with the
   same weight as accept, and dismissing without choosing does NOT count
   as consent — the banner simply returns next visit. */
.cookie{position:fixed;left:24px;bottom:24px;z-index:400;max-width:400px;
  background:color-mix(in srgb,var(--bg) 86%,transparent);
  backdrop-filter:blur(18px) saturate(150%);-webkit-backdrop-filter:blur(18px) saturate(150%);
  border:1px solid var(--hair);border-radius:22px;padding:24px 26px;
  box-shadow:0 28px 70px -30px rgba(22,17,31,.45),0 2px 8px -3px rgba(22,17,31,.12);
  transform:translateY(18px);opacity:0;visibility:hidden;
  transition:opacity .35s ease,transform .35s cubic-bezier(.22,1,.36,1),visibility .35s}
.cookie.show{opacity:1;transform:none;visibility:visible}
.cookie h4{font-family:var(--f-display);font-weight:400;font-size:19px;margin:0 0 8px;color:var(--tx)}
.cookie p{font-size:15px;line-height:1.55;color:var(--tx-soft);margin:0;max-width:none}
.cookie p a{color:var(--accent)}
.cookie-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:18px}
.cookie .btn{font-size:14.5px;padding:11px 22px;border-width:1.5px}
.cookie-close{position:absolute;top:14px;right:14px;width:30px;height:30px;
  display:flex;align-items:center;justify-content:center;
  background:none;border:0;border-radius:50%;cursor:pointer;color:var(--tx-mute);
  transition:background .15s,color .15s}
.cookie-close:hover{background:var(--surface);color:var(--tx)}
.cookie-close svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round}
@media (max-width:600px){
  .cookie{left:14px;right:14px;bottom:14px;max-width:none;padding:20px 22px}
}

@media (prefers-reduced-motion:reduce){
  .ring-spin{animation:none}
  .btn::after{display:none}
}

/* platform mark — the official vendor logo when supplied, sized modestly:
   it is a credential on our page, not a hero graphic */
.platform-mark{display:flex;justify-content:flex-start;margin-bottom:6px}
.platform-mark img{height:52px;width:auto;display:block}
.platform-note{font-family:var(--f-data);font-size:14px;color:var(--tx-mute);margin:0}
@media (max-width:600px){.platform-mark img{height:42px}}


/* ── blog ──────────────────────────────────────────────────────────
   Structure follows the reference the owner picked: the headline and
   meta sit ABOVE the artwork, and a card carries no panel, border or
   shadow. The image is the only filled element, so the grid reads as
   type on the page ground rather than a wall of tiles. Renus keeps its
   own rounding and colour — copying the layout, not the brand. */
.post-lead,.post-card{display:block;text-decoration:none;color:inherit}
.post-lead h2{font-size:clamp(30px,4vw,50px);line-height:1.08;max-width:20ch}
.post-card h3{font-size:24px;line-height:1.16;font-weight:400;max-width:24ch}
.post-lead:hover h2,.post-card:hover h3{color:var(--accent)}
.post-lead h2,.post-card h3{transition:color .2s ease}

.posts{display:grid;grid-template-columns:repeat(3,1fr);gap:56px 32px;margin-top:72px}

/* meta line: month, category, read time, then the affordance */
.post-meta{display:flex;align-items:center;flex-wrap:wrap;gap:0 22px;margin:18px 0 26px;
  font-family:var(--f-data);font-size:13.5px;color:var(--tx-mute)}
.post-meta .mt-kind{color:var(--accent)}
.post-meta .mt-cta{display:inline-flex;align-items:center;gap:7px;color:var(--tx);font-weight:500}
.post-meta .mt-cta svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;transition:transform .22s ease}
.post-lead:hover .mt-cta svg,.post-card:hover .mt-cta svg{transform:translateX(4px)}

/* artwork. Square in the grid, panoramic for the lead — same source SVG,
   which slices rather than squashes because of its preserveAspectRatio. */
.post-shot{display:block;overflow:hidden;border-radius:var(--r-card);background:var(--surface)}
.post-shot img{display:block;width:100%;height:100%;object-fit:cover;
  aspect-ratio:1/1;transition:transform .5s cubic-bezier(.2,.7,.3,1)}
.post-shot-wide img{aspect-ratio:21/9}
.post-lead:hover .post-shot img,.post-card:hover .post-shot img{transform:scale(1.03)}

/* article column — measure is narrower than .plane; long-form prose at
   full page width is hard to track back to the next line */
.post-hero{padding-bottom:32px}
.post-hero .plane,.post-body .plane,.post-foot{max-width:800px}
.post-by{font-family:var(--f-data);font-size:14px;color:var(--tx-mute);margin-top:22px}
.post-art{max-width:1180px;margin:0 auto 56px;padding:0 32px}
.post-art .post-shot img{aspect-ratio:21/9}
.post-body{padding:0 0 24px}
.post-body h2{font-size:30px;margin:48px 0 16px}
.post-body p{font-size:18px;line-height:1.72;color:var(--tx-soft);margin:0 0 18px}
.post-body ul{margin:0 0 22px;padding-left:22px}
.post-body li{font-size:18px;line-height:1.68;color:var(--tx-soft);margin-bottom:12px}
.post-body li b,.post-body p b{color:var(--tx);font-weight:600}
.post-body blockquote{margin:28px 0;padding:4px 0 4px 24px;border-left:2px solid var(--accent);
  font-size:19px;line-height:1.6;color:var(--tx)}

.post-foot{display:flex;justify-content:space-between;align-items:center;gap:24px;flex-wrap:wrap;
  margin:0 auto;padding:28px 32px 8px;border-top:1px solid var(--hair)}
.post-back{display:inline-flex;align-items:center;gap:9px;font-size:15px;font-weight:600;
  text-decoration:none;color:var(--accent)}
.post-back svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;transform:rotate(180deg)}

/* ── social ────────────────────────────────────────────────────── */
.social{display:flex;gap:10px;flex-wrap:wrap}
.social-a{display:inline-flex;align-items:center;gap:9px;text-decoration:none;
  font-size:15px;color:var(--tx-soft);border:1px solid var(--hair);border-radius:var(--r-pill);
  padding:9px 16px;transition:color .2s ease,border-color .2s ease,transform .2s ease}
.social-a:hover{color:var(--accent);border-color:color-mix(in srgb,var(--accent) 40%,transparent);
  transform:translateY(-2px)}
.social-a svg{width:18px;height:18px;color:currentColor}
.social-lg .social-a{font-size:16px;padding:13px 22px}
footer .social-a{color:var(--tx-mute);border-color:color-mix(in srgb,var(--tx) 14%,transparent)}
footer .social-a:hover{color:var(--accent)}

.follow{display:grid;grid-template-columns:1.3fr 1fr;gap:48px;align-items:center}

@media (max-width:960px){
  .posts{grid-template-columns:repeat(2,1fr);gap:48px 28px}
}
@media (max-width:860px){
  .follow{grid-template-columns:1fr;gap:28px}
  .post-body h2{font-size:26px;margin-top:38px}
  .post-body p,.post-body li{font-size:17px}
  .post-shot-wide img,.post-art .post-shot img{aspect-ratio:16/9}
}
@media (max-width:620px){
  .posts{grid-template-columns:1fr;gap:44px}
  .post-card h3{font-size:22px}
}

/* blog index masthead — title and standfirst at the same size, separated
   by weight and colour rather than scale */
.blog-hero{padding-bottom:24px}
.blog-title{font-size:clamp(34px,5vw,60px);line-height:1.1;max-width:22ch}
.blog-title span{color:var(--tx-mute)}

/* ── open roles + application form ─────────────────────────────────
   Roles expand in place. Sending an applicant to the contact page to
   describe a job they were just reading loses them, and loses which
   role they meant. */
.roles-grid{display:grid;grid-template-columns:1.15fr .85fr;gap:56px;align-items:start}
.roles-list{display:flex;flex-direction:column;gap:14px}

.role{background:var(--surface);border-radius:var(--r-card);
  border:1px solid transparent;transition:border-color .2s ease}
.role[open]{border-color:var(--hair)}
.role summary{list-style:none;cursor:pointer;padding:28px 30px;position:relative;
  display:block;padding-right:64px}
.role summary::-webkit-details-marker{display:none}
.role summary:hover h3{color:var(--accent)}
.role h3{font-size:23px;line-height:1.25;margin:6px 0 0;transition:color .2s ease}
.role-n{font-family:var(--f-data);font-size:12.5px;letter-spacing:.06em;color:var(--accent)}
.role-facts{font-family:var(--f-data);font-size:13px;color:var(--tx-mute);margin:12px 0 0}
.role-more{position:absolute;right:26px;top:30px;width:34px;height:34px;border-radius:50%;
  border:1px solid var(--hair);display:flex;align-items:center;justify-content:center;
  transition:transform .25s ease,border-color .2s ease,background .2s ease}
.role-more svg{width:17px;height:17px;stroke:var(--tx);fill:none;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;transform:rotate(90deg)}
.role[open] .role-more{transform:rotate(180deg);background:var(--accent-flat);border-color:transparent}
.role[open] .role-more svg{stroke:#fff}
.role-body{padding:0 30px 28px}
.role-body p{font-size:16.5px;line-height:1.68;color:var(--tx-soft);margin:0 0 14px}
.role-body ul{margin:0 0 18px;padding-left:20px}
.role-body li{font-size:16px;line-height:1.62;color:var(--tx-soft);margin-bottom:9px}
.role-body b{color:var(--tx);font-weight:600}
.roles-none{font-size:17px;line-height:1.68;color:var(--tx-soft);background:var(--surface);
  border-radius:var(--r-card);padding:28px 30px;margin:0}

.apply{background:var(--surface);border-radius:var(--r-card);padding:30px;position:sticky;top:96px}
.apply h3{font-size:22px}
.apply .small{margin:8px 0 22px}
.apply-form{display:flex;flex-direction:column;gap:16px}
.fld{display:flex;flex-direction:column;gap:7px}
.fld-row{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.fld label{font-family:var(--f-data);font-size:13px;color:var(--tx)}
.fld-opt{color:var(--tx-mute)}
.fld input,.fld select,.fld textarea{font-family:var(--f-body);font-size:15.5px;color:var(--tx);
  background:var(--paper);border:1px solid var(--hair);border-radius:var(--r-tile);
  padding:12px 14px;width:100%;transition:border-color .2s ease,box-shadow .2s ease}
.fld textarea{resize:vertical;min-height:78px}
.fld input:focus,.fld select:focus,.fld textarea:focus{outline:none;border-color:var(--accent-flat);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent-flat) 16%,transparent)}
.fld input[type=file]{padding:10px 12px;font-size:14px}
.fld input[type=file]::file-selector-button{font-family:var(--f-body);font-size:14px;
  border:1px solid var(--hair);background:var(--surface);color:var(--tx);
  border-radius:var(--r-pill);padding:7px 14px;margin-right:12px;cursor:pointer}
.fld-note{font-size:13px;color:var(--tx-mute)}
.fld-check{display:flex;gap:11px;align-items:flex-start;font-size:14px;line-height:1.55;
  color:var(--tx-soft);margin-top:2px}
.fld-check input{margin-top:3px;accent-color:var(--accent-flat);width:16px;height:16px;flex:none}
.apply .btn{margin-top:6px;align-self:flex-start}
/* honeypot: present for bots, gone for everyone else */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

@media (max-width:960px){
  .roles-grid{grid-template-columns:1fr;gap:36px}
  .apply{position:static}
}
@media (max-width:620px){
  .fld-row{grid-template-columns:1fr}
  .role summary{padding:24px 22px;padding-right:58px}
  .role-body{padding:0 22px 24px}
}
.apply-alt{font-size:13.5px;line-height:1.6;color:var(--tx-mute);margin:14px 0 0}

/* Sector photo band across the head of a card. Bleeds to the card edges
   by cancelling its padding, and rounds only the top corners so it sits
   in the card rather than on it. Used on the three "Deep" sectors, so
   the image carries the Deep/Active distinction the page already makes
   rather than decorating all six equally. */
.card-shot{display:block;margin:-38px -34px 20px;overflow:hidden;
  border-radius:var(--r-card) var(--r-card) 0 0;background:var(--surface)}
.card-shot img{display:block;width:100%;aspect-ratio:16/9;object-fit:cover;
  transition:transform .5s cubic-bezier(.2,.7,.3,1)}
.card:hover .card-shot img{transform:scale(1.045)}
.card.compact .card-shot{margin:-22px -28px 16px}
@media (max-width:620px){ .card-shot img{aspect-ratio:2/1} }

/* ═══ ambience + glass ═══
   Glass over flat white reads as flat white — the blur has nothing to
   work on. So the page gets an ambient ground first: three barely-there
   brand-colour fields, fixed, behind everything. The translucent cards
   then visibly gather and blur that colour, which is what makes them
   read as glass rather than as grey boxes. */
body::before{content:"";position:fixed;inset:0;z-index:-2;pointer-events:none;
  background:
    radial-gradient(640px 520px at 12% 16%, color-mix(in srgb,var(--magenta) 8%,transparent), transparent 70%),
    radial-gradient(760px 600px at 88% 28%, color-mix(in srgb,var(--cyan) 9%,transparent), transparent 70%),
    radial-gradient(700px 560px at 44% 98%, color-mix(in srgb,var(--violet) 8%,transparent), transparent 70%)}

.card{background:color-mix(in srgb,#fff 55%,transparent);
  border:1px solid color-mix(in srgb,#fff 80%,transparent);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.75),0 12px 32px -20px rgba(22,17,31,.22);
  backdrop-filter:blur(16px) saturate(150%);-webkit-backdrop-filter:blur(16px) saturate(150%)}
.card:hover{box-shadow:inset 0 1px 0 rgba(255,255,255,.85),0 24px 48px -22px rgba(22,17,31,.3)}
.card-shot{margin-top:-39px}
.bleed .card{background:rgba(255,255,255,.13);border:1px solid rgba(255,255,255,.28);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.4);
  backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%)}

/* ═══ sticky stack ═══
   Full-width cards that pin below the nav as you scroll, gathering into
   a slightly fanned deck. The near-solid background is deliberate: a
   sticky card sits over the one behind it, and text ghosting through
   glass is illegible rather than atmospheric. */
.stick-stack{display:flex;flex-direction:column;gap:26px}
.stick-stack>.card{position:sticky;padding:46px 48px;
  background:color-mix(in srgb,#fff 88%,transparent);
  backdrop-filter:blur(22px) saturate(160%);-webkit-backdrop-filter:blur(22px) saturate(160%)}
.stick-stack>.card:nth-child(1){top:112px}
.stick-stack>.card:nth-child(2){top:130px}
.stick-stack>.card:nth-child(3){top:148px}
.stick-stack>.card:nth-child(4){top:166px}
.stick-stack>.card h3{font-size:clamp(24px,2.6vw,32px)}
@media (max-width:760px){.stick-stack>.card{position:static;padding:34px 30px}}

/* ═══ staggered grid ═══
   Columns start at different heights, so a row of equal boxes stops
   reading as a row of equal boxes. Margins, not transforms — the hover
   lift already owns transform. */
@media (min-width:900px){
  .cards-offset{align-items:start}
  .cards-offset>*:nth-child(2){margin-top:30px}
  .cards-offset>*:nth-child(3){margin-top:60px}
}

/* ═══ photo row ═══  Small figures with a caption set into the image. */
.photo-row{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.photo-row figure{margin:0;position:relative;border-radius:var(--r-tile);overflow:hidden;aspect-ratio:4/5}
.photo-row img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .4s ease}
.photo-row figure:hover img{transform:scale(1.05)}
.photo-row figcaption{position:absolute;left:0;right:0;bottom:0;padding:30px 14px 12px;
  font-family:var(--f-data);font-size:12.5px;color:#fff;
  background:linear-gradient(transparent,rgba(11,7,22,.74))}
@media (max-width:760px){.photo-row{grid-template-columns:repeat(2,1fr)}}

/* ═══ diagram frame ═══ */
.diagram{border-radius:var(--r-card);padding:34px;overflow-x:auto;
  background:color-mix(in srgb,#fff 55%,transparent);
  border:1px solid color-mix(in srgb,#fff 80%,transparent);
  backdrop-filter:blur(16px) saturate(150%);-webkit-backdrop-filter:blur(16px) saturate(150%)}
.diagram svg{display:block;width:100%;height:auto;min-width:700px}

/* ═══ scroll parallax in media frames ═══
   Scroll-driven, no JS, progressive: browsers without animation-timeline
   simply show the still image. */
@supports (animation-timeline: view()){
  .media .photo,.card-shot img,.photo-row img{scale:1.14;animation:media-drift linear both;animation-timeline:view()}
  @keyframes media-drift{from{translate:0 -4.5%}to{translate:0 4.5%}}
}
@media (prefers-reduced-motion: reduce){
  .media .photo,.card-shot img,.photo-row img{animation:none;scale:none;translate:none}
}
