/* tphDDB x Red Bull MOBILE — components.
   Consumes styles/tokens.css and names no raw values. Change values
   THERE, never here. */

/* ============================================================
   PROTOTYPE ONLY — hero motion, rough type, no final design.
   Token block below is copied verbatim from styles/tokens.css so
   this file stays self-contained. When this graduates to the real
   build, delete it and <link> tokens.css instead. Values change
   THERE, never here, and never inline.
   ============================================================ */

/* The DDB "B", from ddb-b.svg / ddb-logo.svg. Per-instance colour rides on
   --b-top / --b-bot: custom properties inherit into the <use> shadow tree,
   which ordinary descendant selectors do not. */
.ddbmark{display:block;height:34px;width:auto;aspect-ratio:169/283;flex:none}
/* NB: the fills live as inline styles on the paths inside <symbol>. A rule like
   `.ddbmark .b-top{fill:...}` looks equivalent but silently fails — descendant
   selectors do not match inside the <use> shadow tree, and the mark renders
   SVG-initial black. Custom properties inherit in; selectors do not. */
#ddbDefs{position:absolute;width:0;height:0;overflow:hidden}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{background:var(--paper);color:var(--ink);font-family:var(--body);
     -webkit-font-smoothing:antialiased;overflow-x:clip}

.mono{font-family:var(--mono);text-transform:uppercase}
.disp{font-family:var(--display);font-variation-settings:'wdth' 78,'wght' 800;
      text-transform:uppercase;letter-spacing:var(--hero-track);line-height:var(--hero-leading)}

/* ---------- SCROLL DRIVE ----------
   The sequence is scrubbed by the reader, not played at them. The hero pins
   while they scroll through it; --seq-scroll is how much scrolling that takes. */
#heroScroll{height:calc(100svh + var(--seq-scroll))}
#heroSticky{position:sticky;top:0;height:100vh;height:100svh;overflow:hidden}
#heroSticky .hero{height:100%}

/* ---------- SETTLED HERO (artboards 03 / 04) ---------- */
.hero{position:relative;min-height:100vh;min-height:100svh;background:var(--paper);
      display:flex;flex-direction:column;justify-content:space-between;padding:var(--pad-mobile)}
/* THE GROUND IS THE CHIP. The contact-pad grid is the page grid (CLAUDE.md),
   so the background is that pad partially energised — flat, square, no
   gradients. Colour that means connection rather than decoration. */
.hero__grid{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}
.hero__lines{position:absolute;inset:0;
  background-image:linear-gradient(to right,var(--grid-on-paper) 0 1px,transparent 1px),
                   linear-gradient(to bottom,var(--grid-on-paper) 0 1px,transparent 1px);
  background-size:25% 16.6667%}
.hero__cell{position:absolute;left:calc(var(--c)*25%);top:calc(var(--r)*16.6667%);
      width:calc(var(--cw,1)*25%);height:calc(var(--ch,1)*16.6667%)}
.hero__cell--m{display:block}
.hero__cell--d{display:none}
.hero__top,.hero__line,.hero__foot{position:relative;z-index:1}

/* THE FANNED LOCKUP. Sits in the clear band between the red top row and the
   navy bottom row, aligned to the type column rather than the full-bleed grid.
   It is covered by the stage until the wipe completes, so it never competes
   with first paint — hence the low fetch priority on the <img>. */
/* Mobile: a normal flex item, so space-between drops it into the gap between
   the headline and the foot and it CANNOT collide with the type. Only desktop,
   where there is room beside the headline, lifts it out of flow. */
.hero__logo{align-self:flex-end;height:auto;width:clamp(88px,26vw,132px);
            pointer-events:none}
.hero__top{display:flex;flex-direction:column;gap:36px}
.hero__meta .x{color:var(--signal)}
.hero__meta{display:flex;flex-direction:column;gap:6px;font-family:var(--mono);
            font-size:var(--meta-size-m);letter-spacing:var(--meta-track-m);
            text-transform:uppercase;color:var(--meta-on-paper)}
.hero__line{font-family:var(--display);font-variation-settings:'wdth' 78,'wght' 800;
            text-transform:uppercase;font-size:var(--hero-size);
            line-height:var(--hero-leading);letter-spacing:var(--hero-track)}
.hero__line span{display:block}
.hero__foot{display:flex;flex-direction:column;gap:14px}
.hero__rule{height:1px;background:var(--rule)}
.hero__cue{display:flex;align-items:flex-end;gap:12px}
.hero__cue .cuetext{font-family:var(--mono);font-size:9px;letter-spacing:.28em;
                    text-transform:uppercase;padding-bottom:1px}

/* signal glyph, paper variant */
.bars{display:flex;align-items:flex-end;gap:4px;height:20px}
.bars i{display:block;width:6px;background:var(--ink)}
.bars i:nth-child(1){height:6px}.bars i:nth-child(2){height:11px}
.bars i:nth-child(3){height:15px}.bars i:nth-child(4){height:20px}
.bars i:nth-child(4){background:var(--signal)}   /* full signal, in their red */

/* ---------- SIM ---------- */
.sim{position:relative;width:var(--sim-w);height:var(--sim-h);
     clip-path:polygon(18px 0,100% 0,100% 100%,0 100%,0 18px)}
.sim__fill{position:absolute;inset:1px;clip-path:polygon(17px 0,100% 0,100% 100%,0 100%,0 17px)}
.sim__pad{position:absolute;left:var(--pad-off-x);top:var(--pad-off-y);
          width:var(--pad-w);height:var(--pad-h);
          display:flex;align-items:center;justify-content:center}
.sim__ddb{position:relative;color:var(--ink)}
.sim__pad .ddbmark{--b-top:var(--ink);--b-bot:var(--ink)}   /* on yellow, both bowls ink */

/* settled variant: ink edge, paper fill, yellow pad */
.sim--set{background:var(--ink)}
.sim--set .sim__fill{background:var(--paper)}
.sim--set .sim__pad{background:var(--yellow);
  background-image:linear-gradient(to right,rgba(252,251,243,.6) 0 .5px,transparent .5px),
                   linear-gradient(to bottom,rgba(252,251,243,.6) 0 .5px,transparent .5px);
  background-size:12.6667px 100%,100% 11px}

/* ---------- SCROLL TARGET (rough — proves the skip) ---------- */
/* ============================================================
   SECTIONS. Two-part heads throughout: the commercial term is the
   title, the real term the subtitle. Never ship one without the other.
   ============================================================ */
.sec{position:relative;padding:var(--sec-pad-m);border-top:1px solid var(--rule)}
.sec__head{margin-bottom:clamp(28px,4vw,52px)}
.sec__num{font-family:var(--mono);font-size:var(--meta-size-m);
          letter-spacing:var(--meta-track-m);color:var(--signal);margin:0 0 12px}
.sec__title{font-family:var(--display);font-variation-settings:'wdth' 78,'wght' 800;
            text-transform:uppercase;font-size:clamp(34px,4.4vw,74px);
            line-height:.96;letter-spacing:var(--hero-track);margin:0}
