/* Reviewer supplement page. Deliberately dependency-free: no webfonts, no CDN, no framework, so the
   page renders identically from file:// on a machine with no network. */
:root{
  --ink:#1a1f26; --sub:#5b6673; --line:#dfe4ea; --bg:#ffffff; --panel:#f7f9fb;
  --ours:#1f6fb2; --alt:#c2721c; --gold:#a07c12; --bad:#c53030; --ok:#2f7a4d;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  /* Motion tokens. CSS's built-in easings are too soft to feel deliberate, so entrances and movement use
     stronger custom curves; hovers and colour changes keep plain `ease`, which is what they want. */
  --ease-out:cubic-bezier(0.23,1,0.32,1);       /* entering / exiting: starts fast, feels answered */
  --ease-in-out:cubic-bezier(0.77,0,0.175,1);   /* moving on screen */
  --t-press:140ms;   /* button feedback */
  --t-hover:160ms;   /* hover affordance */
  --t-enter:220ms;   /* small element entering */
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--bg);color:var(--ink);
  font:16px/1.62 "Iowan Old Style","Palatino Linotype",Palatino,Georgia,"Times New Roman",serif}
.wrap{max-width:1120px;margin:0 auto;padding:0 22px}
a{color:var(--ours)}

/* ---------- header / product hero ----------
   No webfonts by design: the page must render identically from file:// with no network, so the display
   face is a system stack rather than an @import. */
