/* Data Sovereignty infographic v4. Generated by infographic/build-v4/build_php_template.py from the built v4 standalone. Do not hand-edit: change build-v4/figma_body.py or build-v4/make_figma_version.py, re-run make_figma_version.py then build_php_template.py, and re-upload. */
@font-face{font-family:"Pure Sans DSI";font-style:normal;font-weight:400;font-display:swap;src:url(../assets/fonts/pure-sans/pure-sans-400-normal.woff2) format("woff2")}
@font-face{font-family:"Pure Sans DSI";font-style:normal;font-weight:500;font-display:swap;src:url(../assets/fonts/pure-sans/pure-sans-500-normal.woff2) format("woff2")}
@font-face{font-family:"Pure Sans DSI";font-style:normal;font-weight:600;font-display:swap;src:url(../assets/fonts/pure-sans/pure-sans-600-normal.woff2) format("woff2")}
@font-face{font-family:"Pure Sans DSI";font-style:normal;font-weight:700;font-display:swap;src:url(../assets/fonts/pure-sans/pure-sans-700-normal.woff2) format("woff2")}

.ep-fig{--draw:2.2s;--draw-ease:cubic-bezier(.65,0,.35,1);
  container-type:inline-size;background:#5a6359;color:#fff5e3;overflow-x:clip;
  font-family:"Pure Sans DSI","Pure Sans","Helvetica Neue",Arial,sans-serif;-webkit-font-smoothing:antialiased}
.ep-fig *,.ep-fig *::before,.ep-fig *::after{box-sizing:border-box}
.ep-fig img{display:block;max-width:none}
.ep-fig .stage{position:relative;--u:calc(100cqw / 1600);height:calc(var(--sh) * var(--u))}

/* --- the canvas: every element carries its Figma coordinates --- */
.ep-fig .stage [style*="--x:"]{position:absolute;left:calc(var(--x) * var(--u));top:calc(var(--y,0) * var(--u))}
.ep-fig .stage [style*="--w:"]{width:calc(var(--w) * var(--u))}
/* Figma puts tracking BETWEEN characters; CSS also adds it after the last one, so a text box
   sized to hug its text in Figma overflows here by exactly one letter-space and wraps a word.
   Give every tracked box that one letter-space back. */
.ep-fig .stage [style*="--w:"][style*="--ls:"]{width:calc((var(--w) + var(--ls)) * var(--u))}
.ep-fig .stage [style*="--h:"]{height:calc(var(--h) * var(--u))}
.ep-fig [style*="--fs:"]{font-size:calc(var(--fs) * var(--u))}
.ep-fig [style*="--lh:"]{line-height:calc(var(--lh) * var(--u))}
.ep-fig [style*="--ls:"]{letter-spacing:calc(var(--ls) * var(--u))}
.ep-fig [style*="--col:"]{color:var(--col)}
.ep-fig .im>img{width:100%;height:100%}
/* An image FILL (board 1305:5 uses three). The node is a window onto a larger bitmap: it
   clips, and the bitmap carries its own size and offset in percent of the node box. Never
   swap this for .im - fitting the bitmap to the box shrinks the artwork and shifts it. */
.ep-fig .cim{overflow:hidden}
.ep-fig .cim>img{position:absolute;left:calc(var(--il) * 1%);top:calc(var(--it) * 1%);
  width:calc(var(--iw) * 1%);height:calc(var(--ih) * 1%);max-width:none}
/* 1312:539 - the ground shadow is masked by the artwork's own alpha (1312:538). mask-size
   and mask-position are expressed against this element's own box, so they hold at every
   tier; Figma's px values would only be right while --u is the desktop unit. */
.ep-fig .rmask{-webkit-mask-image:var(--mi);mask-image:var(--mi);
  -webkit-mask-size:var(--ms);mask-size:var(--ms);
  -webkit-mask-position:var(--mp);mask-position:var(--mp);
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}
.ep-fig .rmask>img{position:absolute;left:0;top:-0.48%;width:100%;height:100.96%}

/* hero (node 2756:10402): a flat ground with a single very large curve bleeding off the
   right. The board rotates it -180deg and mirrors it in x, which nets out to a y flip. */