.sec__sub{font-family:var(--mono);font-size:var(--meta-size-m);
          letter-spacing:var(--meta-track-m);text-transform:uppercase;
          color:var(--meta-on-paper);margin:12px 0 0}
.lede{font-family:var(--display);font-variation-settings:'wdth' 78,'wght' 800;
      text-transform:uppercase;font-size:clamp(20px,2.1vw,34px);line-height:1.06;
      letter-spacing:var(--hero-track);max-width:22ch;margin:0 0 28px}
.sec__body p{max-width:56ch;font-size:15px;font-weight:300;line-height:1.62;
             margin:0 0 18px;color:var(--ink)}
.note{max-width:56ch;font-size:14px;font-weight:300;line-height:1.6;
      color:var(--meta-on-paper);margin:28px 0 0}

/* Build notes: what is missing, stubbed or unbriefed. They exist so nothing
   invented slips through unnoticed — but they are NOT content and must never
   reach the client, so they render only at ?dev, exactly like the HUD.
   Delete them outright once the real content lands. */
html:not(.dev) .stub{display:none}
.stub{font-family:var(--mono);font-size:11px;line-height:1.7;letter-spacing:.06em;
      max-width:60ch;color:var(--signal);border-left:2px solid var(--signal);
      padding:12px 0 12px 16px;margin:28px 0 0}

/* ---- THE LIVE NETWORK (section 01) ----
   The reference was a glowing rainbow particle ring on black. That look would
   fight every other surface here, so this keeps the IDEA — a network that is
   visibly alive, radiating from a centre — in the site's own language:
   hairlines, mono, flat colour, square dots. It also earns its place under the
   motion rule, because what it depicts IS connection: the 200+ offices the
   copy beside it claims. Pulses run on stroke-dashoffset and opacity only. */
.sec__split{display:grid;gap:clamp(28px,4vw,64px);align-items:center}
.sec__col{display:flex;flex-direction:column;justify-content:center}
.sec__col .lede{margin-bottom:24px}
.sec__col .stats{margin-top:28px}
.net{position:relative}
.net svg{display:block;width:100%;height:auto;overflow:hidden}
.net-line{stroke:var(--signal);fill:none;stroke-width:1;
  /* A continuous stream of short dashes running outward — traffic on the
     network, not one dart every four seconds. dashoffset animates exactly one
     dash+gap period so the loop is seamless with no jump. */
  stroke-dasharray:7 34;stroke-linecap:round;
  /* linear, because this is constant motion — easing a continuous loop makes
     it pulse unevenly at the seam */
  animation:netflow 1.9s linear infinite;animation-delay:var(--d)}
.net-line--home{stroke-opacity:1}
.net-line--world{stroke-opacity:.44;animation-duration:2.9s}
/* run past the frame and get cut by it: the offices we are not naming */
.net-line--cut{stroke-opacity:.2;animation-duration:4.6s}
/* exactly one dash+gap period, so the loop has no visible seam */
@keyframes netflow{from{stroke-dashoffset:41}to{stroke-dashoffset:0}}
.net-dot{fill:var(--ink);animation:netblink 3.4s ease-in-out infinite;
         animation-delay:var(--d)}
@keyframes netblink{0%,100%{opacity:.4}50%{opacity:1}}
.net-label{font-family:var(--mono);font-size:9px;letter-spacing:.16em;
  fill:var(--meta-on-paper);text-transform:uppercase}
/* Riyadh is the only office in the Kingdom, so it is the only Saudi node here
   and it is marked as home. The hero keeps its wider city field: that depicts
   Red Bull MOBILE's coverage, not ours. */
.net-label--home{font-size:11px;fill:var(--ink);letter-spacing:.18em}
.net-dot--home{fill:var(--signal)}
.net-core use{--b-top:var(--yellow);--b-bot:var(--ink)}
.net-cap{font-family:var(--mono);font-size:9px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--meta-on-paper);margin:10px 0 0;
  text-align:center}
@media (min-width:900px){ .sec__split{grid-template-columns:1fr 1fr} }
@media (prefers-reduced-motion:reduce){
  .net-line{stroke-dasharray:none;stroke-opacity:.3}
  .net-dot{opacity:1}
}
html.rm .net-line{stroke-dasharray:none;stroke-opacity:.3}
html.rm .net-dot{opacity:1}

/* stat + people rows */
.stats,.people{margin:36px 0 0;display:flex;flex-direction:column}
.stats .row,.people .row{display:flex;gap:20px;padding:14px 0;
                         border-bottom:1px solid var(--rule)}
.stats dt{font-family:var(--display);font-variation-settings:'wdth' 78,'wght' 800;
          font-size:24px;min-width:96px;margin:0;line-height:1}
.stats dt.hot{color:var(--signal)}
.stats dd{margin:0;font-size:14px;font-weight:300;align-self:flex-end}
.people dt{font-weight:500;font-size:15px;min-width:190px;margin:0}
.people dd{margin:0;font-size:14px;font-weight:300}
.people dd span{display:block;font-family:var(--mono);font-size:9px;
                letter-spacing:.2em;text-transform:uppercase;
                color:var(--meta-on-paper);margin-bottom:4px}
.telco{font-family:var(--mono);font-size:var(--meta-size-m);
       letter-spacing:var(--meta-track-m);color:var(--ink);margin:0 0 8px}

/* MOTION 3 — marquees. Transform only, duplicated content, pause on hover. */
.mq-row{display:grid;gap:6px;margin-top:22px}
.mq-label{font-family:var(--mono);font-size:var(--meta-size-m);
  letter-spacing:var(--meta-track-m);text-transform:uppercase;
  color:var(--signal);margin:0}
.marquee{overflow:hidden;border-top:1px solid var(--rule);padding:18px 0;
         white-space:nowrap}
.marquee:last-of-type{border-bottom:1px solid var(--rule)}
.marquee__track{display:inline-flex;animation:mq 40s linear infinite;
                will-change:transform}
.marquee__track span{font-family:var(--display);
                     font-variation-settings:'wdth' 78,'wght' 800;
                     text-transform:uppercase;font-size:clamp(20px,2.4vw,38px);
                     padding-right:.4em}
.marquee--rev .marquee__track{animation-direction:reverse}
.marquee:hover .marquee__track{animation-play-state:paused}
@keyframes mq{to{transform:translateX(-50%)}}

/* MOTION 4 — the handover */
.handover{margin:clamp(48px,7vw,96px) 0 0}
.handover .sim--set{margin-bottom:clamp(24px,3vw,40px)}
.handover__line{font-family:var(--display);
                font-variation-settings:'wdth' 78,'wght' 800;
                text-transform:uppercase;font-size:var(--hero-size);
                line-height:.94;letter-spacing:var(--hero-track);margin:0}
/* Desktop: the SIM is handed ACROSS, not stacked above. Row, full measure, and
   the line sized off the viewport so it actually fills what the SIM leaves —
   nowrap because "WE MOVE THEM." breaking in two kills the bookend. */