header{border-bottom:1px solid var(--line);padding:52px 0 26px;position:relative;overflow:hidden;
  background:
    radial-gradient(1100px 420px at 82% -8%,rgba(31,111,178,.10),transparent 62%),
    radial-gradient(760px 380px at 4% 8%,rgba(194,114,28,.07),transparent 60%),
    linear-gradient(180deg,#fbfcfd 0%,#fff 78%)}
.hero{display:grid;grid-template-columns:minmax(0,1.32fr) minmax(0,1fr);gap:44px;align-items:center;
  padding-bottom:30px}
.eyebrow{margin:0 0 14px;font:700 11.5px/1 var(--mono);letter-spacing:.13em;text-transform:uppercase;
  color:var(--ours)}
h1{margin:0 0 22px;letter-spacing:-.6px}
h1 .mark{display:block;font-size:60px;line-height:.98;font-weight:600;letter-spacing:-1.6px;
  background:linear-gradient(135deg,#12456e 0%,#1f6fb2 52%,#2f93c9 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent}
h1 .tail{display:block;margin-top:11px;font-size:23px;line-height:1.3;font-weight:400;color:var(--ink)}

.authors{display:flex;flex-wrap:wrap;gap:3px 17px;margin:0 0 9px;padding:0;
  font-size:15.5px;font-weight:600;letter-spacing:-.1px}
.authors .au{white-space:nowrap}
.authors sup{font-size:9.5px;font-weight:700;color:var(--ours);margin-left:1px;vertical-align:super}
.affil{display:flex;flex-wrap:wrap;gap:2px 16px;margin:0 0 8px;
  font:11.5px/1.55 var(--mono);color:var(--sub)}
.affil sup{color:var(--ours);font-weight:700;margin-right:1px}
.anote{margin:0 0 18px;font:11.5px/1.5 var(--mono);color:var(--sub)}

/* ---------- paper / code links ----------
   Press feedback and a hover-gated lift, per the motion tokens above: these are the two things a visitor
   is most likely to click, so they should answer immediately. */
.links{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 18px}
.lk{display:inline-flex;align-items:center;gap:9px;text-decoration:none;
  padding:11px 16px;border-radius:10px;border:1px solid var(--line);background:#fff;
  color:var(--ink);font:600 14px/1 var(--mono);letter-spacing:-.1px;
  box-shadow:0 1px 2px rgba(26,31,38,.04);
  transition:background var(--t-hover) ease,border-color var(--t-hover) ease,
    box-shadow var(--t-hover) ease,transform var(--t-press) var(--ease-out)}
.lk svg{width:17px;height:17px;flex:none}
.lk .sub2{color:var(--sub);font-weight:400;font-size:12px}
.lk.pri{background:var(--ours);border-color:var(--ours);color:#fff;
  box-shadow:0 2px 10px rgba(31,111,178,.22)}
.lk.pri .sub2{color:rgba(255,255,255,.78)}
@media (hover:hover) and (pointer:fine){
  .lk:hover{transform:translateY(-1px);box-shadow:0 4px 14px rgba(26,31,38,.12);background:var(--panel)}
  .lk.pri:hover{background:#1a5f9b;border-color:#1a5f9b;box-shadow:0 5px 18px rgba(31,111,178,.30)}
}
.lk:active{transform:scale(0.97)}
@media (max-width:420px){.lk{flex:1 1 100%;justify-content:center}}
.anote sup{color:var(--ours)}

.heroArt{position:relative;aspect-ratio:3/4;display:flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:16px;overflow:hidden;background:#fff;
  box-shadow:0 14px 40px rgba(26,31,38,.10),0 2px 6px rgba(26,31,38,.05)}
.heroGlow{position:absolute;inset:6% 10%;border-radius:50%;
  background:radial-gradient(circle,rgba(31,111,178,.16) 0%,rgba(31,111,178,0) 68%)}
.heroVids{position:relative;width:100%;height:100%}
/* the decomposition half of the hero: the same solo layers section 04 uses, pushed apart along Z */
.heroStack{position:absolute;left:50%;top:50%;translate:-50% -50%;width:56%;
  transform-style:preserve-3d;opacity:0;transition:opacity .5s ease;pointer-events:none}
.heroStack.on{opacity:1}
.heroStack img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;
  backface-visibility:hidden;filter:drop-shadow(-5px 3px 7px rgba(26,31,38,.20))}
.heroArt{perspective:1200px;perspective-origin:50% 45%}
.heroVids video{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;
  opacity:0;transition:opacity .9s ease}
.heroVids video.on{opacity:1}
.heroTag{position:absolute;bottom:2%;left:50%;transform:translateX(-50%);
  font:600 11px/1 var(--mono);color:var(--sub);background:rgba(255,255,255,.9);
  border:1px solid var(--line);border-radius:999px;padding:6px 12px;white-space:nowrap}

@media (max-width:900px){
  .hero{grid-template-columns:1fr;gap:26px}
  h1 .mark{font-size:44px}
  h1 .tail{font-size:20px}
  .heroArt{max-width:330px;margin:0 auto}
}
@media (max-width:600px){
  header{padding:34px 0 20px}
  h1 .mark{font-size:36px;letter-spacing:-1px}
  .authors{gap:3px 12px;font-size:14px}
}
@media (prefers-reduced-motion:reduce){
  .heroVids video{transition:none}
}
.badge{font:600 12.5px/1 var(--mono);color:var(--sub);background:var(--panel);
  border:1px solid var(--line);border-radius:999px;padding:7px 12px;letter-spacing:.2px;
  white-space:nowrap}
.note{margin:20px 0 0;padding:13px 16px;background:#fffdf5;border:1px solid #ecdfae;
  border-left:3px solid var(--gold);border-radius:5px;font-size:14.5px;color:#5b4c1c}

/* ---------- section ---------- */
section{padding:46px 0;border-bottom:1px solid var(--line)}
h2{font-size:23px;margin:0 0 6px;letter-spacing:-.1px}
h2 .n{color:var(--sub);font:600 14px/1 var(--mono);margin-right:10px;vertical-align:2px}
.lede{color:var(--sub);margin:0 0 24px;max-width:76ch;font-size:15.5px}

/* ---------- explorer ---------- */
.explorer{display:grid;grid-template-columns:172px minmax(0,1fr);gap:26px;align-items:start}
/* The group tabs are a THIRD child of this two-column grid. Without spanning both columns they take the
   first cell, push the picker into the second, and the stage wraps onto a new row in the 172px column --
   which collapsed the viewport to 2px wide and left the video with no box at all. */
#exGrp{grid-column:1 / -1;margin:0 0 2px}
.stage{min-width:0}
.picker{display:flex;flex-direction:column;gap:7px;max-height:640px;overflow-y:auto;padding-right:6px}
.picker button{display:flex;gap:9px;align-items:center;text-align:left;cursor:pointer;
  background:#fff;border:1px solid var(--line);border-radius:7px;padding:6px 8px;font:inherit;
  font-size:12.5px;color:var(--ink);transition:border-color var(--t-hover) ease,background var(--t-hover) ease,transform var(--t-press) var(--ease-out)}
.picker button:active{transform:scale(0.985)}
.picker button[aria-selected=true]{border-color:var(--ours);background:#eff6fc;
  box-shadow:inset 0 0 0 1px var(--ours)}
.picker img{width:34px;height:46px;object-fit:contain;background:#fff;border-radius:3px;flex:none}
.picker .pn{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.picker .pm{color:var(--sub);font:11px/1.3 var(--mono)}

.stage{display:grid;grid-template-columns:1fr 300px;gap:24px;align-items:start}
.viewport{position:relative;background:var(--panel);border:1px solid var(--line);border-radius:9px;
  display:flex;align-items:center;justify-content:center;min-height:430px;overflow:hidden}
/* two frames stacked so the top one can be faded in over the bottom: this is what turns a discrete
   frame sequence into continuous motion. The stack sizes itself to the base image. */
.stack{position:relative;display:inline-block;line-height:0}
.stack img{max-width:100%;max-height:600px;display:block}
.stack img.ov{position:absolute;inset:0;width:100%;height:100%;opacity:0;
  will-change:opacity;pointer-events:none}

.feat{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin:0 0 26px}
.feat figure{margin:0;position:relative;border:1px solid var(--line);border-radius:9px;overflow:hidden;
  background:var(--panel);cursor:pointer;transition:box-shadow var(--t-hover) ease,transform var(--t-hover) var(--ease-out)}
@media (hover:hover) and (pointer:fine){
  .feat figure:hover{box-shadow:0 4px 18px rgba(26,31,38,.15);transform:translateY(-2px)}
}
.feat figure:active{transform:scale(0.99)}
.feat img,.feat video{width:100%;aspect-ratio:3/4;object-fit:contain;display:block;
  background:var(--panel)}
.feat img.ov{position:absolute;inset:0;height:auto;opacity:0;will-change:opacity;pointer-events:none}
.feat figcaption{position:relative;padding:7px 9px 9px;font:11.5px/1.4 var(--mono);color:var(--sub);
  border-top:1px solid var(--line);background:#fff}
.feat figcaption b{display:block;color:var(--ink);font-weight:600;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
@media (max-width:760px){.feat{grid-template-columns:repeat(2,1fr)}}
.viewport .tag{position:absolute;left:11px;top:10px;font:600 11.5px/1 var(--mono);color:var(--sub);
  background:rgba(255,255,255,.9);border:1px solid var(--line);border-radius:5px;padding:5px 8px}
.ctl{border:1px solid var(--line);border-radius:9px;padding:16px 16px 18px;background:#fff}
.axes{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:16px}
.axes button{cursor:pointer;transition:background var(--t-hover) ease,border-color var(--t-hover) ease,
  color var(--t-hover) ease,transform var(--t-press) var(--ease-out);
  font:600 12.5px/1 var(--mono);border:1px solid var(--line);background:#fff;
  color:var(--sub);border-radius:6px;padding:7px 10px}
.axes button[aria-selected=true]{background:var(--ours);border-color:var(--ours);color:#fff}
.axes button:active{transform:scale(0.97)}
label.sl{display:block;font:600 12px/1 var(--mono);color:var(--sub);margin:0 0 7px;
  text-transform:uppercase;letter-spacing:.4px}
input[type=range]{width:100%;margin:0 0 4px}
.vals{display:flex;justify-content:space-between;font:12px/1 var(--mono);color:var(--sub)}
.cur{text-align:center;font:600 20px/1.2 var(--mono);color:var(--ink);margin:12px 0 2px}
.curlab{text-align:center;font:12px/1 var(--mono);color:var(--sub);margin-bottom:14px}
.row{display:flex;gap:8px}
.btn{flex:1;cursor:pointer;font:600 13px/1 var(--mono);border:1px solid var(--line);background:#fff;
  color:var(--ink);border-radius:6px;padding:9px 10px}
.btn{transition:background var(--t-hover) ease,border-color var(--t-hover) ease,
  transform var(--t-press) var(--ease-out)}
.btn:active{transform:scale(0.97)}
.btn.on{background:var(--ours);border-color:var(--ours);color:#fff}
.facts{margin-top:16px;padding-top:14px;border-top:1px solid var(--line);
  font:12.5px/1.75 var(--mono);color:var(--sub)}
.facts b{color:var(--ink);font-weight:600}

/* ---------- peel ---------- */
.peel{display:grid;grid-template-columns:1fr 1fr 260px;gap:20px;align-items:start}
.peel .box{border:1px solid var(--line);border-radius:9px;background:var(--panel);padding:10px;
  text-align:center;min-height:300px;display:flex;flex-direction:column}
.peel .box img{max-width:100%;max-height:470px;object-fit:contain;margin:auto}
.peel .cap{font:600 12px/1 var(--mono);color:var(--sub);margin-bottom:8px;text-transform:uppercase;
  letter-spacing:.4px}

/* ---------- comparison ---------- */
.cmp{display:grid;grid-template-columns:repeat(auto-fill,minmax(258px,1fr));gap:18px}
.card{border:1px solid var(--line);border-radius:9px;overflow:hidden;background:#fff}
.card .hd{display:flex;justify-content:space-between;align-items:baseline;padding:9px 11px;
  border-bottom:1px solid var(--line);font:600 12.5px/1.3 var(--mono)}
.card .hd small{color:var(--sub);font-weight:400}
.pair{display:grid;grid-template-columns:1fr 1fr}
.pair figure{margin:0;padding:8px;text-align:center}
.pair figure+figure{border-left:1px solid var(--line)}
.pair img{width:100%;height:auto;display:block}
.pair figcaption{font:600 11px/1 var(--mono);margin-top:6px;letter-spacing:.3px}
.pair .o{color:var(--ours)} .pair .s{color:var(--alt)}

/* ---------- gallery ---------- */
.gal{display:grid;grid-template-columns:repeat(auto-fill,minmax(148px,1fr));gap:13px}
.gal figure{margin:0;border:1px solid var(--line);border-radius:8px;overflow:hidden;background:#fff;
  cursor:pointer;transition:box-shadow var(--t-hover) ease,transform var(--t-hover) var(--ease-out)}
@media (hover:hover) and (pointer:fine){
  .gal figure:hover{box-shadow:0 3px 14px rgba(26,31,38,.13);transform:translateY(-1px)}
}
.gal figure:active{transform:scale(0.985)}
.gal img{width:100%;aspect-ratio:3/4;object-fit:contain;background:#fff;display:block}
.gal figcaption{padding:6px 8px 8px;font:11.5px/1.35 var(--mono);color:var(--sub);
  border-top:1px solid var(--line)}
.gal figcaption b{display:block;color:var(--ink);font-weight:600;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}

/* ---------- table ---------- */
.tw{overflow-x:auto;-webkit-overflow-scrolling:touch}
table{border-collapse:collapse;width:100%;font-size:14.5px;min-width:520px}
th,td{padding:9px 12px;border-bottom:1px solid var(--line);text-align:right;white-space:nowrap}
th:first-child,td:first-child{text-align:left}
thead th{font:600 12px/1 var(--mono);color:var(--sub);text-transform:uppercase;letter-spacing:.4px;
  border-bottom:1.5px solid var(--ink)}
tbody tr.me td{background:#eff6fc;font-weight:600}
tbody tr.grp td{background:var(--panel);font:600 12px/1 var(--mono);color:var(--sub);
  text-transform:uppercase;letter-spacing:.4px;text-align:left}
td.num{font-family:var(--mono);font-variant-numeric:tabular-nums}
.fn{color:var(--sub);font-size:13.5px;margin-top:12px;max-width:88ch}

/* ---------- lightbox ---------- */
#lb{position:fixed;inset:0;background:rgba(18,22,27,.92);display:none;align-items:center;
  justify-content:center;z-index:50;padding:26px;cursor:zoom-out}
#lb.on{display:flex}
#lb .in{max-width:min(1000px,96vw);text-align:center}
#lb img{max-width:100%;max-height:78vh;background:#fff;border-radius:7px}
#lb .cp{color:#e6ebf1;font:13px/1.6 var(--mono);margin-top:14px}
#lb .cp b{color:#fff}
#lb .strip{display:flex;gap:8px;justify-content:center;margin-top:12px}
#lb .strip img{height:78px;width:auto;opacity:.55;cursor:pointer;border:2px solid transparent}
#lb .strip img.on{opacity:1;border-color:#fff}

footer{padding:34px 0 60px;color:var(--sub);font-size:13.5px}
@media (max-width:900px){
  .explorer{grid-template-columns:1fr}
  .picker{flex-direction:row;overflow-x:auto;max-height:none}
  .picker button{flex:none;width:132px}
  .stage,.peel{grid-template-columns:1fr}
}

/* ---------- cursor tracking ---------- */
.track{display:grid;grid-template-columns:1fr 300px;gap:24px;align-items:start}
.trstage{position:relative;background:
    radial-gradient(circle at 50% 42%,#fbfcfe 0%,#eef2f7 100%);
  border:1px solid var(--line);border-radius:11px;min-height:520px;
  display:flex;align-items:center;justify-content:center;overflow:hidden;
  cursor:crosshair;touch-action:none}
.trstage .stack img{max-height:500px}
/* a standing full-body figure gets a taller stage, or a 3.3:1 aspect leaves it 150px across */
.trstage.tall{min-height:760px}
.trstage.tall .stack img{max-height:740px}
.trstage .hint{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);
  display:flex;align-items:center;gap:8px;
  font:600 12.5px/1 var(--mono);color:var(--ink);background:rgba(255,255,255,.95);
  border:1px solid var(--ours);border-radius:999px;padding:9px 16px;pointer-events:none;
  box-shadow:0 3px 14px rgba(26,31,38,.13);transition:opacity .3s;
  animation:hintpulse 1.9s ease-in-out infinite}
/* the prompt stays until the reader actually moves the pointer inside, not merely hovers the section */
.trstage .hint.gone{opacity:0;animation:none}
.trstage .hint .cur{width:13px;height:16px;flex:none;background:var(--ours);
  clip-path:polygon(0 0,0 72%,26% 55%,44% 96%,62% 88%,44% 47%,72% 44%);
  animation:hintmove 1.9s ease-in-out infinite}
@keyframes hintpulse{0%,100%{transform:translateX(-50%) scale(1)}50%{transform:translateX(-50%) scale(1.035)}}
@keyframes hintmove{0%,100%{transform:translate(0,0)}50%{transform:translate(5px,-3px)}}
#trRead{font:12.5px/1.9 var(--mono)}
#trRead b{color:var(--ours)}
@media (max-width:900px){.track{grid-template-columns:1fr}.trstage{min-height:400px}
  .trstage.tall{min-height:560px}.trstage.tall .stack img{max-height:540px}}

/* the explorer plays a video and scrubs stills; both must sit in the same box */
#exVid{max-width:100%;max-height:600px;display:block}

/* A-pose grid. These are standing full-body figures at aspect 2.7-3.3 (H/W), so the tile is TALL and
   narrow -- a 3/4 tile like the gallery uses would letterbox them to a third of its width. */
.apgrid{display:grid;grid-template-columns:repeat(6,1fr);gap:12px}
.apgrid figure{margin:0;position:relative;border:1px solid var(--line);border-radius:9px;overflow:hidden;
  background:#fff;cursor:pointer;transition:box-shadow var(--t-hover) ease,transform var(--t-hover) var(--ease-out)}
@media (hover:hover) and (pointer:fine){
  .apgrid figure:hover{box-shadow:0 4px 18px rgba(26,31,38,.15);transform:translateY(-2px)}
  .apgrid figure:hover .apax{opacity:1}
}
.apgrid figure:active{transform:scale(0.99)}
.apgrid figure.scrub .apax{opacity:1}
.apgrid img,.apgrid video{width:100%;aspect-ratio:var(--ap-ar,5/14);object-fit:contain;
  object-position:center center;background:#fff;display:block}
/* one video per cycled axis, stacked and switched by opacity -- reassigning src made the tile blink */
.apgrid .apvids{position:relative}
.apgrid .apvids video{position:absolute;inset:0;height:100%}
.apgrid .apvids video:first-child{position:relative}
.apgrid figcaption{position:relative;padding:6px 8px 8px;font:11px/1.35 var(--mono);color:var(--sub);
  border-top:1px solid var(--line);background:#fcfcfd}
.apgrid figcaption b{display:block;color:var(--ink);font-weight:600;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.apgrid .apax{position:absolute;left:0;right:0;bottom:0;padding:4px 6px;background:rgba(255,255,255,.93);
  border-top:1px solid var(--line);font:600 10px/1.3 var(--mono);color:var(--ours);text-align:center;
  opacity:0;transition:opacity var(--t-enter) ease;pointer-events:none}
.apgrid .t2i{position:absolute;top:5px;right:5px;padding:2px 5px;border-radius:4px;
  background:rgba(26,31,38,.72);color:#fff;font:600 9.5px/1.3 var(--mono);letter-spacing:.02em}
.grp button{font-size:12px}
@media (max-width:900px){.apgrid{grid-template-columns:repeat(4,1fr)}}
@media (max-width:560px){.apgrid{grid-template-columns:repeat(3,1fr)}}

/* pointer-reactive surfaces get the crosshair the tracking stage uses, so it is discoverable */
.viewport.react{cursor:crosshair}
.apgrid figure{cursor:crosshair}
/* the scrub stack sits exactly where the video is and only appears while the pointer is over the tile */
.apgrid .apstack{display:none;position:relative}
.apgrid figure.scrub .apstack{display:block}
.apgrid figure.scrub video{display:none}
.apgrid .apstack img{width:100%;aspect-ratio:var(--ap-ar,5/14);object-fit:contain;
  object-position:center center;background:#fff;display:block}
.apgrid .apstack img.ov{position:absolute;inset:0;height:auto;opacity:0;will-change:opacity}
#carCount{margin-left:2px}

/* ---------- exploded layer stack ---------- */
.explode{display:grid;grid-template-columns:1fr 300px;gap:24px;align-items:start}
.exstage{position:relative;min-height:620px;border:1px solid var(--line);border-radius:11px;
  background:radial-gradient(circle at 50% 45%,#fbfcfe 0%,#eaeff6 100%);overflow:hidden;
  display:flex;align-items:center;justify-content:center;cursor:ew-resize;
  perspective:1500px;perspective-origin:50% 45%}
.exlayers{position:relative;width:46%;max-width:310px;aspect-ratio:46/73;
  transform-style:preserve-3d;transition:none}
.exlayers img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;
  will-change:transform;backface-visibility:hidden;
  filter:drop-shadow(-6px 3px 8px rgba(26,31,38,.22))}
/* the fan needs room to travel outside the nominal box; the stage clips it */
.exlayers{margin:0 auto}
.exlab{position:absolute;left:12px;top:11px;font:600 11px/1 var(--mono);color:var(--sub);
  background:rgba(255,255,255,.9);border:1px solid var(--line);border-radius:6px;padding:5px 9px}
@media (max-width:900px){.explode{grid-template-columns:1fr}.exstage{min-height:420px}}

/* ---------- scroll reveal (L2) ---------- */
.rev{opacity:0;transform:translateY(10px);
  transition:opacity 260ms var(--ease-out),transform 260ms var(--ease-out)}
.rev.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  .rev{opacity:1;transform:none;transition:none}
  .trstage .hint,.trstage .hint .cur{animation:none}
}
/* touch targets: the guidance asks for 44px minimum on pointer-coarse devices */
@media (pointer:coarse){
  .btn,.axes button,#galSort button{min-height:44px;padding-top:11px;padding-bottom:11px}
}

/* Wide content scrolls inside its own box; the page body must never scroll sideways. */
.tablewrap{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:0 0 8px}
.tablewrap table{min-width:560px}

/* the picker is a tab strip: it scrolls inside itself instead of widening the page */
.picker{overscroll-behavior-x:contain}
.picker::-webkit-scrollbar{height:7px}
.picker::-webkit-scrollbar-thumb{background:var(--line);border-radius:99px}

/* ---------- narrow layout ----------
   Every multi-column grid collapses. Without this the 3-column peel grid alone forced 466px of content
   into a 346px box and the whole page scrolled sideways. */
@media (max-width:760px){
  .peel,.explode,.stage,.explorer,.track{grid-template-columns:1fr;gap:16px}
  .peel .box img{max-height:340px}
  .picker{flex-direction:row;max-height:none;overflow-x:auto;overflow-y:hidden;
    padding-bottom:6px;scrollbar-width:thin}
  .picker button{flex:0 0 auto;min-width:132px}
  .feat{grid-template-columns:repeat(2,1fr)}
  .exstage{min-height:360px}
  .exlayers{width:82%}
  .affil{font-size:11px}
}
@media (max-width:420px){
  .feat{grid-template-columns:1fr}
  .apgrid{grid-template-columns:repeat(2,1fr)}
  .authors{gap:3px 11px;font-size:13.5px}
  .authors .au{white-space:normal}
}

@media (max-width:420px){
  /* section 06 uses .peel too, but with two image boxes side by side inside a 1fr column; and the
     comparison grid's 258px minimum is wider than a 360px viewport once padding is counted */
  .cmp{grid-template-columns:1fr}
  .pair{grid-template-columns:1fr}
  .exlayers{width:74%}
}

/* section 06's two-image variant. This used to be an INLINE grid-template, which outranks every media
   query, so the column set survived the narrow breakpoint and pushed the page 120px sideways. */
.peel3{grid-template-columns:1fr 1fr 260px}
@media (max-width:760px){.peel3{grid-template-columns:1fr}}

/* the See-through argument list */
ul.why{margin:0 0 18px;padding:0 0 0 4px;list-style:none;max-width:900px}
ul.why li{position:relative;padding:0 0 9px 22px;color:var(--sub);font-size:15.5px;line-height:1.6}
ul.why li:before{content:"";position:absolute;left:4px;top:.62em;width:7px;height:7px;border-radius:2px;
  background:var(--ours)}
ul.why b{color:var(--ink);font-weight:600}

/* the stage is a single video now: playback and scrubbing share one element, because the per-axis stills
   were dropped and the slider seeks the clip */
.viewport video{width:100%;max-height:520px;object-fit:contain;display:block;background:#fff}
.apgrid .apstack{display:none}

/* ---------- stagger ----------
   When a grid of tiles enters together, appearing all at once reads as a single flat event. A short
   cascade (40ms apart) reads as the page assembling. Kept decorative: nothing waits on it, and the delay
   budget is capped so the last tile is not left behind. */
.apgrid figure,.feat figure{animation:tileIn 300ms var(--ease-out) both}
.feat figure:nth-child(1){animation-delay:0ms}
.feat figure:nth-child(2){animation-delay:40ms}
.feat figure:nth-child(3){animation-delay:80ms}
.feat figure:nth-child(4){animation-delay:120ms}
.apgrid figure:nth-child(1){animation-delay:0ms}
.apgrid figure:nth-child(2){animation-delay:40ms}
.apgrid figure:nth-child(3){animation-delay:80ms}
.apgrid figure:nth-child(4){animation-delay:120ms}
.apgrid figure:nth-child(5){animation-delay:160ms}
.apgrid figure:nth-child(6){animation-delay:200ms}
.apgrid figure:nth-child(n+7){animation-delay:240ms}
@keyframes tileIn{
  /* not from scale(0): nothing in the world appears out of nothing */
  from{opacity:0;transform:scale(0.97) translateY(6px)}
  to{opacity:1;transform:none}
}

/* ---------- reduced motion ----------
   Fewer and gentler, not zero: opacity still carries the change, movement does not. */
@media (prefers-reduced-motion:reduce){
  .apgrid figure,.feat figure{animation:none}
  .btn:active,.axes button:active,.gal figure:active,.apgrid figure:active,
  .feat figure:active,.picker button:active{transform:none}
  .exstage .exlayers{transition:none}
  *{scroll-behavior:auto}
}

/* ---------- citation ---------- */
.citebox{position:relative;border:1px solid var(--line);border-radius:10px;background:var(--panel);
  overflow:hidden}
.citebox pre{margin:0;padding:18px 20px;overflow-x:auto;font:12.5px/1.75 var(--mono);color:var(--ink);
  white-space:pre;-webkit-overflow-scrolling:touch}
.citebox .cpbtn{position:absolute;top:10px;right:10px;flex:0 0 auto;width:auto;padding:8px 14px;
  background:#fff;z-index:2}
@media (max-width:600px){.citebox pre{font-size:11px;padding:14px 15px 16px}}

/* gallery tiles animate; the still sits underneath as a poster and returns while the pointer scrubs */
.gal figure{position:relative}
.gal figure video{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:#fff;
  z-index:1}
.gal figure.scrub video{display:none}
.gal figcaption{position:relative;z-index:2}

/* ==================================================================== chrome
   Apple's material and typography guidance applied literally:
     - the nav is a translucent LAYER the content scrolls under, not an opaque strip that eats a band of
       the viewport; a bright top edge reads as light catching the material
     - no 1px divider under it. A soft mask where content meets the floating chrome is what Apple ships
       ("scroll edge effects, not hard dividers")
     - tracking is size-specific: negative on display type, ~0 on body. One letter-spacing for everything
       is wrong somewhere
     - reduced-transparency and more-contrast are honoured, since a frosted layer is exactly what those
       settings exist to defeat
   ==================================================================== */
.nav{position:sticky;top:0;z-index:40;
  background:rgba(255,255,255,.72);
  backdrop-filter:blur(20px) saturate(180%);-webkit-backdrop-filter:blur(20px) saturate(180%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.65),0 1px 0 rgba(26,31,38,.055)}
.navin{display:flex;align-items:center;justify-content:space-between;gap:16px;height:56px}
.brand{display:inline-flex;align-items:center;gap:10px;text-decoration:none;color:var(--ink)}
.brand .glyph{width:26px;height:26px;border-radius:7px;background:linear-gradient(145deg,#2f93c9,#12456e);
  color:#fff;font:700 15px/26px Georgia,serif;text-align:center;flex:none;
  box-shadow:0 1px 3px rgba(18,69,110,.34)}
.brand .bt{font:600 16.5px/1 var(--mono);letter-spacing:-.01em}
.navlinks{display:flex;gap:8px}
.nb{display:inline-flex;align-items:center;gap:7px;text-decoration:none;color:var(--sub);
  font:600 13px/1 var(--mono);letter-spacing:0;padding:8px 13px;border-radius:9px;
  border:1px solid transparent;
  transition:color var(--t-hover) ease,background var(--t-hover) ease,
    border-color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}
.nb svg{width:15px;height:15px}
@media (hover:hover) and (pointer:fine){
  .nb:hover{color:var(--ink);background:rgba(26,31,38,.045);border-color:rgba(26,31,38,.07)}
}
.nb:active{transform:scale(0.96)}

/* ---------- closing call to action ---------- */
footer{border-top:0;margin-top:16px;padding:0 0 54px;
  background:linear-gradient(180deg,#fff 0%,#f6f8fb 42%,#eef2f7 100%)}
.cta{text-align:center;padding:60px 0 40px}
.ctak{margin:0 0 14px;font:700 11.5px/1 var(--mono);letter-spacing:.13em;text-transform:uppercase;
  color:var(--ours)}
.ctat{margin:0;font-size:44px;line-height:1.02;font-weight:600;letter-spacing:-.028em;
  background:linear-gradient(135deg,#12456e 0%,#1f6fb2 54%,#2f93c9 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent}
.ctas{margin:10px 0 30px;font-size:18px;line-height:1.4;letter-spacing:-.008em;color:var(--sub)}
.ctarow{display:flex;gap:14px;justify-content:center;flex-wrap:wrap}
.cbtn{display:inline-flex;align-items:center;gap:12px;text-decoration:none;
  padding:15px 24px;border-radius:14px;border:1px solid var(--line);background:#fff;color:var(--ink);
  box-shadow:0 1px 2px rgba(26,31,38,.05),0 8px 24px rgba(26,31,38,.055);
  transition:background var(--t-hover) ease,border-color var(--t-hover) ease,
    box-shadow var(--t-hover) ease,transform var(--t-press) var(--ease-out)}
.cbtn svg{width:21px;height:21px;flex:none}
.cbtn span{display:flex;flex-direction:column;gap:3px;text-align:left}
.cbtn b{font:600 15.5px/1 var(--mono);letter-spacing:-.01em}
.cbtn small{font:400 11.5px/1 var(--mono);color:var(--sub);letter-spacing:.01em}
.cbtn.pri{background:linear-gradient(180deg,#2a7fc0,#1a5f9b);border-color:#1a5f9b;color:#fff;
  box-shadow:0 1px 2px rgba(18,69,110,.28),0 10px 28px rgba(31,111,178,.28)}
.cbtn.pri small{color:rgba(255,255,255,.8)}
@media (hover:hover) and (pointer:fine){
  .cbtn:hover{transform:translateY(-2px);box-shadow:0 2px 4px rgba(26,31,38,.06),0 14px 34px rgba(26,31,38,.10)}
  .cbtn.pri:hover{box-shadow:0 2px 6px rgba(18,69,110,.3),0 16px 38px rgba(31,111,178,.34)}
}
.cbtn:active{transform:scale(0.975)}
.fine{max-width:760px;margin:0 auto;text-align:center;font:12.5px/1.75 var(--mono);color:var(--sub);
  letter-spacing:.01em}

/* ---------- type: tracking is size-specific ---------- */
h2{letter-spacing:-.018em}
.lede{letter-spacing:-.004em}

@media (max-width:600px){
  .navin{height:50px}
  .brand .bt{font-size:15px}
  .nb span,.nb{font-size:12px;padding:8px 10px}
  .ctat{font-size:32px}
  .ctas{font-size:16px}
  .cbtn{width:100%;justify-content:center}
}

/* the two settings a frosted layer must respect */
@media (prefers-reduced-transparency:reduce){
  .nav{background:#fff;backdrop-filter:none;-webkit-backdrop-filter:none;
    box-shadow:0 1px 0 rgba(26,31,38,.10)}
}
@media (prefers-contrast:more){
  .nav{background:#fff;backdrop-filter:none;border-bottom:1px solid var(--ink)}
  .nb{color:var(--ink);border-color:var(--line)}
  .cbtn{border-color:var(--ink)}
}
@media (prefers-reduced-motion:reduce){
  .cbtn:active,.nb:active{transform:none}
}

/* the comparison is video on both sides now */
.cmp .pair figure video{width:100%;aspect-ratio:3/4;object-fit:contain;background:#fff;display:block}

/* ---------- contact ---------- */
.cgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;margin:0 0 26px}
.ccard{border:1px solid var(--line);border-radius:13px;padding:22px 22px 20px;background:#fff;
  box-shadow:0 1px 2px rgba(26,31,38,.04)}
.cicon{width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(145deg,#eaf3fa,#d9e9f6);color:var(--ours);margin-bottom:13px}
.cicon svg{width:20px;height:20px}
.ccard h4{margin:0 0 6px;font:600 15.5px/1.3 var(--mono);letter-spacing:-.01em}
.ccard p{margin:0;color:var(--sub);font-size:14px;line-height:1.6}
.crow{display:flex;gap:14px;flex-wrap:wrap}
@media (max-width:820px){.cgrid{grid-template-columns:1fr}}
@media (max-width:420px){.crow .cbtn{width:100%;justify-content:center}}

/* the re-texture pair is video now; the stills stay as the fallback and for the pose buttons */
.peel .box video{max-width:100%;max-height:470px;object-fit:contain;margin:auto;display:block;background:#fff}

/* an author name that links: the affordance has to be visible without turning the byline into a row of
   blue links, so it is the same ink with a faint underline that firms up on hover */
.authors a.ahome{color:inherit;text-decoration:none;
  border-bottom:1px solid rgba(31,111,178,.42);
  transition:color var(--t-hover) ease,border-color var(--t-hover) ease}
@media (hover:hover) and (pointer:fine){
  .authors a.ahome:hover{color:var(--ours);border-bottom-color:var(--ours)}
}
/* the browser shows the destination in the status bar, but a title makes the KIND of link explicit --
   one opens a homepage, the other opens a mail client, and those are not interchangeable */
.authors a[href^="mailto:"]{cursor:pointer}
.authors a.ahome:active{color:var(--ours)}

/* ---------- "seeking" callouts ----------
   A gradient pill sitting above the name, and the name itself shaking, so the notice is impossible to miss
   in a byline of nine.

   The row reserves headroom via padding-top with an equal negative margin, so the badge can sit above the
   name without pushing the author list down or overlapping the subtitle.

   The shake runs continuously, which is a deliberate exception to this page's own rule about not animating
   what a reader sees the whole time -- it is a recruitment notice and its job is to catch the eye. It is
   still dropped entirely under prefers-reduced-motion, where continuous motion is not a style choice but an
   accessibility problem; the badge stays, so no information is lost. */
/* ---------- "seeking" callouts ----------
   A FLOATING pill centred above the name, as on lottiegpt.github.io: the wrapper reserves headroom with
   padding-top plus an equal negative margin, so the badge occupies space that costs the layout nothing, and
   the pill is absolutely positioned out of flow at top:0 / translate(-50%,-100%).

   The reference can leave it at that because its two tagged authors sit far apart in the list. Ours are the
   FIRST TWO, side by side, and each pill is wider than the name it labels -- centred, they overlapped, and
   the first one rendered as "SEEKING 27 FALL P...". So each tagged author reserves horizontal room equal to
   its own overhang (--oh), which is what keeps the two pills apart without moving them off centre. */
/* ---------- "seeking" callouts ----------
   A floating pill above the name, joined to it by a coiled connector.

   Geometry is reserved on the wrapper (padding-top with an equal negative margin) so the whole assembly --
   pill, coil, name -- costs the layout nothing and cannot push the byline around. The pill is pinned to the
   TOP of that reserved band and the coil fills the space between pill and name, both sized from measurement
   in fitCallouts() because they depend on the pill's rendered width and the resolved font. */
/* ---------- "seeking" callouts ----------
   The card sits at the name's UPPER-RIGHT and close to it, joined by a short coil that drops from the card's
   lower-left to the name's top-right corner.

   Anchoring right rather than centring changes what has to be reserved: a centred card overhangs both sides
   by half its excess width, but a right-anchored one extends entirely PAST the name, so the room goes on the
   right only -- and it is the full card width, not half. Reserved via margin-right from a measured value,
   because the width depends on the font the visitor's system resolves. */
.authors{padding-top:34px}
.au.seeking{position:relative;display:inline-block;vertical-align:top;
  padding-top:var(--band,26px);margin-top:calc(-1 * var(--band,26px));
  margin-right:var(--room,120px)}

.au.seeking .callout{position:absolute;top:0;left:var(--ax,100%);transform:none;
  z-index:3;white-space:nowrap;line-height:0}
.au.seeking .cin{display:inline-block;transform-origin:20% 80%;
  border-radius:999px;padding:7px 14px;white-space:nowrap;
  font:800 9.5px/1 var(--mono);letter-spacing:.06em;text-transform:uppercase;color:#fff;
  background:linear-gradient(135deg,#ff7a18 0%,#ff3d54 100%);
  box-shadow:0 6px 16px rgba(255,61,84,.30);
  animation:seekShake .34s linear infinite}
.au.seeking .callout.job .cin{background:linear-gradient(135deg,#1f9d55 0%,#0f7a86 100%);
  box-shadow:0 6px 16px rgba(15,122,134,.28)}

/* the coil: short now, because the card is close. Drops from the card's lower-left to the name's top-right */
.au.seeking .tether{--tint:#ff5a36;position:absolute;left:var(--tx,100%);top:var(--ty,18px);
  z-index:1;overflow:visible;pointer-events:none}
.au.seeking .tether.job{--tint:#12868b}
.au.seeking .tether path{fill:none;stroke:var(--tint);stroke-width:1.8;stroke-linecap:round;
  stroke-dasharray:5 4;animation:dashFlow .7s linear infinite}
.au.seeking .tether circle{fill:var(--tint)}
@keyframes dashFlow{from{stroke-dashoffset:0}to{stroke-dashoffset:-18}}
@keyframes seekShake{
  0%{transform:translate3d(0,0,0) rotate(0deg) scale(1)}
  20%{transform:translate3d(-2.6px,1.6px,0) rotate(-1.8deg) scale(1.03)}
  40%{transform:translate3d(2.2px,-2.0px,0) rotate(1.8deg) scale(.985)}
  60%{transform:translate3d(-2.0px,-1.3px,0) rotate(-1.4deg) scale(1.022)}
  80%{transform:translate3d(2.6px,.9px,0) rotate(1.4deg) scale(1.006)}
  100%{transform:translate3d(0,0,0) rotate(0deg) scale(1)}
}
@media (prefers-reduced-motion:reduce){
  .au.seeking .cin{animation:none}
  .au.seeking .tether path{animation:none}
}
@media (max-width:600px){
  .au.seeking .cin{font-size:8px;padding:6px 11px}
  .authors{gap:8px 12px;padding-top:30px}
}