.ep-fig .herobg{background:#392d26;overflow:hidden}
.ep-fig .herobg .curve{position:absolute;left:-230.13%;top:-176.96%;width:606.19%;height:549.72%;
  transform:scaleY(-1)}
.ep-fig .hcard{background:#42342d;border-radius:calc(25 * var(--u))}
.ep-fig .hillo{pointer-events:none}
.ep-fig .hillo .p{position:absolute;left:calc(var(--l) * 1%);top:calc(var(--t) * 1%);
  width:calc(var(--pw) * 1%);height:calc(var(--ph) * 1%)}
.ep-fig .hillo .p.flipx{transform:scaleX(-1)}
.ep-fig .hillo .p.bar{background:#93a597;border-radius:calc(2 * var(--u))}
.ep-fig .num.hnum{font-weight:500}
.ep-fig .pct.hpct{font-weight:400}
.ep-fig .hcap{font-weight:400}

/* --- surfaces --- */
/* Borders are painted as inset shadows: a real border insets the padding box, which is the
   containing block for the absolutely positioned children, shifting every card's contents 1px
   off its Figma coordinates. */
.ep-fig .panel.p1{box-shadow:inset 0 0 0 1px #909090;border-radius:calc(15 * var(--u))}
.ep-fig .panel.p2,.ep-fig .panel.p3{background:#6f594d;box-shadow:inset 0 0 0 1px #b9867c;border-radius:calc(15 * var(--u))}
.ep-fig .card{background:#687367;box-shadow:inset 0 0 0 1px rgba(165,191,170,.5);border-radius:calc(15 * var(--u))}
/* the Section 3 trio and the Section 5 pair carry the solid moss edge, Section 4 a 50% one */
.ep-fig .card.z1,.ep-fig .card.z2,.ep-fig .card.z3,.ep-fig .card.cg{box-shadow:inset 0 0 0 1px #a5bfaa}
.ep-fig .closepanel{background:#2d2a27;border-radius:calc(15 * var(--u));
  box-shadow:inset 0 0 0 1px #a49688}
.ep-fig .ptop{border-radius:calc(15 * var(--u)) calc(15 * var(--u)) 0 0;overflow:hidden}

/* --- dashed thread between sections --- */
.ep-fig .rule{pointer-events:none}
.ep-fig .rule.dash{height:calc(2 * var(--u));background:repeating-linear-gradient(to right,
  rgba(255,255,255,.3) 0 calc(6 * var(--u)),transparent calc(6 * var(--u)) calc(12 * var(--u)))}
.ep-fig .rule.dash.v{width:calc(2 * var(--u));height:calc(var(--h) * var(--u));
  background:repeating-linear-gradient(to bottom,
  rgba(255,255,255,.3) 0 calc(6 * var(--u)),transparent calc(6 * var(--u)) calc(12 * var(--u)))}
/* the solid rules are exported <line> nodes; each carries its own stroke, so they are NOT all
   a tint of white - taken from the 1014 / 1149 / 953 / 292 exports in figma-assets */
.ep-fig .rule.solid{height:1px;background:#8fa596}              /* Section 2, 1014 wide */
.ep-fig .rule.solid.half{background:#513f2d}                    /* closing, 679:527 Line 327, 880 wide */
.ep-fig .rule.solid.clay{background:#93786a}                    /* balance panel, 953 wide */
.ep-fig .rule.solid.faint{background:#5a6359}                   /* 679:360 Line 326, 922 wide */
.ep-fig .rule.v.soft{width:1px;background:#909090}              /* Section 1 panel dividers, 292 tall */

/* --- type --- */
.ep-fig .h1,.ep-fig .h2,.ep-fig .h3,.ep-fig .h4{font-weight:500;margin:0;text-wrap:balance}
.ep-fig .pole,.ep-fig .cc{font-weight:700}
.ep-fig .hclose{font-weight:500}                 /* 679:239 is Pure Sans Medium */
.ep-fig .sbd{font-weight:500}
/* 679:499 / 679:502 sit on the seesaw's pills. 18 of the illustration's 641 board units is
   2.81%, so a container query holds the type to the artwork at every width. Nothing inside
   .illo.seesaw reads --u, so making it a container cannot disturb the canvas scale. */
.ep-fig .illo.seesaw{container-type:inline-size}
.ep-fig .illo.seesaw .bkl{position:absolute;font-style:normal;
  left:calc(var(--l) * 1%);top:calc(var(--t) * 1%);width:calc(var(--pw) * 1%);
  font-weight:600;font-size:2.81cqw;line-height:1.4;letter-spacing:.078cqw;
  text-align:center;color:#fbf3e0}
.ep-fig .eyebrow,.ep-fig .thesis,.ep-fig .support{font-weight:400}
.ep-fig .support{color:#fff5e3}
.ep-fig .center{text-align:center}
.ep-fig .right{text-align:right}
.ep-fig .kicker{font-weight:500;text-transform:uppercase}
.ep-fig b{font-weight:600}
.ep-fig .num{font-weight:700;line-height:1;white-space:nowrap;font-variant-numeric:tabular-nums}
/* .num's line-height:1 ties with the generic [style*="--lh:"] rule on specificity and wins on
   source order, so a figure that states its own leading was silently getting font-size
   instead. That left the 92 (178px type, 200px leading, bottom-anchored) 22px low. */
.ep-fig .num[style*="--lh:"]{line-height:calc(var(--lh) * var(--u))}
.ep-fig .num.up{font-weight:500;transform:translateY(-100%)}
.ep-fig .num.sb{font-weight:600}
.ep-fig .pct{font-weight:500;line-height:1;white-space:nowrap}
.ep-fig .pct.ctr{transform:translate(-50%,-50%)}
.ep-fig .pct.p56,.ep-fig .pct.p36,.ep-fig .pct.p178{font-weight:400}

/* --- section badge --- */
.ep-fig .badge .hx{position:absolute;left:1.7%;top:0;width:98.3%;height:98%}
.ep-fig .badge{overflow:hidden}
/* 937:4190 is ONE text box - inset 27.95%/46.31%, two lines, BOTH on a 22-unit line box even
   though the figure is 40. That line box is what seats the pair: with line-height:1 the 40
   drew its own 40-tall box and pushed the label to 66%, ~15% below where the board has it.
   Positioning each line at the board's own line top and giving both the 22 reproduces it.
   And the label is NOT uppercase - get_screenshot on 937:4188 renders "Section". The Tailwind
   conversion says `uppercase`, which is why this survived three builds; the render wins. */
.ep-fig .badge .bn,.ep-fig .badge .bs{position:absolute;left:27.95%;width:46.31%;text-align:center;
  color:#2d2a27;font-weight:600;line-height:calc(22 * var(--u))}
.ep-fig .badge .bn{top:25.81%;font-size:calc(40 * var(--u))}
/* 937:4190's second line starts at 47.65% of the badge, which is what the board's 22-unit
   line box gives. Reproduced literally the ink gap comes out at 2.0 units - the figure's
   ink ends at 52.6 and the label's starts at 54.6 - because a browser centres a 40px
   glyph in a 22px line box tighter than Figma's text engine does - Figma's own gap works
   out at ~3.4. Opened to ~10 at the client's direction, so the two read as clearly
   separate lines. */
.ep-fig .badge .bs{top:55.58%;font-size:calc(16 * var(--u));letter-spacing:calc(.5 * var(--u))}

.ep-fig .nw{white-space:nowrap}
.ep-fig .dotrow{display:flex;align-items:center;gap:calc(17 * var(--u));white-space:nowrap;line-height:1}
.ep-fig .dotrow .dot{flex:none;width:calc(4.446 * var(--u));height:calc(3.834 * var(--u));
  border-radius:50%;background:currentColor}
/* the board paints the 80% card over the 85%, and both over Control/Capability */
.ep-fig .stage .z4{z-index:4}.ep-fig .stage .z3{z-index:3}.ep-fig .stage .z2{z-index:2}.ep-fig .stage .z1{z-index:1}

/* --- illustrations --- */
.ep-fig .illo{pointer-events:none;z-index:0}
/* headings and copy always read over the artwork, as they do on the board */
.ep-fig .h1,.ep-fig .h2,.ep-fig .h3,.ep-fig .h4,.ep-fig .support,.ep-fig .thesis,
.ep-fig .eyebrow,.ep-fig .num,.ep-fig .pct,.ep-fig .badge{z-index:2}
.ep-fig .card,.ep-fig .panel,.ep-fig .closepanel{z-index:1}
.ep-fig .illo .p{position:absolute;left:calc(var(--l) * 1%);top:calc(var(--t) * 1%);
  width:calc(var(--pw) * 1%);height:calc(var(--ph) * 1%)}
/* 679:27's content is rotate-180 + -scale-y-100, which composes to a horizontal mirror */
.ep-fig .illo .p.flip{transform:scaleX(-1)}
/* 679:27 is painted after the panel 679:26, so the traces cross onto it */
.ep-fig .illo.trans{z-index:2}
/* 679:418 is a plain Basil rounded rect under the racks, not an export */
.ep-fig .illo .sq{background:#c5e4cc}
.ep-fig .illo .barline{background:#5a6359;border-radius:calc(70 * var(--u))}

/* --- driver bars --- */
.ep-fig .bar{background:#939393;border-radius:calc(100 * var(--u));overflow:hidden}
.ep-fig .bar>i{display:block;height:100%;width:var(--p);background:#f87834;border-radius:inherit;
  transition:width var(--draw) var(--draw-ease)}

/* --- gauges (top half of the exported ring) --- */
.ep-fig .gauge{overflow:hidden}
/* the rail is a fixed backdrop; only .garc carries the sweep mask */
.ep-fig .gauge img{position:absolute;inset:0;width:100%;height:200%}

/* --- balance --- */
.ep-fig .track{border-radius:calc(100 * var(--u));
  background:linear-gradient(90deg,#c6e3cc 0%,#fff5e3 50%,#f96f24 100%);
  box-shadow:inset 0 calc(4 * var(--u)) calc(7 * var(--u)) rgba(0,0,0,.29)}
.ep-fig .pill{border-radius:calc(4 * var(--u));display:grid;place-items:center}
.ep-fig .pill.ctrl{background:#c6e3cc}
.ep-fig .pill.cap{background:#f96f24}
.ep-fig .pill span{font-weight:600;font-size:calc(20 * var(--u));letter-spacing:calc(.5 * var(--u))}
.ep-fig .pill.ctrl span{color:#2d2a27}
.ep-fig .pill.cap span{color:#fff5e3}
.ep-fig .stage .handle{left:calc((var(--v,50) * 7.02 - 1.05) * var(--u));transition:left .35s cubic-bezier(.2,.7,.2,1)}

/* ===================== board 679:21 additions ===================== *
 * The revision introduces two card treatments (Basil and CREAM), the pill labels that
 * bracket section 4, and the 958x731 outline that groups it. Colours are the board's own,
 * not the brand palette - see build-v3/NOTES-v3.md, they drifted. */
.ep-fig .card.cream{background:#fff5e3;box-shadow:inset 0 0 0 1px #fff6e1}
.ep-fig .card.c87,.ep-fig .card.c39{background:#677368;box-shadow:none}
.ep-fig .panel.p2b{background:#687367;box-shadow:inset 0 0 0 1px #a5bfaa;
  border-radius:calc(15 * var(--u))}
/* 679:560 is a 2px stroke that FADES around the loop - brightest at the live end. The MCP
   flattens gradient strokes (it reports a solid border-[#fff5e3] however the node is asked
   for), so the stops are read off the board's own render, not from the capture. Painted as a
   gradient in the border box masked against the padding box, which is the only way to get a
   gradient stroke on a rounded rect. --ga is the angle, re-pointed at the live card. */
.ep-fig .sec.s4 .bracket{border:calc(2 * var(--u)) solid transparent;border-radius:calc(49 * var(--u));
  pointer-events:none;
  background:linear-gradient(var(--ga,0deg),#fff5e3 0%,#fff5e3 26%,rgba(255,245,227,.22) 66%,rgba(255,245,227,.08) 100%) border-box;
  -webkit-mask:linear-gradient(#000 0 0) padding-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask:linear-gradient(#000 0 0) padding-box,linear-gradient(#000 0 0);
  mask-composite:exclude;transition:--ga .45s ease}
@property --ga{syntax:'<angle>';inherits:true;initial-value:0deg}
/* The live end follows the active card. CSS gradient angles name the direction the line
   POINTS, so the first stop - the bright one - sits at the opposite end: 180deg points down
   and therefore lights the TOP. The three were inverted, lighting the far side of the loop
   from the card that was active.
     CONTROL     top centre      -> 180deg  (bright at top)
     CAPABILITY  bottom left     ->  45deg  (line to top-right, bright at bottom-left)
     COMPLEXITY  bottom right    -> 315deg  (line to top-left,  bright at bottom-right) */
.ep-fig .sec.s4[data-flow="control"]{--ga:180deg}
.ep-fig .sec.s4[data-flow="capability"]{--ga:45deg}
.ep-fig .sec.s4[data-flow="complexity"]{--ga:315deg}

/* Arrow colour marks the live leg of the circuit. The board ships the CONTROL state - the
   upper pair 679:561/563 cream, the lower 679:562/564 #677368 - so both inks come from the
   design; only which position wears which changes.
     CONTROL     both sides converge upward -> .top and .up lit
     CAPABILITY  bottom LEFT                -> the whole left leg lit
     COMPLEXITY  bottom RIGHT               -> the whole right leg lit */
.ep-fig .sec.s4 .poly{color:#677368}
.ep-fig .sec.s4 .poly svg [fill="#FFF5E3"],.ep-fig .sec.s4 .poly svg [fill="#677368"],
.ep-fig .sec.s4 .poly svg [fill="#fff5e3"],.ep-fig .sec.s4 .poly svg [fill="#677368"]{
  fill:currentColor;transition:fill .3s ease}
.ep-fig .sec.s4[data-flow="control"] .poly.top,
.ep-fig .sec.s4[data-flow="control"] .poly.up{color:#fff5e3}
.ep-fig .sec.s4[data-flow="capability"] .poly.l{color:#fff5e3}
.ep-fig .sec.s4[data-flow="complexity"] .poly.r{color:#fff5e3}
/* the bottom rail joins the two lower ends, so its notch belongs to neither leg: it lights and
   turns toward whichever of them is live, and sits dormant in CONTROL, where the board runs the
   flow up both sides instead. */
.ep-fig .sec.s4[data-flow="capability"] .poly.mid,
.ep-fig .sec.s4[data-flow="complexity"] .poly.mid{color:#fff5e3}
/* The arrows point along the flow. The board draws them converging on CONTROL - the top pair
   aimed inward, the side pair aimed up. When a bottom card is live the circuit runs the other
   way, so the whole set turns 180deg: the sides now point DOWN toward the live card and the
   top pair points outward, away from CONTROL. Rotating the container works for all six - the
   +/-90 pair carry their own rotation on the inner <img>, which composes with this. */
.ep-fig .sec.s4 .poly{transition:transform .35s cubic-bezier(.2,.7,.2,1)}
.ep-fig .sec.s4:not([data-flow="control"]) .poly:not(.mid){transform:rotate(180deg)}
/* .mid is authored pointing right (r90); 180 on the wrapper composes with that to point left */
.ep-fig .sec.s4[data-flow="capability"] .poly.mid{transform:rotate(180deg)}

/* The icons must follow their card. They are inlined SVG (a baked-in fill cannot be
   recoloured through an <img>), and only the INK fills are redirected to currentColor -
   'none' and the 'white' clipPath rects are left alone, or the clip would start painting.
   The board gives the ink both ways already: #5a6359 on the cream card, #fff5e3 on Basil. */
.ep-fig .icon.ink svg{display:block;width:100%;height:100%}
.ep-fig .icon.ink svg [fill="#FFF5E3"],.ep-fig .icon.ink svg [fill="#5A6359"],
.ep-fig .icon.ink svg [fill="#fff5e3"],.ep-fig .icon.ink svg [fill="#5a6359"]{
  fill:currentColor;transition:fill .3s ease}
.ep-fig .sec.s4 .card.live .icon.ink{color:#5a6359}
.ep-fig .sec.s4 .card.dormant .icon.ink{color:#fff5e3}

/* --- the three cards are selectable; the live one takes the cream treatment the board
       gives the 92% card. Only that state is drawn on the board, so the other two mirror it
       rather than inventing a new one. Sizes are untouched. --- */
.ep-fig .sec.s4 .card.lead,.ep-fig .sec.s4 .card.c87,.ep-fig .sec.s4 .card.c39{
  cursor:pointer;pointer-events:auto;
  transition:background-color .3s ease,box-shadow .3s ease}
.ep-fig .sec.s4 .card.c87 .num,.ep-fig .sec.s4 .card.c39 .num,
.ep-fig .sec.s4 .card.c87 .pct,.ep-fig .sec.s4 .card.c39 .pct,
.ep-fig .sec.s4 .card.c87 .cap22,.ep-fig .sec.s4 .card.c39 .cap22,
.ep-fig .sec.s4 .card.lead .num,.ep-fig .sec.s4 .card.lead .pct,
.ep-fig .sec.s4 .card.lead .cap40{transition:color .3s ease}
/* live */
.ep-fig .sec.s4 .card.live{background:#fff5e3;box-shadow:inset 0 0 0 1px #fff6e1}
.ep-fig .sec.s4 .card.live .num,.ep-fig .sec.s4 .card.live .pct{color:#f87834}
.ep-fig .sec.s4 .card.live .cap22,.ep-fig .sec.s4 .card.live .cap40{color:#5a6359}
/* dormant */
.ep-fig .sec.s4 .card.dormant{background:#677368;box-shadow:none}
.ep-fig .sec.s4 .card.dormant .num,.ep-fig .sec.s4 .card.dormant .pct{color:#fff5e3}
.ep-fig .sec.s4 .card.dormant .cap22,.ep-fig .sec.s4 .card.dormant .cap40{color:#c5e4cc}
/* The three pills SELECT the loop, exactly like the cards - they are buttons, not captions.
   Verified against the board (get_design_context on 679:565, 2026-09-16): the pills carry a
   fill and a 100px radius and NO stroke at all - `bg-[#677368] rounded-[100px]`. The only
   stroked nodes in this group are the lead card 679:530 and the bracket 679:560. So the state
   change is fill-only: cream for the live end (679:559), #677368 for the other two. */
.ep-fig .sec.s4 .plabel{transition:background-color .3s ease;cursor:pointer}
.ep-fig .sec.s4 .plabel>span{transition:color .3s ease}
.ep-fig .sec.s4 .plabel.live{background:#fff5e3}
.ep-fig .sec.s4 .plabel.live>span{color:#504e4b}
.ep-fig .sec.s4 .plabel.dormant{background:#677368}
.ep-fig .sec.s4 .plabel.dormant>span{color:#fff5e3}
.ep-fig .sec.s4 .plabel:focus-visible{outline:2px solid #f87834;outline-offset:3px}
/* the six notches on the bracket. 679:570/571 are 14x16 boxes holding a 16x14 image turned
   +/-90, so the image keeps its pre-rotation size and is centred. */
.ep-fig .poly>img,.ep-fig .poly>svg{display:block;width:100%;height:100%}
.ep-fig .poly.r90>img,.ep-fig .poly.rn90>img,
.ep-fig .poly.r90>svg,.ep-fig .poly.rn90>svg{position:absolute;left:50%;top:50%;
  width:calc(16 * var(--u));height:calc(14 * var(--u))}
.ep-fig .poly.r90>img,.ep-fig .poly.r90>svg{transform:translate(-50%,-50%) rotate(90deg)}
.ep-fig .poly.rn90>img,.ep-fig .poly.rn90>svg{transform:translate(-50%,-50%) rotate(-90deg)}
.ep-fig .plabel{display:grid;place-items:center;border-radius:calc(100 * var(--u))}
.ep-fig .plabel>span{font-weight:500;font-size:calc(24 * var(--u));
  letter-spacing:calc(.5 * var(--u));line-height:calc(29 * var(--u))}
.ep-fig .plabel.ctl{background:#fff5e3}
.ep-fig .plabel.ctl>span{color:#504e4b}
.ep-fig .plabel.cap,.ep-fig .plabel.cpx{background:#677368}
.ep-fig .plabel.cap>span,.ep-fig .plabel.cpx>span{color:#fff5e3}
/* section 3's cream card carries dark type, inverting the section */
.ep-fig .card.ccc.cream .h3.cc{color:#fa7224}
.ep-fig .stage .conn>img{width:100%;height:100%}
/* --- section 3's connector threads draw themselves --- */
.ep-fig .conns{pointer-events:none}
.ep-fig .conn svg{display:block;width:100%;height:100%;overflow:visible}
/* --len is each path's own getTotalLength(), set by the JS at init */
.ep-fig.js .conns .conn path{stroke-dasharray:var(--len,600);stroke-dashoffset:var(--len,600)}
/* a negative offset reveals the path from its OTHER end - this one is authored downward but
   should draw bottom-up. Must sit before the .on rule: same specificity, source order wins. */
.ep-fig.js .conns .conn.rev path{stroke-dashoffset:calc(var(--len,600) * -1)}
.ep-fig.js .conns.on .conn path{stroke-dashoffset:0;
  transition:stroke-dashoffset 1.05s cubic-bezier(.65,0,.35,1)}
.ep-fig.js .conns .conn circle{opacity:0}
.ep-fig.js .conns.on .conn circle{opacity:1;transition:opacity .3s ease .85s}
@media (prefers-reduced-motion:reduce){
  .ep-fig.js .conns .conn path{stroke-dashoffset:0}
  .ep-fig.js .conns .conn circle{opacity:1}}

/* --- 679:27: the traces out of section 5 draw themselves into the closing panel --- */
.ep-fig .illo.trans svg{display:block;width:100%;height:100%;overflow:visible}
/* the drawing IS this element's reveal, so no fade or lift underneath it */
.ep-fig.js .illo.trans.rv{opacity:1;transform:none}
.ep-fig.js .illo.trans .tr{stroke-dasharray:var(--len,400);stroke-dashoffset:var(--len,400)}
/* subpaths 1 and 3 are authored from their dot outwards - a negative offset draws them the
   other way. Must sit before the .on rule: same specificity, source order wins. */
.ep-fig.js .illo.trans .tr.rev{stroke-dashoffset:calc(var(--len,400) * -1)}
.ep-fig.js .illo.trans.on .tr{stroke-dashoffset:0;
  transition:stroke-dashoffset 1.05s cubic-bezier(.65,0,.35,1)}
/* every dot lands once its own trace has arrived */
.ep-fig.js .illo.trans .dot{opacity:0}
.ep-fig.js .illo.trans.on .dot{opacity:1;transition:opacity .3s ease .85s}
@media (prefers-reduced-motion:reduce){
  .ep-fig.js .illo.trans .tr{stroke-dashoffset:0}
  .ep-fig.js .illo.trans .dot{opacity:1}}

.ep-fig .stage .handle{overflow:visible}
.ep-fig .handle>img{position:absolute;left:-12.5%;top:0;width:125%;height:125%}
.ep-fig .slider{z-index:3}
.ep-fig .slider input{-webkit-appearance:none;appearance:none;width:100%;height:100%;margin:0;background:transparent;cursor:pointer}
.ep-fig .slider input::-webkit-slider-thumb{-webkit-appearance:none;width:calc(32 * var(--u));height:calc(32 * var(--u));border-radius:50%;background:transparent}
.ep-fig .slider input::-moz-range-thumb{width:calc(32 * var(--u));height:calc(32 * var(--u));border:0;border-radius:50%;background:transparent}
.ep-fig .slider input:focus-visible{outline:2px solid #f96f24;outline-offset:2px;border-radius:calc(20 * var(--u))}
.ep-fig .chip button{width:100%;height:100%;border-radius:calc(100 * var(--u));border:1px solid transparent;
  background:#564136;color:#fff;font:inherit;font-size:calc(16 * var(--u));line-height:calc(29 * var(--u));
  letter-spacing:calc(.5 * var(--u));cursor:pointer;white-space:nowrap;
  padding:0 calc(10 * var(--u)) 0 calc(var(--pl,12) * var(--u));
  text-align:left;
  transition:background .2s,color .2s,border-color .2s,transform .2s}
.ep-fig .chip button[aria-pressed="true"]{background:#fff5e3;border-color:transparent;color:#504e4b;font-weight:500}
.ep-fig .chip button:hover{border-color:#f96f24;transform:translateY(-1px)}

/* the beam tips around the fulcrum and the weights gain and lose mass */
.ep-fig .scale{--tilt-max:4.5}      /* the board's cap, derived from ITS spacing */
.ep-fig .stage .beam{transform:rotate(var(--tilt,0deg));transform-origin:50% 81.43%;
  transition:transform .5s cubic-bezier(.2,.7,.2,1)}
.ep-fig .pill{transition:transform .5s cubic-bezier(.2,.7,.2,1),opacity .35s;transform-origin:50% 100%}
.ep-fig .pill.ctrl{transform:scale(var(--kc,1))}
.ep-fig .pill.cap{transform:scale(var(--kp,1))}
.ep-fig .scale[data-side="control"] .pill.cap,
.ep-fig .scale[data-side="capability"] .pill.ctrl{opacity:.6}

/* charts draw themselves: a conic mask sweeps the exported arc into place */
/* Each arc is a round-capped stroke, so the wedge has to START on the cap and STOP at the
   arc's own end. Beginning at 0deg left the donut's start cap sitting at 356.6-360deg, which
   the sweep only reached on its last frame - the tip appeared to pop in after the draw - and
   sweeping the full 360 meant the 210deg arc finished at 58% and then sat still.
   --sweep-from is the cap's leading edge; --sweep-full is the arc's own angular length. */
@property --sweep{syntax:'<angle>';inherits:false;initial-value:360deg}
.ep-fig .donut>.p:nth-child(2){--sweep-from:-5deg;--sweep-full:212deg;
  -webkit-mask-image:conic-gradient(from var(--sweep-from) at 28.4% 50%,#000 var(--sweep),transparent 0);
  mask-image:conic-gradient(from var(--sweep-from) at 28.4% 50%,#000 var(--sweep),transparent 0)}
.ep-fig .gauge .garc{
  -webkit-mask-image:conic-gradient(from var(--sweep-from) at 50% 50%,#000 var(--sweep),transparent 0);
  mask-image:conic-gradient(from var(--sweep-from) at 50% 50%,#000 var(--sweep),transparent 0)}
.ep-fig .donut>.p:nth-child(2),.ep-fig .gauge .garc{transition:--sweep var(--draw) var(--draw-ease)}

/* --- call to action --- */
.ep-fig .cta a{display:flex;align-items:center;justify-content:center;width:100%;height:100%;
  background:#d55d1d;border-radius:calc(4 * var(--u));color:#fff5e3;font-weight:500;
  font-size:calc(16 * var(--u));letter-spacing:calc(.16 * var(--u));text-decoration:none;transition:filter .2s}
.ep-fig .cta a:hover{filter:brightness(1.08)}

/* --- reveal --- */
.ep-fig.js .rv{opacity:0;transform:translateY(calc(22 * var(--u)));
  transition:opacity .65s ease,transform .75s cubic-bezier(.2,.7,.2,1);
  transition-delay:calc(var(--d,0) * 90ms)}
.ep-fig.js .rv.big{transform:translateY(calc(34 * var(--u))) scale(.985)}
.ep-fig.js .rv.on,.ep-fig.js .rv.big.on{opacity:1;transform:none}
.ep-fig.js .rv.num.up{transform:translateY(-100%)}
@media (prefers-reduced-motion:reduce){.ep-fig *{transition:none!important;animation:none!important}
  .ep-fig.js .rv{opacity:1;transform:none}}

/* ============== narrow: the same blocks, in one readable column ==============
   The reset below and every component rule are all `.ep-fig .stage …`, so they share
   specificity and source order decides — components must stay after the reset. */
@container (max-width:1279px){
  .ep-fig .stage{height:auto;--u:1px}
  .ep-fig .stage [style*="--x:"]{position:static;left:auto;top:auto;width:auto;height:auto;transform:none}
  /* the tracked-box width fix above is one selector more specific than this reset, so undo it here too */
  .ep-fig .stage [style*="--w:"][style*="--ls:"]{width:auto}
  /* .num.up is bottom-anchored on the board (permanent translateY(-100%)); once it is in
     normal flow that lift only leaves a hole the height of the figure */
  .ep-fig.js .stage .rv.num.up,.ep-fig .stage .num.up{transform:none}

  .ep-fig .stage .sec{padding:2.5rem 1.25rem;display:block;max-width:820px;margin:0 auto}
  /* the panel keeps the same side gutter as every other section rather than running to the
     screen edge - the board insets it too (679:26 starts at x235 of 1600) */
  .ep-fig .stage .sec.close{max-width:none}
  .ep-fig .stage .sec.hero{position:relative;padding:3rem 1.25rem 2.5rem;overflow:hidden;
    background:#392d26}
  .ep-fig .stage .herobg{display:none}
  .ep-fig .stage .hero>*{position:relative;left:auto;top:auto;z-index:1}
  .ep-fig .stage .rule,.ep-fig .stage .ptop,.ep-fig .stage .mark,
  .ep-fig .stage .fulcrum,.ep-fig .stage .handle,
  .ep-fig .stage .conns,
  .ep-fig .stage .sec.s4 .poly,.ep-fig .stage .sec.s4 .bracket{display:none}

  .ep-fig .stage .badge{position:relative;width:76px;height:67px;margin-bottom:1.2rem}
  .ep-fig .stage .badge .bn{font-size:26px;line-height:14px}
  .ep-fig .stage .badge .bs{font-size:10px;line-height:14px}
  /* The board threads every badge onto a dashed rule. Those rules are hidden here (their
     geometry is the 1600 serpentine - right, down, back left, down), so redraw just the
     segment that leaves the badge: same 2px / 6-6 / white-30% stroke, starting 42% across
     the badge as on the board so it runs behind the hex, ending on the content gutter
     (the board stops at 1479 of 1600, not at the canvas edge). Badge is the first laid-out
     child of the section, so its centre is padding-top + 67/2. */
  .ep-fig .stage .sec.s1,.ep-fig .stage .sec.s2,.ep-fig .stage .sec.s3,
  .ep-fig .stage .sec.s4,.ep-fig .stage .sec.s5{position:relative}
  .ep-fig .stage .sec.s1::before,.ep-fig .stage .sec.s2::before,.ep-fig .stage .sec.s3::before,
  .ep-fig .stage .sec.s4::before,.ep-fig .stage .sec.s5::before{content:"";position:absolute;
    left:calc(1.25rem + 32px);right:1.25rem;top:calc(2.5rem + 32.5px);height:2px;
    background:repeating-linear-gradient(to right,
    rgba(255,255,255,.3) 0 6px,transparent 6px 12px)}

  .ep-fig .nw{white-space:normal}
  .ep-fig .stage .illo{position:relative;width:min(100%,300px);height:auto;margin:0 auto 1.6rem;
    aspect-ratio:calc(var(--w) / var(--h))}
  .ep-fig .stage .illo.flat>img{width:100%;height:100%}

  .ep-fig .stage .wrap,.ep-fig .stage .poles,.ep-fig .stage .chips{display:block}
  .ep-fig .stage .hstat,.ep-fig .stage .drv,.ep-fig .stage .mini,
  .ep-fig .stage .bigstat,.ep-fig .stage .card,.ep-fig .stage .hcard{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 .25rem}
  .ep-fig .stage .hstat,.ep-fig .stage .mini,.ep-fig .stage .bigstat{margin:0 0 1.6rem}
  /* flex-basis wins over width on a flex item, so the cap has to be a max-width */
  .ep-fig .stage .hillo{flex:0 0 100%;position:relative;width:auto;max-width:260px;height:auto;
    aspect-ratio:calc(var(--w) / var(--h));margin:0 0 1rem}
  .ep-fig .stage .hillo.im>img{width:100%;height:100%}  /* not .target, whose parts size themselves */
  .ep-fig .stage .hcap{flex:1 1 55%;font-size:.95rem;line-height:1.45;align-self:center}
  .ep-fig .stage .num.hnum{font-size:3.4rem;line-height:1}   /* 108: 1.17x .big, as the board */
  .ep-fig .stage .pct.hpct{font-size:1.5rem;line-height:1}
  .ep-fig .stage .drv{margin:0 0 1.9rem}
  .ep-fig .stage .card,.ep-fig .stage .panel,.ep-fig .stage .hcard{border-radius:16px;padding:1.25rem;margin:0 0 1.5rem}
  /* a card or panel that ENDS a section must not add its stacking margin to the section's
     own floor - sections 2 and 3 were closing on 64px where the rest close on 40 */
  .ep-fig .stage .sec>.card:last-child,.ep-fig .stage .sec>.panel:last-child{margin-bottom:0}
  /* equal padding all round. The clipped bottom was compensating for the last driver's own
     1.9rem stacking margin - which only exists in THIS tier, so zero that instead and the
     tablet tier (where .drv margins are already 0) stops sitting on its bars. */
  .ep-fig .stage .panel.p1{padding:1.25rem}
  /* the 3rem here cleared the balance panel, which 937:3981 removes - 937:4089 now follows
     the card directly, 80 units below it on the board where every other reflow gap is
     1.25rem, so the card's own stacking margin is the whole story */
  .ep-fig .stage .panel.p1 .drv:last-child{margin-bottom:0}
  .ep-fig .stage .icon,.ep-fig .stage .cap16,.ep-fig .stage .cap17,.ep-fig .stage .cap18,.ep-fig .stage .cap20,
  .ep-fig .stage .cap22,.ep-fig .stage .cap28,.ep-fig .stage .cap40,.ep-fig .stage .bar,
  .ep-fig .stage .support,.ep-fig .stage .h3,.ep-fig .stage .h4{flex:0 0 100%}
  /* the loop's pills hug their text at every width, rather than becoming full-width bars */
  .ep-fig .stage .sec.s4 .plabel{width:fit-content;margin-inline:auto;
    padding:.45rem 1.25rem;border-radius:100px}
  .ep-fig .stage .sec.s4 .plabel>span{font-size:1rem;line-height:1.2}
  .ep-fig .stage .icon{width:auto;height:40px;margin-bottom:.8rem}
  .ep-fig .stage .icon>img{width:auto;height:100%}
  /* section 4's icons are INLINE svg (they have to be, to recolour with their card) and an
     inline svg at width:100% does not hold its aspect the way an <img> does - it stretched
     to the full card. The board draws them square (68 and 48), so pin both axes. */
  /* the wrapper keeps its full-width flex line, so the icon still sits on its own row above
     the figure as the board draws it; the svg inside is what gets pinned square */
  .ep-fig .stage .icon.ink{flex:0 0 100%;width:auto;height:40px}
  .ep-fig .stage .icon.ink>svg{display:block;width:40px;height:40px}
  /* 679:536 is 68 where the two lower cards' are 48 - the lead card carries the bigger
     icon on the board, so it does here too (40 x 68/48) */
  .ep-fig .stage .sec.s4 .card.lead .icon.ink{height:56px}
  .ep-fig .stage .sec.s4 .card.lead .icon.ink>svg{width:56px;height:56px}

  /* the board puts the icon BESIDE the figure here (679:144 at x381, 679:132 at x449, same
     row), unlike the drivers above, where it sits on its own line */
  .ep-fig .stage .panel.p2b .mini{display:grid;gap:0 .4rem;align-items:baseline;
    grid-template-columns:auto auto 1fr;grid-template-rows:auto 1fr}
  .ep-fig .stage .panel.p2b .mini .icon{grid-area:1/1/2/2;align-self:center;margin:0 .2rem 0 0}
  .ep-fig .stage .panel.p2b .mini .num{grid-area:1/2/2/3}
  .ep-fig .stage .panel.p2b .mini .pct{grid-area:1/3/2/4;justify-self:start}
  .ep-fig .stage .panel.p2b .mini .cap22{grid-area:2/1/3/4;margin-top:.6rem}
  /* 679:531 / 679:533 put the icon beside the figure, not under it */
  .ep-fig .stage .sec.s4 .card.c87,.ep-fig .stage .sec.s4 .card.c39{display:grid;
    grid-template-columns:auto auto 1fr;align-items:baseline;column-gap:.55rem}
  .ep-fig .stage .sec.s4 .card.c87>.icon,.ep-fig .stage .sec.s4 .card.c39>.icon{
    grid-area:1/1/2/2;align-self:center;margin:0}
  .ep-fig .stage .sec.s4 .card.c87>.num,.ep-fig .stage .sec.s4 .card.c39>.num{grid-area:1/2/2/3}
  .ep-fig .stage .sec.s4 .card.c87>.pct,.ep-fig .stage .sec.s4 .card.c39>.pct{grid-area:1/3/2/4}
  .ep-fig .stage .sec.s4 .card.c87>.cap22,.ep-fig .stage .sec.s4 .card.c39>.cap22{
    grid-area:2/1/3/4;margin-top:.7rem}
  /* the rail and arc are position:absolute so they can stack; the reset above makes .gauge
     static, which would anchor them to .stage and blow them up to the full page */
  .ep-fig .stage .gauge{flex:0 0 120px;width:120px;height:60px;margin-bottom:.6rem;position:relative}
  /* Section 5's gauge cards, narrow only. The board seats the icon BESIDE the number
     (icon x 44-90, number 117.9-206.5, both on the row under the arc) - in one column that
     puts the icon between the arc and its own figure. Reorder to icon / arc / number /
     caption, keeping the board's relationship between arc and number: the number group
     starts (117.9-53)/167 = 38.9% across the arc, so it reads as sitting inside the dome.
     The zero-height ::before is the line break that keeps the number off the arc's row. */
  /* --gw is the arc's width; 180 keeps the reference crop's ratio of number height to dome
     width (~0.14) - at 120 the number filled the opening and the % touched the mint. */
  .ep-fig .stage .card.cg{--gw:180px}
  .ep-fig .stage .card.cg .icon{order:1}
  /* The board seats the dome across the middle of the card - 679:247 is 88 in from the
     card's left edge of 552 and 137 from its right, 679:252 is 106/119 - with the icon
     top left and the caption centred under it. Flush left is the one thing that does not
     read like the board's card, at either narrow width. */
  .ep-fig .stage .card.cg .gauge{order:2;flex:0 0 var(--gw);width:var(--gw);
    height:calc(var(--gw) / 2);margin:0 auto .1rem}
  .ep-fig .stage .card.cg::before{content:"";order:3;flex:0 0 100%;height:0}
  /* and pull that line up into the dome's opening - a half-circle is empty below its apex.
     The same negative margin on both keeps their baseline relationship. .num/.pct already
     carry z-index 2, so they paint over the arc.
     .389 was the board's offset, which only existed to clear the icon sitting to the left;
     with the icon moved up, centre the pair under the dome instead: .334 = (gw - (num +
     gap + pct)) / 2 / gw for a two-digit number at 2.2rem. A one- or three-digit value
     would need this re-derived. */
  /* EVERYTHING inside the dome is derived from --gw using board 1305:5's own ratios, so the
     composition holds at any --gw instead of drifting as the generic narrow type scale and
     the fixed dome width pull apart. Against the board's 327 gauge (1305:169):
       num  92 -> .2813    pct 56   -> .1713    num left 94 -> .2875
     The type was reading 8% (num) and 30% (pct) small against the dome, which is what made
     the pair look adrift rather than seated in the opening. Deriving the left offset from
     the board too means a one- or three-digit value no longer needs it re-derived. */
  .ep-fig .stage .card.cg .num{font-size:calc(var(--gw) * .2813);line-height:1.087}
  .ep-fig .stage .card.cg .pct{font-size:calc(var(--gw) * .1713);line-height:1.1429}
  .ep-fig .stage .card.cg .num,.ep-fig .stage .card.cg .pct{margin-top:calc(var(--gw) * -.285)}
  /* both are pulled up over the gauge by the same amount, which cancels the % superscript -
     it needs its own raise on top of that lift */
  /* measured residual against the board's own ratios (pct left .5963, top .1927 of the
     gauge width): the hug-width number leaves the % 1.7% too far right and 1.2% too low,
     because align-items:baseline re-aligns whatever the line-heights say. Nudged directly. */
  .ep-fig .stage .card.cg .pct{margin-top:calc(var(--gw) * -.2966 - .22rem);
    margin-left:calc(var(--gw) * -.0172)}
  .ep-fig .stage .card.cg .num{order:4;
    margin-left:calc((100% - var(--gw)) / 2 + var(--gw) * .2875)}
  .ep-fig .stage .card.cg .pct{order:5}
  .ep-fig .stage .card.cg .cap17,.ep-fig .stage .card.cg .cap22{order:6}
  .ep-fig .stage .bar{height:6px;margin-top:.9rem;border-radius:100px}

  .ep-fig .stage .h1{font-size:clamp(1.9rem,8vw,2.5rem);line-height:1.1}
  .ep-fig .stage .h2{font-size:clamp(1.55rem,6.4vw,2rem);line-height:1.15;margin-bottom:1.2rem}
  .ep-fig .stage .h2.hclose{font-size:1.6rem}   /* 679:239 is 56, like 679:524 */
  .ep-fig .stage .h3{font-size:1.6rem;line-height:1.15}
  .ep-fig .stage .h4{font-size:1.05rem;line-height:1.3;margin-bottom:1rem}   /* 679:160 is 28 */
  .ep-fig .stage .eyebrow{font-size:.78rem;line-height:1.4;margin-bottom:.5rem}
  .ep-fig .stage .thesis{font-size:1rem;line-height:1.45;margin:.9rem 0 2rem}   /* 679:358 is 20 */
  .ep-fig .stage .support{font-size:1.02rem;line-height:1.5;margin:1.4rem 0 0}
  /* The board leaves 44 between the panel and 937:4012 (1972+292 = 2264 -> 2308) and this
     tier is normal flow, so the margin COLLAPSES with the panel's own 24 rather than adding
     to it - it would have to carry the whole 44 itself. Reduced to the 1.5rem every other
     gap in this tier uses; the board's 44 reads long once the section is one column. */
  .ep-fig .stage .sec.s1>.support.nw{margin-top:1.5rem}
  .ep-fig .stage .cap16,.ep-fig .stage .cap17{font-size:.92rem;line-height:1.45;margin-top:.5rem}
  .ep-fig .stage .cap20,.ep-fig .stage .cap22{font-size:1rem;line-height:1.5;margin-top:.5rem}
  /* .cap18 is a misnomer: 937:4198 and 937:4480 are 30 on the board, so it sits with
     .cap30 in the ladder rather than with the 22s */
  .ep-fig .stage .cap18{font-size:1.08rem;line-height:1.45;margin-top:.6rem}
  .ep-fig .stage .cap28{font-size:1.05rem;line-height:1.5;margin-top:.6rem}
  /* the ONLY caption class with no rule here, so it kept its board size (30px) and came out
     LARGER than the .h3 above it (1.6rem), inverting the card's hierarchy. It sits between
     cap28 and cap40 on the board, and does here too. */
  .ep-fig .stage .cap30{font-size:1.08rem;line-height:1.45;margin-top:.6rem}
  .ep-fig .stage .cap40{font-size:1.25rem;line-height:1.35;margin-top:.6rem}
  .ep-fig .stage .num.up{font-size:4.6rem;line-height:1;transform:none}   /* 178: the page's largest */
  .ep-fig .stage .num.big{font-size:2.9rem;line-height:1}
  .ep-fig .stage .num.mid{font-size:1.9rem;line-height:1}   /* board 56, under .h2's 68 */
  .ep-fig .stage .pct{font-size:1.35rem;line-height:1;align-self:start}
  .ep-fig .stage .pct.hpct{margin-top:-.16rem}    /* 679:287 sits 7 above 679:315 */
  .ep-fig .stage .pct.p56{margin-top:-.22rem}     /* 679:65 sits 11 above 679:64 */
  .ep-fig .stage .pct.p36{margin-top:-.34rem}     /* 679:134 sits 14 above 679:133 */
  .ep-fig .stage .pct.p178{margin-top:-.22rem}
  .ep-fig .stage .pct.ctr{transform:none}
  .ep-fig .stage .pole{font-size:1.25rem;line-height:1.2;margin-top:1rem}
  /* .ep-fig .right right-aligns Capability, which on the board sits over its own right-hand
     dotrow. Stacked in one column that leaves the heading adrift from its own words. */
  .ep-fig .stage .pole.right{text-align:left}
  .ep-fig .stage .dotrow{font-size:.85rem;gap:.55rem;margin-top:.2rem}
  .ep-fig .stage .dotrow .dot{width:4px;height:4px}
  .ep-fig .stage .cc{font-size:1.95rem}   /* 679:615 is 64 - just under .h2's 68, above .num.mid's 56 */

  /* The board gives this panel a banded header - a translucent black strip with the panel's
     own top radius, the hex marker hanging at its left, the heading beside it - and rules the
     poles off from the scale. All three are killed by the reset above (.ptop/.mark are images,
     the divider is a .rule), which is what leaves the mobile panel looking flat.
     The strip's export is a 1126x109 rounded rect; stretched to 335 its 14px corners squash to
     4px, so redraw it instead - same rgba(0,0,0,.3), the panel's own 16px radius - and let it
     size itself to however many lines the heading takes. The marker keeps its exported art. */
  /* .ptop, .mark and .h4 are SIBLINGS, not nested, so the band cannot simply wrap them -
     lay the panel out as a grid and let all three share row 1: the strip stretched across it,
     the marker in a marker-width column, the heading in the rest. The row is sized by the
     heading, so the band grows with it however many lines it wraps to. */
  .ep-fig .stage .panel.balance{display:grid;grid-template-columns:auto 1fr;align-items:center;
    padding-top:0}
  .ep-fig .stage .panel.balance>*{grid-column:1/-1}
  .ep-fig .stage .panel.balance .ptop{display:block;position:static;grid-area:1/1/2/3;
    align-self:stretch;width:auto;height:auto;margin:0 -1.25rem;background:rgba(0,0,0,.3);
    border-radius:16px 16px 0 0}
  .ep-fig .stage .panel.balance .ptop>img{display:none}   /* the rect itself, redrawn above */
  /* 679:155 starts at x234.95 and the panel 679:153 at x235 - the rule runs out to the panel's
     own edge, so it has to clear the 1.25rem padding the reflow adds, the way .ptop does */
  .ep-fig .stage .panel.balance .mark{display:block;position:static;grid-area:1/1/2/2;
    width:44px;height:19.3px;margin:1.1rem .6rem 1.1rem -1.25rem}
  .ep-fig .stage .panel.balance .mark>img{width:100%;height:100%}
  .ep-fig .stage .panel.balance .h4{grid-area:1/2/2/3;margin:1.1rem 0}
  /* the one .rule that carries meaning here rather than threading sections together */
  .ep-fig .stage .panel.balance .rule.solid.clay{display:block;position:static;
    width:auto;height:1px;margin:1.25rem 0 0}

  /* ---- the balance widget, rebuilt for one column ----
     On the board this is a physical beam: two weighted pills at the ends of a bar that tips
     about a fulcrum, with the three exposure labels spread beneath it. Stacked naively, the
     pills become a meaningless vertical pair, the knob falls off the track, and .center /
     .right turn the labels into a diagonal staircase. Rebuild it as: pills on one row at the
     two ends, full-width track with the knob on it, labels in a three-column row.
     The tilt and the fulcrum are meaningless without a beam, so both go. */
  /* the raised end rises half the beam width * sin(4.5deg) - ~12px at 375 - so the row above
     needs about twice that, and the labels have to clear the fulcrum's overhang */
  .ep-fig .stage .scale{display:grid;grid-template-columns:1fr auto 1fr;gap:.5rem 0;
    margin:1.9rem 0 1.2rem;position:relative}
  /* The beam still tips and still has its fulcrum - that is the whole metaphor - but the knob
     is the range input's thumb, in a box of its own, so tilting only the beam would leave it
     floating off a sloped track. Rotate BOTH by --tilt about the same world point, the
     track's centre line: the boxes are the same width and both end on it, so origins of
     `50% calc(100% - 5px)` and `50% 50%` land on the same pixel. Dragging still works,
     pointer coordinates map back through the rotation.
     .beam.front stays hidden: it carries the exported handle image, and the styled thumb
     already matches it. Sizes here are the phone's; the tablet tier scales them up. */
  .ep-fig .stage .beam.back{grid-area:1/1/2/4;display:flex;flex-wrap:wrap;align-items:center;
    justify-content:space-between;width:auto;height:auto;
    transform:rotate(var(--tilt,0deg));transform-origin:50% calc(100% - 5px)}
  .ep-fig .stage .scale .slider{transform:rotate(var(--tilt,0deg));transform-origin:50% 50%}
  .ep-fig .stage .beam.back,.ep-fig .stage .scale .slider{
    transition:transform .5s cubic-bezier(.2,.7,.2,1)}
  .ep-fig .stage .beam.front{display:none}
  .ep-fig .stage .scale .fulcrum{display:block;position:static;grid-area:1/1/2/4;
    align-self:end;justify-self:center;width:22px;height:18px;margin:0 0 -14px}
  .ep-fig .stage .scale .fulcrum>img{width:100%;height:100%}
  .ep-fig .stage .pill{width:110px;height:32px;margin:0}
  .ep-fig .stage .pill span{font-size:.75rem;letter-spacing:.06em}
  .ep-fig .stage .track{flex:0 0 100%;height:10px;width:100%;margin-top:.7rem;
    border-radius:100px;box-shadow:inset 0 3px 5px rgba(0,0,0,.29)}
  /* same cell as the pills+track, pinned to its bottom edge, so the knob centres on the
     10px track however tall the row above it turns out to be */
  .ep-fig .stage .slider{grid-area:1/1/2/4;align-self:end;width:100%;height:28px;margin:0 0 -9px}
  .ep-fig .stage .kicker{grid-row:2;font-size:.62rem;letter-spacing:.1em;
    display:block;margin:1.5rem 0 0;width:auto}
  .ep-fig .stage .kicker.center{grid-column:2;text-align:center;padding:0 .4rem}
  .ep-fig .stage .kicker.right{grid-column:3;text-align:right}
  .ep-fig .stage .slider input::-webkit-slider-thumb{width:26px;height:26px;background:#fff5e3;border:3px solid #f96f24}
  .ep-fig .stage .slider input::-moz-range-thumb{width:20px;height:20px;background:#fff5e3;border:3px solid #f96f24}
  .ep-fig .stage .chips{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1rem}
  .ep-fig .stage .chip{width:auto;height:auto}
  .ep-fig .stage .chip button{padding:.5rem .85rem;font-size:.85rem;line-height:1.2;border-radius:100px;white-space:normal}
  .ep-fig .stage .tryone{flex:0 0 100%;margin-bottom:.2rem}

  .ep-fig .stage .closepanel{margin:0;padding:2.5rem clamp(1.25rem,5vw,4rem)}
  .ep-fig .stage .cta{width:auto;margin-top:1.4rem}
  .ep-fig .stage .cta a{display:inline-flex;width:auto;height:auto;padding:.85rem 1.2rem;font-size:.95rem;border-radius:4px}
  .ep-fig .stage .illo.seesaw{margin-top:1.6rem}
  .ep-fig.js .rv{transform:translateY(14px)}
  .ep-fig.js .rv.on{transform:none}
}

/* ============== phone: the loop's three ends become one row of controls ==============
   Below 768 the bracket is gone and the cards stack, so the pills have nothing to sit on -
   they were three centred blocks scattered through the section. They read better as one row
   of buttons at its foot, and a tap on one scrolls to the card it names. */
@container (max-width:767px){
  /* 679:128 and 679:129 are centred on the board and stay centred on desktop and tablet.
     At phone width they wrap to three ragged lines, so they read left here. The two
     .support.center boxes only - NOT .kicker.center, and not the section 5 card
     captions, which the board itself centres. */
  .ep-fig .stage .support.center{text-align:left}
  /* The hero card was a WRAPPING FLEX ROW, so its break point moved with the viewport: at
     375 the illustration filled the line on its own, but at 412 the figure fitted beside it
     and the % and the caption dropped to a line of their own. Place the four parts on an
     explicit grid instead - illustration on top, then the figure, its % and the caption on
     one line, the way the desktop board reads. */
  .ep-fig .stage .hcard{display:grid;grid-template-columns:auto auto 1fr}
  .ep-fig .stage .hcard>.hillo{grid-area:1/1/2/4}
  .ep-fig .stage .hcard>.hnum{grid-area:2/1/3/2}
  .ep-fig .stage .hcard>.hpct{grid-area:2/2/3/3}
  .ep-fig .stage .hcard>.hcap{grid-area:2/3/3/4}
  /* The shared 300px width was set when these three were LANDSCAPE - section 1 was 420x277
     and section 5 a 364.787x247 gear cluster - so each stood about 200 tall. Board 1305:5
     replaced all three with square-ish artwork (280x263, 304x275, 258x258), which at 300
     wide is 271-300 tall and swamps a 375 viewport. Size them by HEIGHT, exactly as section
     4 already is below, so all four illustrations sit in the same band. `:not(.trans)` is
     load-bearing: 679:27's circuit traces are also a `.sec.s5>.illo`. */
  .ep-fig .stage .sec.s1>.illo,.ep-fig .stage .sec.s3>.illo,
  .ep-fig .stage .sec.s5>.illo:not(.trans){width:auto;height:220px;margin-inline:auto}
  .ep-fig .stage .sec.s4{display:grid;grid-template-columns:repeat(3,1fr);gap:1.25rem .4rem}
  .ep-fig .stage .sec.s4>*{grid-column:1/-1}
  .ep-fig .stage .sec.s4>.badge{grid-row:1}
  /* 679:420 is 237x264 - the tallest aspect of any of the illustrations - so at the shared
     300px width it stood 334 tall against section 1's 198 and section 5's 223. Size it by
     HEIGHT here so it sits in the same band as them, and centre it. */
  .ep-fig .stage .sec.s4>.illo{grid-row:2;width:auto;height:220px;
    justify-self:center;margin:0}
  .ep-fig .stage .sec.s4>.h2{grid-row:3}
  .ep-fig .stage .sec.s4>.card{margin:0}
  /* the lead card falls in with the two below it here - icon beside the figure, caption
     under both - rather than keeping the board's icon-on-its-own-row */
  .ep-fig .stage .sec.s4>.card.lead{grid-row:4;display:grid;
    grid-template-columns:auto auto 1fr;align-items:baseline;column-gap:.55rem}
  .ep-fig .stage .sec.s4>.card.lead>.icon{grid-area:1/1/2/2;align-self:center;margin:0}
  .ep-fig .stage .sec.s4>.card.lead>.num{grid-area:1/2/2/3}
  .ep-fig .stage .sec.s4>.card.lead>.pct{grid-area:1/3/2/4}
  .ep-fig .stage .sec.s4>.card.lead>.cap40{grid-area:2/1/3/4;margin:.7rem 0 0}
  .ep-fig .stage .sec.s4>.card.c87{grid-row:5}
  .ep-fig .stage .sec.s4>.card.c39{grid-row:6}
  .ep-fig .stage .sec.s4>.plabel{grid-row:7;width:100%;margin:0;
    padding:.42rem .25rem;text-align:center}
  .ep-fig .stage .sec.s4>.plabel.ctl{grid-column:1}
  .ep-fig .stage .sec.s4>.plabel.cap{grid-column:2}
  .ep-fig .stage .sec.s4>.plabel.cpx{grid-column:3}
  .ep-fig .stage .sec.s4>.plabel>span{font-size:.72rem;letter-spacing:.01em}
  .ep-fig .stage .sec.s4>.support{grid-row:8}
  /* same arithmetic as the tablet tier: 2.5rem clears section 5's floor, 2.5rem the
     closing section's top, and the last 1rem lands the dots on the panel */
  /* 757:4 ran straight into the first card here - the section is normal flow at this width
     and .support carries no bottom margin - so give it the same 1.5rem the cards use
     between themselves. */
  /* 951:4601 and 757:4 both introduce a block rather than close a section, and .support
     carries no bottom margin - each sat on the thing below it. Same 1.5rem the cards use. */
  .ep-fig .stage .sec.s1>.support:not(.nw),
  .ep-fig .stage .sec.s5>.support{margin-bottom:1.5rem}
  /* and close the gap the last card's own 1.5rem left above the traces: -1.5rem collapses
     against it to 0, which is where the board has them (cards end 7700, 679:27 starts
     7709). */
  .ep-fig .stage .sec.s5>.illo.trans{margin:-1.5rem auto -6rem}

    .ep-fig .stage .closepanel .cta{width:fit-content;margin-inline:auto}

}

/* ============== tablet: one column is too few for this width ==============
   The narrow layout above is a phone layout, and below 1280 it was the ONLY fallback, so a
   tablet got 780px-wide single-column cards in an 820px column. The desktop canvas can't just
   be scaled down to fill the gap - at 1024 --u would be 0.64 and the 17px captions would
   render at 11px - so keep the narrow tier's readable fixed sizes and restore only the
   COLUMN COUNTS the board uses: 3 up for the hero stats, section 1's drivers, section 2's
   minis and section 3's cards; 2 up for sections 4 and 5.
   Each group's parent is the section itself, sharing it with headings, rules and panels, so
   the section becomes the grid and everything that is not a card spans the full width. */
@container (min-width:768px) and (max-width:1279px){
  .ep-fig .stage .sec{max-width:1040px}
  .ep-fig .stage .sec.close{max-width:none}

  .ep-fig .stage .wrap.herostats,.ep-fig .stage .panel.p1,.ep-fig .stage .panel.p2b,
  .ep-fig .stage .sec.s1,.ep-fig .stage .sec.s2,.ep-fig .stage .sec.s3,
  .ep-fig .stage .sec.s4,.ep-fig .stage .sec.s5{display:grid;gap:1.25rem;align-items:start}
  .ep-fig .stage .wrap.herostats,.ep-fig .stage .panel.p1,.ep-fig .stage .panel.p2b,
  .ep-fig .stage .sec.s2{grid-template-columns:repeat(3,1fr)}
  /* six, so the two statistics can take a half each and Control/Capability the full width */
  /* ONE 8-column grid across sections 1, 3, 4 and 5 so the illustration/heading pairing
     is identical in all of them - it was 272|436 in s1, 250|478 in s3 and 354|354 in s4
     and s5, which left the heading 72, 20, 188 and 167 from its illustration. 1/4 + 4/-1
     is section 1's split (the board's 420:666); 1/5 + 5/-1 leaves every side-by-side pair
     at the same 354 it already had, since 4 columns + 3 gaps equals the old half. */
  .ep-fig .stage .sec.s1,.ep-fig .stage .sec.s3,
  .ep-fig .stage .sec.s4,.ep-fig .stage .sec.s5{grid-template-columns:repeat(8,1fr)}

  /* only the repeated items take a column; every heading, badge, rule, panel and support
     line still runs the full width. The illustration/heading pairs are excluded here and
     placed explicitly below - a :not() chain rather than a later override, because
     `>:not(.card)` already out-specifies any `.sec.sN .illo` rule. */
  .ep-fig .stage .panel.p1>:not(.drv),.ep-fig .stage .sec.s2>:not(.mini),
  .ep-fig .stage .sec.s1>:not(.illo):not(.h2),
  .ep-fig .stage .sec.s3>:not(.card):not(.illo):not(.h2),
  .ep-fig .stage .sec.s4>:not(.card):not(.illo):not(.h2):not(.bracket):not(.plabel):not(.poly),
  .ep-fig .stage .sec.s5>:not(.card):not(.illo):not(.h2):not(.support){grid-column:1/-1}

  /* ---- illustration beside its heading, as on the board ----
     Stacked, each illustration eats a whole screen before its own heading arrives. The board
     pairs them and alternates the side: art LEFT in sections 1, 3 and 5, RIGHT in 4.
     Every row is numbered explicitly - with a mix of spanning and single-column items,
     leaving any of them to auto-placement puts the cards on the wrong rows. */
  .ep-fig .stage .sec.s1>.badge,.ep-fig .stage .sec.s3>.badge,
  .ep-fig .stage .sec.s4>.badge,.ep-fig .stage .sec.s5>.badge{grid-row:1}
  .ep-fig .stage .sec.s1>.illo{grid-row:2;grid-column:1/4;max-width:420px}
  .ep-fig .stage .sec.s1>.h2{grid-row:2;grid-column:4/-1}
  /* 951:4601 sits between the heading and the panel on the board. Both it and the closing
     line are `.support`, so one row rule gave them the same row and dropped the new line
     BELOW the panel here. Tell them apart by the closing line's `nw`. */
  /* 951:4601 is x699 w666 on the board - the SAME column as its own heading at 699, exactly
     how 757:4 sits under section 5's. It was running full width here because the section's
     :not() chain spans everything that is not the illo or the h2.
     The illustration spans both rows so it centres on the heading + line pair, as s5's does
     do. The grid gap alone gave 20 against the 28 this tier uses everywhere else. */
  .ep-fig .stage .sec.s1>.support:not(.nw){grid-row:3;grid-column:4/-1;margin-top:0;margin-bottom:.5rem}
  .ep-fig .stage .sec.s1>.illo{grid-row:2/4}
  .ep-fig .stage .sec.s1>.panel.p1{grid-row:4}
  /* The panel's own 1.5rem bottom margin ADDS to the grid's 1.25rem row gap here rather
     than collapsing into it, so the line under a panel sat 44 below it in s1 and 66 in s3
     (24 + 20 + the line's own 22.4). Drop the panel's margin in these two and let a small
     one on the line set the gap: 28, in line with section 4's 27. */
  .ep-fig .stage .sec.s1>.panel.p1{margin-bottom:0}
  .ep-fig .stage .sec.s1>.support.nw{grid-row:5;margin-top:.5rem}

  .ep-fig .stage .sec.s3>.illo{grid-row:2;grid-column:1/4;max-width:378px}
  .ep-fig .stage .sec.s3>.h2{grid-row:2;grid-column:4/-1}
  /* Section 3's three cards read icon / figure / caption, but the third card's figure is a
     two-line "Control Capability" heading where the others have a number, so the rows differ
     in height and the captions drift ~20px apart. Share the tracks: the cards span three of
     the section's rows as subgrid, so icon, figure and caption each get one line across all
     three. (The board itself offsets them - it draws these as an overlapping staircase - so
     there is no board geometry to copy here, only the row they now sit in.) */
  .ep-fig .stage .sec.s3>.card{grid-row:3/6;display:grid;grid-template-rows:subgrid;
    grid-template-columns:auto auto 1fr;align-items:baseline}
  .ep-fig .stage .sec.s3>.card>.icon{grid-area:1/1/2/4}
  .ep-fig .stage .sec.s3>.card>.num{grid-area:2/1/3/2}
  .ep-fig .stage .sec.s3>.card>.pct{grid-area:2/2/3/3}
  .ep-fig .stage .sec.s3>.card>.h3{grid-area:2/1/3/4}
  .ep-fig .stage .sec.s3>.card>.cap17{grid-area:3/1/4/4}
  /* The two statistics share the row - and the shared tracks above, so their captions line up.
     Control/Capability is the takeaway from them, not a third of the same kind (the board's
     feedback note 687:1180), so it drops to its own full-width row rather than being squeezed
     into a third of the width, where its sentence broke over seven lines. */
  .ep-fig .stage .sec.s3>.card.c80{grid-column:1/5}
  .ep-fig .stage .sec.s3>.card.c85{grid-column:5/-1}
  .ep-fig .stage .sec.s3>.card.ccc{grid-row:6;grid-column:1/-1;
    grid-template-rows:auto auto auto;margin-bottom:1.75rem}
  .ep-fig .stage .sec.s3>.card.ccc>.h3{grid-area:2/1/3/4}
  .ep-fig .stage .sec.s3>.card.ccc>.cap30{grid-area:3/1/4/4}
  /* row 7 was the balance panel's; with it gone the line moves up rather than leaving an
     empty row the grid still charges two gaps for */
  .ep-fig .stage .sec.s3>.card.ccc{margin-bottom:0}
  .ep-fig .stage .sec.s3>.support{grid-row:7;margin-top:.5rem}

  /* ---- section 4 keeps the board's arrangement, with one tablet exception ----
     The loop, the wide statistic across the top of it, the two halves beneath, and a pill
     straddling each edge of the bracket exactly where 679:559 / 679:565 / 679:566 sit. The
     old rules here named `.card.c92`, which this build never emits (it is `.card.lead`), so
     nothing was placed and the section fell apart. The six notches are dropped: they are
     14x16 marks pinned to board coordinates on the bracket, with nothing to pin to here.
     THE EXCEPTION: the board puts this heading left and the sparkle right, the opposite way
     round to sections 1, 3 and 5. On the 1600 canvas that reads as variety; in a two-column
     tablet grid it just reads as the one section that breaks the rhythm, so the pair is
     swapped here to match the others. Tablet only - desktop still follows the board. */
  .ep-fig .stage .sec.s4>.h2{grid-row:2;grid-column:4/-1}
  .ep-fig .stage .sec.s4>.illo{grid-row:2;grid-column:1/4}
  /* align-self:stretch, NOT the section's align-items:start - a spanning item that packs to
     the start collapses to its own (empty) content height, which here is just the 2px border */
  .ep-fig .stage .sec.s4>.bracket{display:block;grid-row:3/7;grid-column:1/-1;z-index:0;align-self:stretch;
    border-width:2px;border-radius:32px}
  .ep-fig .stage .sec.s4>.plabel{z-index:2;justify-self:center;align-self:center;margin-inline:0}
  .ep-fig .stage .sec.s4>.plabel.ctl{grid-row:3;grid-column:1/-1;transform:translateY(-50%)}
  /* inset from the loop on the outer edges only - the inner gap is the grid's own */
  .ep-fig .stage .sec.s4>.card.lead{grid-row:4;grid-column:1/-1;margin-inline:1.25rem;
    display:grid;grid-template-columns:auto auto 1fr;align-items:baseline;column-gap:.4rem}
  .ep-fig .stage .sec.s4>.card.lead>.icon{grid-area:1/1/2/4;align-self:start}
  .ep-fig .stage .sec.s4>.card.lead>.num{grid-area:2/1/3/2}
  .ep-fig .stage .sec.s4>.card.lead>.pct{grid-area:2/2/3/3}
  .ep-fig .stage .sec.s4>.card.lead>.cap40{grid-area:2/3/3/4;margin:0;align-self:center}
  .ep-fig .stage .sec.s4>.card.c87{grid-row:5;grid-column:1/5;margin-left:1.25rem}
  .ep-fig .stage .sec.s4>.card.c39{grid-row:5;grid-column:5/-1;margin-right:1.25rem}
  .ep-fig .stage .sec.s4>.plabel.cap{grid-row:6;grid-column:1/5;transform:translateY(50%)}
  .ep-fig .stage .sec.s4>.plabel.cpx{grid-row:6;grid-column:5/-1;transform:translateY(50%)}
  /* .5rem here reads 11 - section 4's pill row ends close to the line's own row start, so
     unlike s1 and s3 the grid gap contributes almost nothing and the margin carries it */
  .ep-fig .stage .sec.s4>.support{grid-row:7;margin-top:1.5rem}

  /* The board stacks the heading and its support line in ONE right-hand column - both start
     at x=610 (board 821) - with the illustration beside them at 265-523, spanning the pair.
     Tablet ran the line full width under both instead, which stranded the heading in the
     middle of the illustration's row with empty space above and below it. */
  .ep-fig .stage .sec.s5>.illo{grid-row:2/4;grid-column:1/4;max-width:325px}
  /* ONE expression for all four, placed after the per-section max-widths above so it
     governs them. Section 3's was the one that read correctly on tablet - 207 tall at 768,
     284 at 1024 - so the clamp tracks it and the others come down to meet it (s5 was 325
     and s1 272). Sized by HEIGHT, not width, because the four aspects differ: section 4 is
     PORTRAIT (0.898), so at an equal width it is the tallest of the set, which is exactly
     why it loomed at only 219 wide. max-width:none lets the height govern - the widths it
     implies (309/321/260/290 at the 290 ceiling) all sit inside their columns.
     `:not(.trans)` is load-bearing: 679:27's traces are also a `.sec.s5>.illo`. */
  .ep-fig .stage .sec.s5>.h2{grid-row:2;grid-column:4/-1}
  /* 757:4 sits under the heading and ABOVE the cards on the board, so it takes row 3 and
     everything below it shifts down one. The rule below used to name row 5 and match
     nothing at all - section 4's support is the one at 6696, not section 5's. */
  .ep-fig .stage .sec.s5>.support{grid-row:3;grid-column:4/-1;margin-top:0}
  .ep-fig .stage .sec.s5>.card{grid-row:4;grid-column:span 4}
  /* NOT the section's illustration slot - `.sec.s5>.illo` was matching this too and dropping
     it on top of the illustration. 679:27 is the thread into the closing panel: it runs full width
     BENEATH the cards on the board (7654, just under their 7645), so it does here too. */
  .ep-fig .stage .sec.s5>.illo.trans{grid-row:5;grid-column:1/-1;
    /* the board does NOT run this the full width: 679:27 spans 470-1086 against the cards'
       own 227-1368, i.e. just over half of them. Full width here made it half again as
       tall as the cards it hangs from. */
    width:56%;max-width:none;justify-self:center;align-self:start;
    /* -2.5rem clears section 5's own bottom padding and -2.5rem the closing section's top,
       and the last 1rem lands the lower dots ON the panel the way 679:27 does (it runs to
       7849.5 against the panel's 7836) */
    /* the grid's own 1.25rem gap is far more than the board leaves: the cards end at 7645
       and 679:27 starts at 7654, 9u - which at this thread's 408/616 scale is ~6px. */
    margin:-.875rem 0 -6rem}

  /* the paired illustrations size to their column instead of the phone tier's centred 300px */
  .ep-fig .stage .sec.s1>.illo,.ep-fig .stage .sec.s3>.illo,
  .ep-fig .stage .sec.s4>.illo,.ep-fig .stage .sec.s5>.illo,
  .ep-fig .stage .closepanel .illo.seesaw{width:100%;margin:0;align-self:center}

  /* MUST sit after the width:100% above, which is what was really sizing these: section 3
     and section 5 only looked right because their columns happen to match their aspect,
     while section 1 stretched to 272 (aspect wants 221) and section 4 to 354 (wants 186).
     Set the WIDTH and let `.illo`'s own aspect-ratio give the height. Not `width:auto` -
     grid stretch wins that; not a calc'd `height` - a division inside calc() does not
     survive var() substitution here. A literal per-section ratio has neither problem.
     --illh is the shared height: section 3's, the one that already read correctly. */
  .ep-fig .stage .sec.s1>.illo,.ep-fig .stage .sec.s3>.illo,
  .ep-fig .stage .sec.s4>.illo,.ep-fig .stage .sec.s5>.illo:not(.trans){
    --illh:clamp(190px,27cqw,290px);height:auto;max-width:none}
  .ep-fig .stage .sec.s1>.illo{width:calc(var(--illh) * 1.0646)}
  .ep-fig .stage .sec.s3>.illo{width:calc(var(--illh) * 1.1080)}
  .ep-fig .stage .sec.s4>.illo{width:calc(var(--illh) * 0.8977)}
  .ep-fig .stage .sec.s5>.illo:not(.trans){width:var(--illh)}
  .ep-fig .stage .sec.s3>.h2,.ep-fig .stage .sec.s4>.h2{align-self:center}
  /* Neither s1's nor s5's heading is alone in its column - 951:4601 and 757:4 sit under
     them - so the heading goes to the bottom of its row and the line to the top of the next.
     Centred, the heading floated in a row the spanning illustration had stretched, leaving
     138 between it and its own line where s5 reads 39. */
  /* and drop the heading's own 1.2rem, which was adding to the grid's row gap: the board
     leaves 20 under 937:4184 (1572 -> 1592) and 23 under 937:4008 (6472 -> 6495), where
     19.2 + 20 was rendering 39. The row gap alone is the board's figure. */
  .ep-fig .stage .sec.s1>.h2,.ep-fig .stage .sec.s5>.h2{align-self:end;margin-bottom:0}
  .ep-fig .stage .sec.s1>.support:not(.nw),
  .ep-fig .stage .sec.s5>.support{align-self:start}

  /* section 2's donut belongs beside its statistic, not stacked above it (board: 352 | 397) */
  .ep-fig .stage .panel.p2{display:grid;grid-template-columns:auto 1fr;gap:1.5rem;
    align-items:center}
  .ep-fig .stage .panel.p2 .illo.donut{width:min(40vw,300px);margin:0}

  /* ---- the balance widget back to the board's composition ----
     The phone tier stacks the two poles and drops the beam, which at this width just looks
     like a different design. Restore: Control left / Capability right over their own dot
     rows, the fulcrum under the track, and the tilt.
     The tilt is the fiddly one - .beam.back carries the pills and track, but the knob is the
     range input's thumb, which lives in a separate box and would sit off a tilted track. So
     rotate BOTH by the same --tilt about the same world point: the track's centre line. The
     two boxes are the same width and both end on that line, so origins of
     `50% calc(100% - 5px)` and `50% 50%` land on the same pixel. Dragging still works -
     pointer coordinates map back through the rotation. */
  .ep-fig .stage .poles{display:grid;grid-template-columns:1fr 1fr;column-gap:1.5rem}
  .ep-fig .stage .poles>:nth-child(1){grid-area:1/1}
  .ep-fig .stage .poles>:nth-child(2){grid-area:2/1}
  .ep-fig .stage .poles>:nth-child(3){grid-area:1/2}
  .ep-fig .stage .poles>:nth-child(4){grid-area:2/2;justify-content:flex-end}
  .ep-fig .stage .pole.right{text-align:right}

  /* Headroom for the tilt. The board leaves 92u between the dot rows and the pills on a 733u
     beam (12.5%); the reflow left only 40px on a 960px beam (4.2%), so at a dragged 0/100 the
     raised pill came within 3px of the dot row. The rise is half the beam width * sin(4.5),
     ~37px here, so the row needs ~2x that. */
  .ep-fig .stage .scale{margin-top:2.6rem}
  /* the beam mechanism is shared with the phone tier; only the scale changes - a 960px beam
     rises ~37px against the phone's ~12px */
  .ep-fig .stage .scale .fulcrum{width:34px;height:28px;margin:0 0 -24px}
  /* The board's 4.5deg is derived from ITS spacing - 366u of arm against 29u of travel. Here
     the arm is ~480px at the widest tablet, so 4.5deg drops the knob ~38px and the labels had
     to be pushed 2.9rem clear of it. The labels are the thing being read, so spend the budget
     there instead: 2.5deg drops the knob ~21px, which 1.5rem clears. */
  .ep-fig .stage .scale{--tilt-max:2.5}
  .ep-fig .stage .scale .kicker{margin-top:1.5rem}

  /* ---- the closing panel, laid out as the board lays it out ----
     679:239 / 679:240 across the top, the seesaw 679:494 as a band beneath them (327-968 of
     the panel's 235-1365, so left-aligned at ~57%), the rule 679:527, then the lower block:
     679:524 / 679:525 / 679:526 down the left and the racks 679:361 beside them on the right
     (x1041 of 1130). Every row is numbered - the racks arrive after the second caption in the
     DOM, so auto-placement drops them between the copy and the CTA, full width, which is what
     made this read as broken. */
  .ep-fig .stage .closepanel{display:grid;grid-template-columns:1fr auto;gap:0 1.5rem;
    align-items:start}
  .ep-fig .stage .closepanel>*{grid-column:1/-1}
  .ep-fig .stage .closepanel .rule.solid.half{display:block;position:static;
    width:auto;height:1px;margin:1.4rem 0}
  .ep-fig .stage .closepanel>.h2.hclose{grid-row:1}
  .ep-fig .stage .closepanel>.cap18{grid-row:2;grid-column:1/-1}
  .ep-fig .stage .closepanel>.illo.seesaw{grid-row:3;grid-column:1/-1;
    width:57%;min-width:260px;margin:.6rem 0 0;justify-self:start;align-self:start}
  .ep-fig .stage .closepanel>.rule.solid.half{grid-row:4}
  .ep-fig .stage .closepanel>.h3.sbd{grid-row:5;grid-column:1}
  .ep-fig .stage .closepanel>.h3.sbd~.cap18{grid-row:6;grid-column:1}
  .ep-fig .stage .closepanel>.cta{grid-row:7;grid-column:1;justify-self:start}

  /* Three hero cards across leaves each one ~229px, and .hcap's 55% basis then squeezes the
     caption into 106px beside the number - 3 lines on two cards, 6 on the third. Stack it
     under the number instead, where it gets the card's full width. */
  .ep-fig .stage .hcap{flex:0 0 100%;align-self:auto;margin-top:.35rem}

  /* gap replaces the stacking margins, and cards match heights across a row */
  .ep-fig .stage .hcard,.ep-fig .stage .drv,.ep-fig .stage .mini,
  .ep-fig .stage .sec.s3 .card,.ep-fig .stage .sec.s4 .card,
  .ep-fig .stage .sec.s5 .card{margin:0;align-self:stretch}

  /* ---- align the repeated items to each other, not just their own box ----
     Three separate causes, all invisible in one column:
     (a) the phone tier wraps these in a flex box, and equal-height cards + the default
         align-content:stretch then SPREAD the wrapped lines by whatever slack each card
         has, so a two-line caption shifts that card's number 5-7px off its neighbours;
     (b) a driver's bar must sit on the row's baseline (the board puts all three at y1949),
         which top-packing alone would not do - it needs a row that absorbs the slack;
     (c) the three hero illustrations have different aspect ratios (1.65 / 1.23 / 1.67), so
         they end at different heights and push their numbers apart. Only a shared row track
         fixes that, so the cards become subgrid rows of .herostats. Where subgrid is
         unsupported the rule is dropped and the cards fall back to today's behaviour. */
  .ep-fig .stage .mini{align-content:flex-start}
  /* the divider and the closing line sit inside the panel on the board, so they do here too */
  .ep-fig .stage .panel.p2b>:not(.mini){grid-column:1/-1}
  .ep-fig .stage .panel.p2b>.rule.solid.faint{display:block;position:static;
    width:100%;height:1px;margin:0}
  .ep-fig .stage .panel.p2b>.support{margin:0}

  .ep-fig .stage .panel.p1 .drv{display:grid;gap:0 .3rem;align-items:baseline;
    grid-template-columns:auto auto 1fr;grid-template-rows:auto auto 1fr auto}
  .ep-fig .stage .panel.p1 .drv .icon{grid-area:1/1/2/4}
  .ep-fig .stage .panel.p1 .drv .num{grid-area:2/1/3/2}
  .ep-fig .stage .panel.p1 .drv .pct{grid-area:2/2/3/3}
  .ep-fig .stage .panel.p1 .drv .cap17{grid-area:3/1/4/4}
  .ep-fig .stage .panel.p1 .drv .bar{grid-area:4/1/5/4;align-self:end}

  .ep-fig .stage .hcard{display:grid;grid-row:span 3;grid-template-rows:subgrid;
    grid-template-columns:auto auto 1fr;align-items:baseline}
  /* NOT justify-self:start - the target illustration's parts are all absolutely positioned,
     so shrink-to-fit gives it zero width and, through aspect-ratio, zero height. Let it
     stretch to the column the way flex-basis:100% did. */
  .ep-fig .stage .hcard .hillo{grid-area:1/1/2/4;align-self:end}
  .ep-fig .stage .hcard .hnum{grid-area:2/1/3/2}
  .ep-fig .stage .hcard .hpct{grid-area:2/2/3/3}
  .ep-fig .stage .hcard .hcap{grid-area:3/1/4/4}
}