@media (min-width:768px){
  .handover{display:flex;align-items:center;gap:40px}
  .handover .sim--set{margin-bottom:0;flex:none}   /* fixed 120px */
  /* Fill the measure the SIM leaves. CSS cannot fit text to a box, but this
     string is fixed and the display face is metrically stable, so the width of
     "WE MOVE THEM." is a constant 6.92x its font-size — everything else on the
     row is fixed px (100px section padding each side, 120px SIM, 40px gap), so
     the size solves exactly. Divisor is 7.1, not 6.92, to leave room for a
     scrollbar inside 100vw. Re-derive if the string or the face changes. */
  .handover__line{flex:1;white-space:nowrap;
                  font-size:min(calc((100vw - 360px) / 7.1), 200px)}
}
.colophon{margin:clamp(48px,6vw,80px) 0 0;padding-top:22px;
          border-top:1px solid var(--rule);font-family:var(--mono);
          font-size:var(--meta-size-m);letter-spacing:var(--meta-track-m);
          text-transform:uppercase;color:var(--meta-on-paper)}
.colophon p{margin:0 0 5px}

/* MOTION 2 — the signal glyph as scroll progress, fixed bottom-left */
#progress{position:fixed;left:var(--pad-x-m);bottom:20px;z-index:40;
          display:flex;align-items:flex-end;gap:10px;pointer-events:none}
#progress .bars i{background:var(--rule)}
#progress .bars i.on{background:var(--ink)}
#progress .bars i.on:nth-child(4){background:var(--signal)}
#progress .cuetext{font-family:var(--mono);font-size:9px;letter-spacing:.26em;
                   text-transform:uppercase;color:var(--meta-on-paper)}
#progress.is-full .cuetext{color:var(--ink)}

/* ============================================================
   THE STAGE — navy sequence overlay.
   Ground panels, empty bars and SEARCHING… ship in the HTML so
   beat 1 paints with no JS and no font. Everything else is built
   by script and may arrive late.
   ============================================================ */
#stage{position:absolute;inset:0;z-index:50;overflow:hidden;pointer-events:none;
       contain:layout paint;background:transparent}
#stage[hidden]{display:none}
.ground{position:absolute;left:0;right:0;background:var(--navy);will-change:transform}
#gTop{top:0;transform-origin:top center}
#gBot{bottom:0;transform-origin:bottom center}

/* hairline grid — the SIM contact-pad geometry, over the navy */
.gridline{position:absolute;inset:0;pointer-events:none;
  background-image:linear-gradient(to right,var(--grid-on-navy) 0 1px,transparent 1px),
                   linear-gradient(to bottom,var(--grid-on-navy) 0 1px,transparent 1px);
  background-size:16.6667% 25%}

#net{position:absolute;left:0;top:0;width:0;height:0;transform-origin:0 0;
     will-change:transform,opacity}
#net svg{position:absolute;left:-2000px;top:-2000px;overflow:visible}
.node{position:absolute;transform:translate(-50%,-50%);background:var(--navy);
      font-family:var(--mono);text-transform:uppercase;white-space:pre;opacity:0}
.node--near{padding:6px 10px;font-size:var(--city-size);
            letter-spacing:var(--city-track);color:var(--on-navy)}
.node--far{padding:5px 9px;font-size:var(--city-size-far);
           letter-spacing:var(--city-track-far);color:var(--on-navy-soft)}

/* the sequence SIM — navy variant, travels to the settled one */
#simSeq{position:absolute;left:0;top:0;opacity:0;will-change:transform;
        background:var(--paper);
        clip-path:polygon(18px 0,100% 0,100% 100%,0 100%,0 18px)}
#simSeq .sim__fill{background:var(--navy);
        clip-path:polygon(17px 0,100% 0,100% 100%,0 100%,0 17px)}
#simSeq .sim__pad{display:grid;grid-template-columns:repeat(6,1fr);
        grid-template-rows:repeat(4,1fr);place-items:stretch}
#simSeq .cell{   /* the JS-built pad-boot cells, not .hero__cell */border:.5px solid rgba(252,251,243,.34)}
/* the mark sits on the PAD, not on the SIM — inset:0 here centred it on the
   whole card and left it hanging 4px above the yellow */
#simSeq .sim__ddb{position:absolute;left:var(--pad-off-x);top:var(--pad-off-y);
        width:var(--pad-w);height:var(--pad-h);display:flex;align-items:center;
        justify-content:center;opacity:0;will-change:transform,opacity}
#simOutline{position:absolute;left:0;top:0;overflow:visible;pointer-events:none}

/* centred glyph + cue, navy variant (artboard 01) */
#cueWrap{position:absolute;left:0;right:0;top:62%;display:flex;flex-direction:column;
         align-items:center;gap:26px}
.bars--dark{display:flex;align-items:flex-end;gap:var(--sig-gap);height:var(--sig-h)}
.bars--dark i{display:block;position:relative;width:var(--sig-bar-w);
              border:1px solid rgba(255,255,255,.30);background:transparent}
.bars--dark i:nth-child(1){height:calc(var(--sig-h)*.294)}
.bars--dark i:nth-child(2){height:calc(var(--sig-h)*.529)}
.bars--dark i:nth-child(3){height:calc(var(--sig-h)*.765)}
.bars--dark i:nth-child(4){height:var(--sig-h)}

/* THE HUNT. While nothing has locked yet the bars scan, the way a handset
   sweeps for a cell. Hard steps, not a fade — a search is a series of tries,
   not a breath. Opacity on an overlay only, so it stays on the compositor.
   Runs by DEFAULT, with no class and no JS: the searching beat ships in the
   HTML so it is alive on the first frame even before hero.js parses. Each bar
   stops the moment it acquires (.on), so the hunt resolves into the stutter
   on its own. */
.bars--dark i::after{content:'';position:absolute;inset:0;
                     background:var(--on-navy);opacity:0}
.bars--dark i::after{animation:barhunt 1.5s steps(1,end) infinite}
.bars--dark i:nth-child(2)::after{animation-delay:.11s}
.bars--dark i:nth-child(3)::after{animation-delay:.20s}
.bars--dark i:nth-child(4)::after{animation-delay:.33s}
.bars--dark i.on::after{animation:none;opacity:0}
@keyframes barhunt{0%{opacity:.9}9%{opacity:0}100%{opacity:0}}
.bars--dark i.on{background:var(--on-navy);border-color:var(--on-navy)}
.bars--dark i.on:nth-child(4){background:var(--signal);border-color:var(--signal)}
#hint{font-family:var(--mono);font-size:var(--hint-size);letter-spacing:.28em;
      text-transform:uppercase;color:var(--on-navy-faint);margin-top:18px;
      transition:opacity .32s ease-out}
#cue{font-family:var(--mono);font-size:var(--searching-size);
     letter-spacing:var(--searching-track);text-transform:uppercase;
     color:var(--on-navy);white-space:pre;animation:searchpulse 1.7s linear infinite}
/* squarer and quicker than the artboard's sine breath — it reads as a device
   retrying, not a thing gently glowing */
@keyframes searchpulse{0%,42%{opacity:.92}50%,92%{opacity:.28}100%{opacity:.92}}
@media (max-width:767px){ #cueWrap{top:auto;bottom:34px;gap:18px} }

/* ---------- REDUCED MOTION: settled state, immediately, no sequence ---------- */
@media (prefers-reduced-motion:reduce){
  #stage{display:none}
  #heroScroll{height:auto}
  #heroSticky{position:static;height:auto;overflow:visible}
  *,*::before,*::after{animation:none!important;transition:none!important}
}
html.rm #stage{display:none}
html.rm #heroScroll{height:auto}
html.rm #heroSticky{position:static;height:auto;overflow:visible}
html.rm *,html.rm *::before,html.rm *::after{animation:none!important;transition:none!important}

/* ---------- HUD — prototype scaffolding, deleted before build ---------- */
#hud{position:fixed;right:12px;bottom:12px;z-index:100;font-family:var(--mono);
     font-size:9px;letter-spacing:.14em;text-transform:uppercase;
     background:rgba(252,251,243,.94);border:1px solid var(--rule);
     padding:9px 10px;display:none;flex-direction:column;gap:7px;color:var(--ink)}
/* The HUD is a workbench tool, not part of the site. It renders ONLY at
   ?dev — a forwarded link can never show it, and nobody can stumble into it.
   Delete the #hud markup outright before this ships; the wiring below is
   guarded so removing it cannot break the page. */
html.dev #hud{display:flex}
#hud .r{display:flex;gap:5px;align-items:center}
#hud button{font:inherit;letter-spacing:.14em;text-transform:uppercase;
            background:transparent;border:1px solid var(--rule);color:var(--ink);
            padding:4px 7px;cursor:pointer}
#hud button:hover{border-color:var(--ink)}
#hud button.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}
#hud .t{color:var(--muted);min-width:150px}
#hud .t b{color:var(--ink);font-weight:500}

@media (min-width:768px){
  .hero__lines{background-size:16.6667% 25%}
  .hero__cell{left:calc(var(--c)*16.6667%);top:calc(var(--r)*25%);
        width:calc(var(--cw,1)*16.6667%);height:calc(var(--ch,1)*25%)}
  .hero__cell--m{display:none}
  .hero__cell--d{display:block}
  .sec{padding:var(--sec-pad-d)}
  .band{grid-template-columns:auto 1.05fr 1.75fr}
  .band__q li{max-width:46ch}
  .band__body{grid-column:auto}
  .band__q{margin-top:0;grid-template-columns:1fr 1fr}
  #progress{left:var(--pad-x-d);bottom:26px}
  .hero{padding:var(--pad-desktop)}
  /* desktop: the clear band between the red top row and the navy bottom row */
  .hero__logo{position:absolute;z-index:1;right:var(--pad-x-d);
              top:50%;transform:translateY(-50%);width:var(--logo-w)}
  .hero__top{gap:44px}
  .hero__meta{font-size:var(--meta-size);letter-spacing:var(--meta-track);gap:7px}
  .hero__line span{display:inline;white-space:nowrap}
  .hero__line span+span{display:block}
  .hero__foot{gap:20px}
  .hero__cue{gap:16px}
  .hero__cue .cuetext{font-size:11px;letter-spacing:var(--cue-track)}
  .bars{gap:var(--bar-gap);height:26px}
  .bars i{width:var(--bar-w)}
  .bars i:nth-child(1){height:8px}.bars i:nth-child(2){height:14px}
  .bars i:nth-child(3){height:20px}.bars i:nth-child(4){height:26px}
  .after{padding:96px 100px 140px}
  .after dt{font-size:34px;min-width:140px}
}

/* ---- emotion leaving the head ----
   The head is the supplied render, background keyed out by flood-filling from
   the edges (a plain luminance key would have punched out the specular
   highlights on the head itself). It sits straight on the paper, no plate.
   The signal leaving it is drawn: six harmonics in the fan lockup's own petal
   colours, amplifying as they travel. */
.simkey{margin:0;display:block}
.simkey__stage{display:grid;grid-template-columns:auto minmax(0,1fr);
               align-items:center;gap:0}
.emotion-head{height:clamp(230px,26vw,360px);width:auto;display:block}
.emotion-out{min-width:0}
.emotionwave{display:block;width:100%;height:clamp(180px,20vw,280px);
             overflow:visible}
.wave{fill:none;stroke-width:1.1;vector-effect:non-scaling-stroke}
.wave--ghost{stroke:var(--ink);stroke-opacity:.08}
/* TWO motions per harmonic, which is what makes it read as casting rather
   than a diagram with dots running along it:
     waveflow — dashes travelling outward (the same device as the network)
     wavecast — the line itself stretching and swelling, anchored AT THE HEAD
   transform-origin is the left edge, so every wave grows out of him rather
   than scaling about its own middle. Transform + dashoffset only. */
.wave--live{stroke-linecap:round;stroke-dasharray:7 40;
            transform-box:fill-box;transform-origin:0% 50%;
            animation:waveflow 2.1s linear infinite,
                      wavecast 3.4s ease-in-out infinite}
.wave--f1{stroke:var(--fan-1);animation-duration:2.1s,3.4s;animation-delay:0s,0s}
.wave--f2{stroke:var(--fan-2);animation-duration:2.6s,4.3s;animation-delay:-.3s,-.3s}
.wave--f3{stroke:var(--fan-3);animation-duration:1.9s,2.9s;animation-delay:-.7s,-.7s}
.wave--f4{stroke:var(--fan-4);animation-duration:2.9s,5.1s;animation-delay:-1.1s,-1.1s}
.wave--f5{stroke:var(--fan-5);animation-duration:2.3s,3.7s;animation-delay:-1.5s,-1.5s}
.wave--f6{stroke:var(--fan-6);animation-duration:1.6s,4.7s;animation-delay:-1.9s,-1.9s}
@keyframes waveflow{from{stroke-dashoffset:47}to{stroke-dashoffset:0}}
@keyframes wavecast{
  0%,100%{transform:scaleY(.86) scaleX(.985)}
  50%    {transform:scaleY(1.20) scaleX(1.015)}
}
.simkey__cap{font-family:var(--mono);font-size:9px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--meta-on-paper);margin-top:12px}
@media (max-width:700px){
  .simkey__stage{grid-template-columns:1fr;justify-items:center}
  .emotionwave{height:120px}
}
@media (prefers-reduced-motion:reduce){
  .wave--live{animation:none;stroke-dasharray:none;stroke-opacity:.6;transform:none}
}
html.rm .wave--live{animation:none;stroke-dasharray:none;stroke-opacity:.6}

/* ============================================================
   03 — THE POWER TO MOVE ASSEMBLING INTO A SIM
   Seven horizontal bands, each position:sticky, so the next slides over the
   last and the card builds top-down as you read. Band 1 carries the SIM's cut
   corner; the middle bands carry the contact-pad grid; band 7 closes it.
   Square corners and hairlines only — the Dallah stack this borrows its
   BEHAVIOUR from used 26px radii and drop shadows, which this brief forbids.
   The bands read at comfortable height rather than true 3:2, which at seven
   bands would leave ~114px each and no room for the questions.
   ============================================================ */
.ptm-head{margin-top:clamp(40px,5vw,72px)}
.ptm{margin:clamp(22px,2.6vw,36px) auto 0;padding-bottom:60px;
     /* the assembled card is a SIM, so it is capped at SIM proportions
        rather than running the full page width — at 2000px the questions
        were sitting a metre apart and the shape read as a table */
     max-width:1100px}
.band{position:sticky;top:var(--band-top);   /* JS sets a cumulative top so the card ASSEMBLES */
      background:var(--paper);border:1px solid var(--ink);
      border-bottom-width:0;padding:clamp(12px,1.2vw,16px) clamp(18px,2.4vw,32px);
      display:grid;grid-template-columns:auto 1fr;gap:6px clamp(16px,2.4vw,34px);
      align-items:start}
.ptm.assembles .band--first{clip-path:polygon(var(--sim-notch) 0, 100% 0,
                            100% 100%, 0 100%, 0 var(--sim-notch))}
.band--last{border-bottom-width:1px}
/* overlap mode: each band is a complete card, not a slice of one */
.ptm:not(.assembles) .band{border-bottom-width:1px;margin-bottom:18px}
/* the contact pad, showing through the middle of the card as it assembles */
.band:not(.band--first):not(.band--last)::before{
  content:'';position:absolute;left:50%;top:0;bottom:0;width:min(46%,340px);
  transform:translateX(-50%);pointer-events:none;
  background-image:linear-gradient(to right,var(--grid-on-paper) 0 1px,transparent 1px),
                   linear-gradient(to bottom,var(--grid-on-paper) 0 1px,transparent 1px);
  background-size:16.6667% 50%}
.band__num{font-family:var(--mono);font-size:var(--meta-size-m);
           letter-spacing:var(--meta-track-m);color:var(--signal);
           padding-top:5px}
.band__name h3{font-family:var(--display);
               font-variation-settings:'wdth' 78,'wght' 800;
               text-transform:uppercase;font-size:clamp(19px,2vw,30px);
               line-height:1;letter-spacing:var(--hero-track);margin:0}
.band__action{font-size:12.5px;font-weight:300;line-height:1.4;
              margin:5px 0 0;color:var(--ink)}
.band__body{grid-column:2}
.band__q{margin:8px 0 0;padding:0;list-style:none;display:grid;gap:3px 20px}
.band__q li{position:relative;padding-left:14px;font-size:12px;font-weight:300;
            line-height:1.34;color:var(--meta-on-paper)}
.band__q li::before{content:'';position:absolute;left:0;top:.62em;width:9px;
                    height:1px;background:var(--signal)}

@media (prefers-reduced-motion:reduce){
  .band{position:static}
}
html.rm .band{position:static}

/* ============================================================
   SECTION DIVIDERS — full bleed, the word set as large as it will go.
   The same page-break device as the SAB site (modelled on ddb.com), but
   rendered in THIS site's language: flat colour fields, no gradient wash and
   no grain, because square-and-flat is what the rest of the page is.
   This is where the DDB palette lives — agency moments, never UI.
   aria-hidden: the section's real <h2> follows immediately and a screen
   reader should not hear the name twice.
   ============================================================ */
.divider{position:relative;display:grid;place-items:center;overflow:hidden;
         min-height:min(58vh,560px);padding:var(--sec-pad-m)}
.divider__word{font-family:var(--display);
               font-variation-settings:'wdth' 78,'wght' 800;
               text-transform:uppercase;white-space:nowrap;line-height:.9;
               letter-spacing:-.03em;color:var(--ddb-black);
               /* One line, edge to edge: whichever is smaller — the display
                  ceiling, or the size at which the whole string still fits.
                  .62em is the average advance. Measured at .52 it clipped short
                  words ("WORK") on mobile, and the fallback face before Archivo
                  loads is wider still, so this carries deliberate headroom. */
               font-size:max(34px, min(calc(88vw / (var(--chars,6) * .62)), 46vh))}
.divider--yellow{background:var(--yellow)}
.divider--green {background:var(--ddb-green)}
.divider--blue  {background:var(--ddb-blue)}
.divider--gray  {background:var(--ddb-gray)}
.divider--black {background:var(--ddb-black)}
.divider--black .divider__word{color:var(--paper)}
/* the contact-pad grid rides over every divider, as it does everywhere else */
.divider::before{content:'';position:absolute;inset:0;pointer-events:none;
  background-image:linear-gradient(to right,rgba(14,14,14,.06) 0 1px,transparent 1px),
                   linear-gradient(to bottom,rgba(14,14,14,.06) 0 1px,transparent 1px);
  background-size:25% 50%}
@media (min-width:768px){
  .divider{padding:var(--sec-pad-d)}
  .divider::before{background-size:16.6667% 50%}
}

/* ---- CREATIVE LIBRARY — clean tiles, case study in an overlay ----
   Plain rectangles. The B device is NOT used here: the SAB build tried it and
   rejected it, and the note is worth keeping — the DDB presence comes from
   colour, not from shape. Colour is cycled per tile, never role-coded. */
.work{display:grid;gap:clamp(22px,2.6vw,36px);margin-top:clamp(28px,4vw,52px);
      grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
/* Each tile IS a SIM. Built the way the hero SIM is: the DDB colour is the
   card edge, the still sits inset inside it, and both carry the cut corner —
   expressed as a percentage so the silhouette holds at any tile width.
   3/2 is the real SIM ratio (120x80); the tiles were already 16/10. */
.case-media{display:block;position:relative;width:100%;aspect-ratio:3/2;
  background:var(--ddb,var(--ddb-gray));margin-bottom:14px;
  clip-path:polygon(var(--sim-notch-x) 0, 100% 0, 100% 100%, 0 100%, 0 var(--sim-notch-y))}
.case-media img{position:absolute;top:var(--sim-edge-w);left:var(--sim-edge-w);
  /* explicit size: width/height:auto on a replaced element resolves to the
     image's INTRINSIC size, not the inset box, so the still blew out of the
     tile at 1000px wide. */
  width:calc(100% - var(--sim-edge-w) * 2);
  height:calc(100% - var(--sim-edge-w) * 2);
  object-fit:cover;
  clip-path:polygon(var(--sim-notch-x) 0, 100% 0, 100% 100%, 0 100%, 0 var(--sim-notch-y))}
.case-client{display:flex;align-items:center;gap:8px;font-family:var(--mono);
  font-size:9px;letter-spacing:.2em;text-transform:uppercase;color:var(--ink);
  margin:0 0 7px}
.case-client::before{content:'';flex:none;width:12px;height:12px;
  background:var(--ddb,var(--signal))}
.case-title{font-family:var(--display);font-variation-settings:'wdth' 78,'wght' 800;
  text-transform:uppercase;font-size:clamp(19px,1.7vw,25px);line-height:1;margin:0}
.case-line{font-size:13.5px;font-weight:300;line-height:1.55;color:var(--meta-on-paper);
  margin:8px 0 0;max-width:44ch}
.case-cta{display:inline-block;margin-top:12px;font-family:var(--mono);font-size:9px;
  letter-spacing:.2em;text-transform:uppercase;color:var(--ink);text-decoration:none;
  border-bottom:1px solid var(--rule);padding-bottom:3px}
.case-cta::after{content:' \2192'}
.case-cta:hover{color:var(--signal);border-bottom-color:var(--signal)}

.case-ov{position:fixed;inset:0;z-index:210;background:var(--paper)}
.case-ov[hidden]{display:none}
.case-ov__scroll{position:absolute;inset:0;overflow:auto}
.case-ov__close{position:fixed;top:16px;right:20px;z-index:2;font-size:26px;
  line-height:1;background:none;border:0;color:var(--paper);cursor:pointer;
  mix-blend-mode:difference}
.case-ov__hero{min-height:min(62vh,560px);background-size:cover;
  background-position:center;background-color:var(--ink);display:grid;
  place-content:center;text-align:center;padding:40px 24px}
.case-ov__client{font-family:var(--mono);font-size:10px;letter-spacing:.26em;
  text-transform:uppercase;color:var(--yellow);margin:0 0 12px}
.case-ov__title{font-family:var(--display);font-variation-settings:'wdth' 78,'wght' 800;
  text-transform:uppercase;font-size:clamp(34px,5vw,84px);line-height:.96;
  color:var(--paper);margin:0}
.case-ov__body{max-width:900px;margin:0 auto;padding:clamp(36px,5vw,72px) 24px 96px}
.case-ov__film{aspect-ratio:16/9;background:var(--ink);margin-bottom:36px}
.case-ov__film iframe{width:100%;height:100%;border:0;display:block}
.case-ov__label{font-family:var(--mono);font-size:9px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--signal);margin:26px 0 6px}
.case-ov__copy{font-size:15px;font-weight:300;line-height:1.65;margin:0;max-width:62ch}
.case-ov__stills{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
  gap:12px;margin-top:32px}
.case-ov__stills img{width:100%;height:auto;display:block;border:1px solid var(--rule)}
/* prev / next — the 1px gap IS the rule, showing the ground through */
.case-nav{margin-top:clamp(44px,5vw,76px);display:grid;grid-template-columns:1fr 1fr;
  gap:1px;background:var(--rule);border-block:1px solid var(--rule)}
.case-nav-btn{display:grid;gap:6px;align-content:center;font:inherit;color:inherit;
  padding:clamp(22px,2.6vw,34px) clamp(16px,2vw,26px);background:var(--paper);
  text-align:left;border:0;cursor:pointer;transition:background 180ms ease-out}
.case-nav-btn:hover{background:rgba(14,14,14,.03)}
.case-nav-btn:active{transform:scale(.99)}
.case-nav-btn--next{text-align:right}
.case-nav-dir{font-family:var(--mono);font-size:9px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--signal)}
.case-nav-title{font-family:var(--display);
  font-variation-settings:'wdth' 78,'wght' 800;text-transform:uppercase;
  font-size:clamp(17px,2vw,26px);line-height:1.1;letter-spacing:var(--hero-track)}

/* ---- CONTACTS — departments collapse, then person cards ---- */
.pdept{border-top:5px solid var(--ddb,var(--rule))}
.pdept:last-of-type{border-bottom:1px solid var(--rule)}
.pdept-head{display:flex;align-items:baseline;gap:clamp(12px,1.6vw,22px);
  padding-block:clamp(16px,2vw,26px);cursor:pointer;user-select:none;
  position:relative;z-index:2}
.pdept-num{font-family:var(--mono);font-size:11px;font-weight:500;line-height:1;
  color:var(--ddb-black);background:var(--ddb,var(--ddb-gray));padding:7px 9px;
  align-self:center}
.pdept-name{font-family:var(--display);font-variation-settings:'wdth' 78,'wght' 800;
  text-transform:uppercase;font-size:clamp(21px,2.6vw,34px);line-height:1;margin:0}
.pdept-count{font-family:var(--mono);font-size:9px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--meta-on-paper)}
.pdept-toggle{margin-left:auto;font-family:var(--mono);font-size:9px;
  letter-spacing:.2em;text-transform:uppercase;background:var(--ddb,var(--rule));
  color:var(--ddb-black);padding:9px 14px;align-self:center}
/* 0fr->1fr opens without measuring. The row SNAPS and only opacity fades:
   animating grid-template-rows re-lays out every card each frame. */
.pdept-body{display:grid;grid-template-rows:minmax(0,0fr);opacity:0;overflow:hidden;
  transition:opacity 180ms ease-out}
.pdept-body>*{overflow:hidden;min-height:0}
.pdept:not(.is-open) .pdept-body{pointer-events:none}
.pdept.is-open .pdept-body{grid-template-rows:minmax(0,1fr);opacity:1}
.pcard-grid{display:grid;gap:clamp(18px,2vw,28px);
  grid-template-columns:repeat(auto-fill,minmax(200px,1fr));
  padding-bottom:clamp(24px,3vw,40px)}
/* contain, not cover: the B composition is baked into the artwork (608x1100)
   and cropping it to a square cuts the device in half */
.pcard-photo{position:relative;aspect-ratio:4/5;background:var(--ddb-gray);
  overflow:hidden}
.pcard-photo img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;object-position:center bottom;padding:14px 10px 0}
.pcard-name{font-weight:500;font-size:17px;margin:14px 0 0}
.pcard-role{display:block;margin-top:4px;font-family:var(--mono);font-size:9px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--signal)}
.pcard-telco{display:block;margin-top:4px;font-family:var(--mono);font-size:9px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--ink)}
.pcard-rule{display:block;width:36px;height:2px;background:var(--rule);margin:13px 0}
.pcard-bio{font-size:13.5px;font-weight:300;line-height:1.55;color:var(--meta-on-paper);
  margin:0;display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;
  overflow:hidden}
.pcard-more{margin-top:12px;position:relative;font-family:var(--mono);font-size:9px;
  letter-spacing:.18em;text-transform:uppercase;color:var(--ink);background:none;
  border:0;border-bottom:1px solid var(--rule);padding:0 0 3px;cursor:pointer;
  touch-action:manipulation}
/* 44px tap target grown underneath, without changing how the button looks */
.pcard-more::after{content:'';position:absolute;left:0;right:0;top:50%;
  transform:translateY(-50%);height:44px;min-width:44px}
.pcard-more:hover{color:var(--signal);border-bottom-color:var(--signal)}

/* ---- KNOWLEDGE TRANSFER ---- */
.kt-partner{display:flex;align-items:center;gap:clamp(20px,2.6vw,40px);
  margin-top:clamp(30px,4vw,52px);padding:clamp(20px,2.4vw,32px);
  border:1px solid var(--rule);flex-wrap:wrap}
.kt-logo{width:clamp(160px,18vw,240px);height:auto;display:block;flex:none}
.kt-partner__title{font-family:var(--display);
  font-variation-settings:'wdth' 78,'wght' 800;text-transform:uppercase;
  font-size:clamp(16px,1.6vw,22px);line-height:1.06;margin:0}
.kt-partner__sub{font-family:var(--mono);font-size:9px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--meta-on-paper);margin:8px 0 0}
.kt-grid{display:grid;gap:clamp(16px,2vw,24px);margin-top:clamp(20px,2.4vw,32px)}
.kt-card{border-top:5px solid var(--ddb,var(--rule));padding-top:16px}
.kt-card:nth-child(1){--ddb:var(--yellow)}
.kt-card:nth-child(2){--ddb:var(--ddb-green)}
.kt-card:nth-child(3){--ddb:var(--ddb-blue)}
.kt-num{font-family:var(--mono);font-size:9px;letter-spacing:.2em;
  color:var(--meta-on-paper)}
.kt-card h3{font-family:var(--display);
  font-variation-settings:'wdth' 78,'wght' 800;text-transform:uppercase;
  font-size:clamp(17px,1.6vw,22px);line-height:1.04;margin:8px 0 8px}
.kt-card p{font-size:13.5px;font-weight:300;line-height:1.55;margin:0;
  color:var(--meta-on-paper)}
@media (min-width:768px){ .kt-grid{grid-template-columns:repeat(3,1fr)} }

/* the quarterly exchange. Sirar renders this as a purple gradient card with a
   glow; here it is a flat bordered panel, because that is this site's language. */
.qsi{margin-top:clamp(20px,2.4vw,32px);border:1px solid var(--ink);
     display:grid;gap:clamp(24px,3vw,44px);padding:clamp(24px,3vw,44px)}
.qsi__eyebrow{font-family:var(--mono);font-size:9px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--signal);margin:0 0 12px}
.qsi__title{font-family:var(--display);
  font-variation-settings:'wdth' 78,'wght' 800;text-transform:uppercase;
  font-size:clamp(21px,2.2vw,32px);line-height:1.02;
  letter-spacing:var(--hero-track);margin:0 0 16px}
.qsi__body{font-size:14px;font-weight:300;line-height:1.62;margin:0 0 16px;
  color:var(--meta-on-paper);max-width:58ch}
.qsi__goal{font-size:14px;font-weight:500;line-height:1.6;margin:0;max-width:58ch}
.qsi__label{font-family:var(--mono);font-size:9px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--meta-on-paper);margin:0 0 14px;
  padding-bottom:10px;border-bottom:1px solid var(--rule)}
.qsi__list{margin:0;padding:0;list-style:none;display:grid;gap:11px}
.qsi__list li{position:relative;padding-left:22px;font-size:13.5px;
  font-weight:300;line-height:1.5}
.qsi__list li::before{content:'\2713';position:absolute;left:0;top:0;
  color:var(--signal);font-size:12px}
@media (min-width:900px){ .qsi{grid-template-columns:1.25fr 1fr} }

/* ---- THE BOARD ---- */
.tr-head{position:relative;display:flex;align-items:flex-start;
         justify-content:space-between;gap:24px;
         /* the margin lives HERE, not on the heading: zeroing it on .sub-head
            to align the Trello mark left the heading butted against the boxes
            above it with no gap at all */
         margin-top:clamp(44px,5vw,76px)}
.tr-head .sub-head{margin-top:0}
.tr-head .sub-head b{font-weight:inherit;color:var(--signal)}
/* Trello's own blue on Trello's own mark: a product credit, not a second
   accent — flat, no gradient, no shadow. */
.tr-mark{flex:none;width:72px;height:72px;display:grid;place-items:center;
         background:#0052CC}
.sub-head{font-family:var(--display);font-variation-settings:'wdth' 78,'wght' 800;
  text-transform:uppercase;font-size:clamp(20px,2.1vw,32px);line-height:1.02;
  letter-spacing:var(--hero-track);margin:clamp(44px,5vw,76px) 0 12px}
.sub-lede{font-size:14.5px;font-weight:300;line-height:1.6;max-width:56ch;margin:0}
.tr-chips{margin-top:clamp(20px,2.4vw,32px);display:flex;flex-wrap:wrap;gap:10px}
.tr-chip{display:inline-flex;align-items:center;gap:9px;padding:9px 14px;
  border:1px solid var(--rule);background:var(--paper);font-size:13px}
.tr-chip::before{content:'';flex:0 0 auto;width:6px;height:6px;
  background:var(--signal)}
.tr-board{margin-top:clamp(20px,2.4vw,32px);display:grid;gap:14px;
  align-items:start}
.tr-col{background:rgba(14,14,14,.03);border:1px solid var(--rule);padding:14px}
.tr-col-head{display:flex;align-items:baseline;gap:10px;margin-bottom:14px;
  font-family:var(--mono);font-size:9px;letter-spacing:.2em;text-transform:uppercase}
.tr-col-count{color:var(--meta-on-paper)}
.tr-cards{display:grid;gap:10px}
.tr-card{background:var(--paper);border:1px solid var(--rule);padding:13px}
.tr-labels{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}
.tr-label{font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;
  text-transform:uppercase;padding:4px 8px;background:var(--ddb,var(--ddb-gray));
  color:var(--ddb-black)}
.tr-card-title{font-size:14px;font-weight:500;line-height:1.34;margin:0}
.tr-meta{display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-top:12px}
.tr-due{font-family:var(--mono);font-size:9px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--meta-on-paper)}
.tr-due--done{color:var(--signal)}
.tr-who{width:24px;height:24px;display:grid;place-items:center;
  background:var(--ink);color:var(--paper);font-family:var(--mono);font-size:9px}
@media (min-width:768px){ .tr-board{grid-template-columns:repeat(3,minmax(0,1fr));gap:18px} }

.studio__reel{aspect-ratio:16/9;background:var(--ink)}
.studio__reel iframe{width:100%;height:100%;border:0;display:block}
.studio{display:grid;gap:clamp(20px,2.6vw,40px);padding-bottom:clamp(24px,3vw,40px);
         grid-template-columns:repeat(auto-fit,minmax(300px,1fr));align-items:start}
/* studio.logo is NOT rendered. The asset (ddb-studio.webp, 600x805) is a
   poster composition, not a horizontal lockup: full-width it swallowed the
   viewport, and at SAB's 30px it collapsed to a ~24px smudge. The department
   header already reads "DDB Studio" and the reel's poster frame carries the
   mark, so the slot is redundant. Restore only with a proper lockup asset. */
.studio__copy p{font-size:14px;font-weight:300;line-height:1.65;margin:0 0 14px;
                max-width:60ch}

/* Veyron. Unlike ddb-studio.webp this asset IS a horizontal lockup (378x160,
   already transparent), so the logo slot is worth having — it sits on paper,
   where the magenta and the grey both hold. Capped by height, not width, so it
   never inflates to the column. */
.mpartner{display:grid;gap:clamp(20px,2.6vw,40px);padding-bottom:clamp(24px,3vw,40px);
          grid-template-columns:repeat(auto-fit,minmax(280px,1fr));align-items:start}
.mpartner__mark{display:flex;align-items:center;justify-content:flex-start}
.mpartner__mark img{height:clamp(68px,7vw,104px);width:auto;display:block}
.mpartner__copy p{font-size:14px;font-weight:300;line-height:1.65;margin:0 0 14px;
                  max-width:60ch}


.bio-ov{position:fixed;inset:0;z-index:200;background:rgba(14,14,14,.72);
        display:grid;place-items:center;padding:24px}
.bio-ov[hidden]{display:none}
.bio-ov__panel{position:relative;background:var(--paper);border:1px solid var(--ink);
  max-width:60ch;width:100%;max-height:80vh;overflow:auto;padding:clamp(26px,3vw,44px)}
.bio-ov__close{position:absolute;top:14px;right:16px;font-family:var(--mono);
  font-size:9px;letter-spacing:.2em;text-transform:uppercase;background:none;
  border:0;color:var(--meta-on-paper);cursor:pointer}
.bio-ov__close:hover{color:var(--signal)}
.bio-ov__name{font-family:var(--display);font-variation-settings:'wdth' 78,'wght' 800;
  text-transform:uppercase;font-size:clamp(22px,2.4vw,34px);line-height:1;margin:0}
.bio-ov__role{font-family:var(--mono);font-size:9px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--signal);margin:8px 0 20px}
.bio-ov__text{font-size:14px;font-weight:300;line-height:1.65}

/* ---- SOW / SLA placeholder boxes, ready for the supplied content ---- */
.slots{display:grid;gap:14px;margin-top:clamp(28px,4vw,48px)}
.slot{width:100%;text-align:left;font:inherit;color:inherit;cursor:pointer;
      background:var(--paper);border:1px solid var(--rule);
      padding:clamp(18px,2.2vw,30px);min-height:132px;
      display:flex;flex-direction:column;justify-content:space-between;gap:18px}
.slot:hover{border-color:var(--ink)}
.slot__h{display:block;font-family:var(--display);
         font-variation-settings:'wdth' 78,'wght' 800;text-transform:uppercase;
         font-size:19px;line-height:1;margin-bottom:8px}
.slot__p{display:block;font-size:13px;font-weight:300;line-height:1.5;
         color:var(--meta-on-paper)}
.slot__await{display:block;font-family:var(--mono);font-size:9px;letter-spacing:.2em;
             text-transform:uppercase;color:var(--signal)}
.slot__await::after{content:' \2197'}
/* THREE across, not two. With three items in a two-column grid the third was
   orphaned on its own row, which is what made it read as misplaced. */
@media (min-width:768px){ .slots{grid-template-columns:repeat(3,1fr);gap:18px} }

/* ============================================================
   NAV. Hidden through the hero: the sequence is a cold open and a bar sitting
   over it would break that, so it only arrives once the reader is past it.
   NO backdrop blur, unlike the SAB build — the brief rules out glassmorphism,
   and SAB's own CSS notes the blur is recomputed every scroll frame and taxes
   phones. A solid ground and a hairline costs nothing.
   ============================================================ */
.nav{position:fixed;top:0;left:0;right:0;z-index:60;
     display:flex;align-items:center;justify-content:space-between;
     gap:clamp(16px,2vw,32px);padding:12px var(--pad-x-m);
     background:var(--paper);border-bottom:1px solid transparent;
     opacity:0;pointer-events:none;transform:translateY(-8px);
     transition:opacity 240ms var(--ease),transform 240ms var(--ease),
                border-color 240ms var(--ease)}
.nav.is-in{opacity:1;pointer-events:auto;transform:none;
           border-bottom-color:var(--rule)}
.nav__brand{display:flex;align-items:center;gap:10px;text-decoration:none;
            color:var(--ink)}
.nav__brand .ddbmark{height:22px;--b-top:var(--yellow);--b-bot:var(--ink)}
.nav__us{font-family:var(--mono);font-size:9px;letter-spacing:.22em;
         text-transform:uppercase}
/* the same × the hero meta line uses — their colour, since it joins us to them */
.nav__x{font-size:12px;line-height:1;color:var(--signal)}
/* the official SIDE-BY-SIDE lockup: one line at 8.6:1, so it reads at a
   smaller height than the stacked version ever could */
.nav__client{height:19px;width:auto;display:block}
@media (max-width:520px){
  /* the lockup is the first thing to crowd on a small phone; our wordmark goes
     before either logo does, and the mark still identifies us */
  .nav__us{display:none}
  .nav__client{height:16px}
}
.nav__links{display:flex;align-items:center;gap:2px}
.nav__links a{font-family:var(--mono);font-size:9px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--meta-on-paper);text-decoration:none;
  padding:9px 11px;transition:color 160ms var(--ease),transform 160ms var(--ease)}
@media (hover:hover) and (pointer:fine){ .nav__links a:hover{color:var(--ink)} }
.nav__links a:active{transform:scale(.97)}
/* 44px minimum tap target. The bars stay 22px wide and the button looks the
   same; the target is grown underneath. It was rendering at 30. */
.nav__toggle{display:none;background:none;border:0;cursor:pointer;
             min-width:44px;min-height:44px;place-items:center;
             touch-action:manipulation}
.nav__toggle span{display:block;width:22px;height:1px;background:var(--ink);
                  transition:transform 200ms var(--ease)}
.nav__toggle span+span{margin-top:6px}
.nav__toggle.is-open span:first-child{transform:translateY(3.5px) rotate(45deg)}
.nav__toggle.is-open span+span{transform:translateY(-3.5px) rotate(-45deg)}

@media (max-width:820px){
  .nav__toggle{display:grid}
  .nav__links{position:absolute;top:100%;left:0;right:0;flex-direction:column;
    align-items:flex-start;gap:0;background:var(--paper);
    border-bottom:1px solid var(--rule);padding:6px var(--pad-x-m) 14px;
    opacity:0;pointer-events:none;transform:translateY(-6px);
    transition:opacity 180ms var(--ease),transform 180ms var(--ease)}
  .nav__links.is-open{opacity:1;pointer-events:auto;transform:none}
  .nav__links a{padding:12px 0;width:100%}
}
@media (min-width:768px){ .nav{padding:14px var(--pad-x-d)} }

/* the fixed bar must not sit over a section the reader just jumped to */
.sec,.divider{scroll-margin-top:76px}

@media (prefers-reduced-motion:reduce){ .nav{transition:opacity 240ms linear} }
