/* EigenDEXplore, prototype B. One dark page whose colour comes from the footage (section 1) and the video's
   studio grey (section 2). Glass = clear, lightly frosted, specular rim brightest top-left. */
:root {
  color-scheme: dark;
  --bg: #0e0e10;
  --bg2: #151517;
  --studio: #484746;
  --ink: #ececee;
  --ink2: rgba(236, 236, 238, .74);
  --ink3: rgba(236, 236, 238, .52);
  --line: rgba(255, 255, 255, .12);
  --js: #7098b7;
  --ours: #c9a227;
  --joint: #7098b7;
  --eigen: #a08bab;
  --residual: #87a08b;
  --pc1: #7098b7;
  --pc2: #e1b84e;
  --pc3: #87a08b;
  --act: #6fa3c8;      /* the paper's action blue, lifted for a dark page */
  --noise: #d39b45;    /* the paper's noise ochre, lifted */
  --bad-bg: rgba(255, 226, 221, .86);
  --good-bg: rgba(226, 248, 232, .86);
  --tag-ink: #1e1e1e;
  --r-card: 26px;
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Avenir Next", Inter, system-ui, sans-serif;
  --w: 1240px;
  --gut: 24px;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
html { background: #fff; }
body {
  margin: 0; background: var(--studio); color: var(--ink); font-family: var(--font);
  font-size: 17px; line-height: 1.55; overflow-x: hidden; -webkit-font-smoothing: antialiased;
}
a { color: inherit; }
button, select, input { font: inherit; color: inherit; }
button { cursor: pointer; }
svg { display: block; }
[hidden] { display: none !important; }

/* ------------------------------------------------------------ glass */
.glass {
  position: relative;
  background: linear-gradient(180deg, rgba(255,255,255,.085), rgba(255,255,255,.035));
  -webkit-backdrop-filter: blur(14px) saturate(165%);
  backdrop-filter: blur(14px) saturate(165%);
  border-radius: 999px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.14), 0 6px 22px rgba(0,0,0,.22);
  isolation: isolate;
}
.glass.panel { border-radius: 22px; }
/* thin specular rim: brightest top-left, weaker opposite (Liquid Glass), drawn as a 1 px ring */
.glass::before, .lg-rim::before, .pill::before, .chip::before, .auto::before, .tagx::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px; pointer-events: none;
  background: linear-gradient(135deg, rgba(255,255,255,.78) 0%, rgba(255,255,255,.22) 22%, rgba(255,255,255,.05) 50%, rgba(255,255,255,.10) 75%, rgba(255,255,255,.42) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
}
.btn { display: inline-flex; align-items: center; gap: 8px; padding: 10px 18px; min-height: 44px; text-decoration: none;
  font-weight: 600; font-size: 15px; letter-spacing: .01em; border: 0; transition: transform .2s ease, background .2s; }
.btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.btn:hover { background: linear-gradient(180deg, rgba(255,255,255,.14), rgba(255,255,255,.06)); }
.btn:active { transform: scale(.97); }
:focus-visible { outline: 2px solid rgba(255,255,255,.8); outline-offset: 2px; }

/* Reset view: one button for every 3D stage (sections 1 to 5), in words, at the top centre of the stage between the two
   names and level with them; it fades in once the reader has turned the view. Placed by left / right / margin, never by
   a transform: pressing it scales it (.btn:active), which must not move it. --rvTop is set per stage (level with its pills) */
.r3d-reset, .m-reset, .t-reset { min-height: 34px; padding: 6px 14px; font-size: 13.5px; white-space: nowrap; opacity: 0; pointer-events: none;
  transition: opacity .3s ease, transform .2s ease, background .2s; }
.m-reset, .t-reset { position: absolute; z-index: 4; top: var(--rvTop); left: max(0px, 2 * var(--rvDX)); right: max(0px, -2 * var(--rvDX)); margin: 0 auto; width: max-content; }
:root { --rvTop: 10px; --rvDX: 0px; }
@media (max-width: 599px) { .r3d-reset, .m-reset, .t-reset { min-height: 28px; padding: 4px 11px; font-size: 12px; } }

/* each control row is one composited layer, so it moves as a whole when the page above it changes height (a fold-out
   opening, a font arriving). Without it iOS WebKit (Safari and Chrome on iPhone) can keep painting a pressed button or
   a round glass button a few px above its new place, cut at its top edge */
.stage-top, .transport, .s2-top, .t-top { will-change: transform; }

/* segmented control (glass capsule with a sliding glass thumb) */
.seg { display: inline-flex; position: relative; padding: 4px; gap: 2px; border-radius: 999px; }
.seg button { position: relative; z-index: 1; border: 0; background: none; padding: 8px 16px; min-height: 40px; border-radius: 999px;
  color: var(--ink2); font-weight: 600; font-size: 15px; white-space: nowrap; transition: color .25s; }
.seg button[aria-selected="true"], .seg button[aria-pressed="true"] { color: #fff; }
.seg-thumb { position: absolute; z-index: 0; top: 4px; bottom: 4px; left: 0; width: 0; border-radius: 999px;
  background: linear-gradient(180deg, rgba(255,255,255,.22), rgba(255,255,255,.10));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 2px 8px rgba(0,0,0,.2);
  transition: transform .45s cubic-bezier(.2,.8,.2,1), width .45s cubic-bezier(.2,.8,.2,1); }
.seg.small { padding: 3px; background: rgba(255,255,255,.06); box-shadow: inset 0 0 0 1px rgba(255,255,255,.08); }
.seg.small button { padding: 6px 12px; min-height: 36px; font-size: 13.5px; }
.seg.small button[aria-pressed="true"] { background: rgba(255,255,255,.16); box-shadow: inset 0 1px 0 rgba(255,255,255,.3); }

/* ------------------------------------------------------------ opening (hero + section 1): white, like the video's end card */
.opening {
  position: relative; overflow: hidden; color-scheme: light;
  --ink: #1d1d1f; --ink2: rgba(29, 29, 31, .74); --ink3: rgba(29, 29, 31, .52); --line: rgba(0, 0, 0, .08);
  --ours-ink: #9a780f; --js-ink: #47709a;
  color: var(--ink);
  background: radial-gradient(90% 60% at 50% 0%, #ffffff 0%, #fafafb 55%, #f4f4f6 100%);
}
.hero, .s1 { position: relative; z-index: 1; }
/* hero = a 3-column grid: sprite column | content | sprite column. The sprites live in their own cells, so they can
   never overlap the text; js picks the largest crisp scale that fits the side columns and the content height. */
.opening { --g1: 8px; --g2: 16px; }
.hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 680px) minmax(0, 1fr); grid-template-rows: repeat(3, auto);
  column-gap: 24px; max-width: 1400px; margin: 0 auto; padding: 40px var(--gut) 8px; text-align: center; }
.hero-c { grid-column: 2; grid-row: 1 / 4; align-self: center; position: relative; z-index: 1; }
.title { margin: 0; font-size: clamp(32px, 3.2vw, 42px); line-height: 1.06; letter-spacing: -.02em; font-weight: 700; color: #1d1d1f; }
.subtitle { margin: var(--g1) auto 0; font-size: clamp(16px, 1.45vw, 18.5px); line-height: 1.35; color: var(--ink2); font-weight: 500; white-space: nowrap; }
.authors { margin: var(--g2) auto 0; display: flex; flex-direction: column; align-items: center; gap: .2em; font-size: 15px; }
.arow { margin: 0; display: flex; justify-content: center; align-items: baseline; flex-wrap: nowrap; gap: 0 .9em; font-size: var(--af, 15px); line-height: 1.5; }
.agrp { display: flex; align-items: baseline; white-space: nowrap; gap: 0 .9em; }
.au { white-space: nowrap; }
.eqc { font-size: .7em; line-height: 0; vertical-align: .62em; margin-left: .08em; color: var(--ink2); font-weight: 600; }
.affil-row { margin: 12px 0 0; display: flex; align-items: center; justify-content: center; gap: 14px; flex-wrap: wrap; }
.affil-row .affil { margin: 0; }
.eqnote { font-size: 13px; color: var(--ink3); }
.eqnote sup { font-size: .85em; line-height: 0; vertical-align: .18em; margin-right: 1px; }
.authors a { text-decoration: none; color: var(--ink); font-weight: 500; background: linear-gradient(currentColor 0 0) 0 100% / 0 1px no-repeat; transition: background-size .25s ease; padding-bottom: 1px; }
.authors a:hover { background-size: 100% 1px; }
.affil { display: inline-block; margin: 12px 0 0; line-height: 0; border-radius: 6px; }
.affil img { height: 22px; width: auto; display: block; }
.links { margin: var(--g2) 0 0; display: flex; flex-wrap: wrap; justify-content: center; gap: .55em; font-size: var(--lf, 14px); }
.links.one-row { flex-wrap: nowrap; }
.tldr { margin: var(--g2) auto 0; max-width: 680px; padding: 14px 18px; text-align: left; font-size: 15px; line-height: 1.56; color: var(--ink2); border-radius: 18px; text-wrap: pretty; }
.tldr b { color: var(--ink); margin-right: 6px; }

/* light Liquid Glass (the end card's white capsules): frosted white, fine edge, soft shadow, bright top-left rim */
:is(.opening, .s4) .glass {
  background: linear-gradient(180deg, rgba(255, 255, 255, .82), rgba(255, 255, 255, .58));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95), inset 0 0 0 1px rgba(0, 0, 0, .055), 0 1px 2px rgba(0, 0, 0, .05), 0 8px 24px rgba(0, 0, 0, .07);
}
:is(.opening, .s4) .glass::before { background: linear-gradient(135deg, rgba(255,255,255,1) 0%, rgba(255,255,255,.5) 22%, rgba(255,255,255,0) 50%, rgba(0,0,0,.04) 78%, rgba(0,0,0,.07) 100%); }
:is(.opening, .s4) .btn { color: var(--ink); }
:is(.opening, .s4) .btn:hover { background: linear-gradient(180deg, rgba(255, 255, 255, .98), rgba(255, 255, 255, .78)); }
:is(.opening, .s4) :focus-visible { outline-color: rgba(0, 0, 0, .7); }
.hero .btn { min-height: 38px; padding: .5em 1em .5em .86em; font-size: 1em; gap: .5em; white-space: nowrap; }
.hero .btn .ic { width: 1.2em; height: 1.2em; }
.hero .btn .ic.yt { width: 1.34em; height: 1.34em; }
.btn .ic { width: 17px; height: 17px; flex: none; }
.btn .ic.doc { fill: none; stroke: currentColor; stroke-width: 1.7; }
.btn .ic.brand { fill: currentColor; stroke: none; }
.btn .ic.arxiv { fill: #b31b1b; }
.btn .ic.yt { fill: #ff0033; width: 19px; height: 19px; }
.btn .ic.gh { fill: #1d1d1f; }

/* sprites: pixel art at an integer number of device pixels (set by js), in the end card's six spots */
.spr { display: block; justify-self: center; width: calc(var(--w) * var(--s) * 1px); height: calc(var(--h) * var(--s) * 1px);
  background-repeat: no-repeat; background-size: calc(var(--n) * var(--w) * var(--s) * 1px) 100%; background-position: 0 0;
  image-rendering: pixelated; image-rendering: crisp-edges; opacity: 0; transform-origin: 50% 100%; }
.spr.in { animation: spr-pop .3s linear both; animation-delay: var(--d, 0s); }
.spr.in.run { animation: spr-pop .3s linear both, spr-run var(--t) steps(var(--n)) infinite; animation-delay: var(--d, 0s), var(--d, 0s); }
@keyframes spr-run { to { background-position-x: calc(var(--n) * var(--w) * var(--s) * -1px); } }
@keyframes spr-pop { 0% { opacity: 0; transform: scale(.5); } 1% { opacity: 1; transform: scale(.5); } 49% { transform: scale(.5); } 50%, 100% { opacity: 1; transform: none; } }
.spr-row { display: contents; }
/* the end card's zig-zag (credits.py SPR_REGIONS): on each side the top sprite sits inward, the middle one hugs the
   outer edge and the bottom one sits between, mirrored left/right, with the rows offset in height */
.spr[data-at="tl"] { grid-column: 1; grid-row: 1; align-self: start; justify-self: end; margin: 6px 4% 0 0; }
.spr[data-at="ml"] { grid-column: 1; grid-row: 2; align-self: center; justify-self: start; margin-left: 2%; }
.spr[data-at="bl"] { grid-column: 1; grid-row: 3; align-self: end; justify-self: center; margin: 0 0 4px 10%; }
.spr[data-at="tr"] { grid-column: 3; grid-row: 1; align-self: start; justify-self: start; margin: 0 0 0 2%; }
.spr[data-at="mr"] { grid-column: 3; grid-row: 2; align-self: center; justify-self: end; margin: 18px 1% 0 0; }
.spr[data-at="br"] { grid-column: 3; grid-row: 3; align-self: end; justify-self: center; margin: 0 6% 0 0; }
@media (prefers-reduced-motion: reduce) { .spr.in, .spr.in.run { animation: none; opacity: 1; } }

.sec-head { max-width: var(--w); margin: 0 auto; padding: 0 var(--gut); }
.kicker { margin: 0; color: var(--ink3); font-size: 13px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.sec-head h2 { margin: 0; font-size: clamp(26px, 2.8vw, 34px); line-height: 1.1; letter-spacing: -.015em; font-weight: 700; }
.lead { margin: 8px 0 0; max-width: 760px; color: var(--ink2); font-size: 16px; text-wrap: pretty; }
.fine { margin: 8px 0 0; color: var(--ink3); font-size: 13.5px; line-height: 1.5; }
h3 { margin: 0; font-size: 18px; font-weight: 650; }

/* ------------------------------------------------------------ section 1: the whole stage fits one screen
   js/stage.js sets the card height --H from the viewport height (the column keeps the page width, so the cards get
   wider than tall and show more of the full Sony frame); the overlays scale with --k. */
.s1 { --H: 420px; --k: 1; --cg: 14px; padding: 140px 0 28px; }
.s1-in { container: s1 / inline-size; max-width: var(--w); margin: 0 auto; padding: 0 var(--gut); }
.s1 .sec-head { max-width: none; margin: 0; padding: 0; }
.s1 .sec-head h2 { margin: 0; font-size: clamp(26px, 2.8vw, 34px); }
.s1 .lead { margin-top: 8px; max-width: 760px; font-size: 16px; }
.stage-top { margin-top: 18px; display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.stage-top #viewSeg { margin-left: auto; }
.task-line { margin: 0; color: var(--ink2); font-size: 14.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.s1 #taskSeg button { padding: 7px 15px; min-height: 38px; font-size: 14.5px; }
.s1 .seg.small button { min-height: 34px; padding: 5px 11px; font-size: 13.5px; }

.cards { overflow-anchor: none; position: relative; margin-top: 12px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--cg); }
.card { position: relative; margin: 0; height: var(--H); border-radius: calc(12px + 10px * var(--k)); overflow: hidden; background: #1b1b1d;
  box-shadow: 0 18px 50px rgba(0,0,0,.45), inset 0 0 0 1px rgba(255,255,255,.06); transition: filter .6s ease; font-size: calc(14px * var(--k)); }
.card::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; padding: 1.5px; z-index: 5;
  background: linear-gradient(135deg, rgba(255,255,255,.65), rgba(255,255,255,.08) 30%, rgba(255,255,255,0) 55%, rgba(255,255,255,.25));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; }
.card.dim { filter: brightness(.45) saturate(.7); }
.media, .media video { position: absolute; inset: 0; width: 100%; height: 100%; }
.media video { object-fit: cover; object-position: 50% 40%; background: #1b1b1d; }
.ov { position: absolute; inset: 0; pointer-events: none; z-index: 4; }
.ov > * { pointer-events: auto; }
.pill, .chip, .auto, .tagx, .res { position: absolute; display: inline-flex; align-items: center; gap: .4em; border-radius: 999px;
  font-weight: 600; white-space: nowrap; -webkit-backdrop-filter: blur(10px) saturate(170%); backdrop-filter: blur(10px) saturate(170%);
  box-shadow: 0 4px 14px rgba(0,0,0,.18); isolation: isolate; line-height: 1.25; }
.pill { top: .8em; padding: .38em .9em; font-size: 1.04em; color: #fff; }
.pill.js { left: .8em; background: color-mix(in srgb, var(--js) 72%, transparent); }
.pill.ours { right: .8em; background: color-mix(in srgb, var(--ours) 76%, transparent); }
.chip { top: .8em; padding: .4em .8em; font-size: .96em; color: #1d1d1f; background: rgba(255,255,255,.72); font-variant-numeric: tabular-nums; transition: background .5s; }
.card[data-side="js"] .chip { right: .8em; }
.card[data-side="ours"] .chip { left: .8em; }
.chip.fast { background: rgba(255, 214, 140, .85); }
.chip .dot { opacity: .55; }
.auto { left: .8em; bottom: .8em; padding: .32em .8em; font-size: .9em; color: #fff; background: rgba(40,40,44,.38); font-weight: 500; }
.wp { position: absolute; left: .8em; bottom: .8em; display: none; flex-direction: column; gap: .42em; min-width: 10.5em; padding: .55em .85em .65em;
  border-radius: .95em; background: rgba(255,255,255,.76); color: #1d1d1f; font-size: .92em; font-weight: 600;
  -webkit-backdrop-filter: blur(12px) saturate(170%); backdrop-filter: blur(12px) saturate(170%); box-shadow: 0 4px 14px rgba(0,0,0,.16), inset 0 1px 0 rgba(255,255,255,.9); }
.wp b { font-size: 1.12em; font-variant-numeric: tabular-nums; }
.wp-t { font-variant-numeric: tabular-nums; }
.wp-bar { display: block; height: .32em; border-radius: .16em; background: rgba(0,0,0,.1); overflow: hidden; }
.wp-bar i { display: block; height: 100%; width: 0; border-radius: inherit; transition: width .35s cubic-bezier(.2,.8,.2,1); }
.card[data-side="js"] .wp-bar i { background: var(--js); } .card[data-side="ours"] .wp-bar i { background: var(--ours); }
.wp.done { background: var(--good-bg); }
.cards.trials .wp { display: flex; }
/* outcome outlines (the video's SAM masks): a crisp edge with a soft glow, red for a failure, green for a success */
.olay { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.olay path { fill: none; stroke-width: 2.4; stroke-linejoin: round; }
.olay .bad { stroke: rgb(255,150,135); filter: drop-shadow(0 0 3px rgba(255,150,135,.9)); }
.olay .good { stroke: rgb(150,240,170); filter: drop-shadow(0 0 3px rgba(150,240,170,.9)); }
.cards.three .olay, .cards.trials .olay { display: none; }
.tagx { padding: .5em 1em; font-size: 1.05em; color: var(--tag-ink); background: rgba(255,255,255,.8); transform: translate(-50%, 0);
  opacity: 0; transition: opacity .45s ease, transform .55s cubic-bezier(.2,.8,.2,1); pointer-events: none; font-weight: 650; }
.tagx.bad { background: var(--bad-bg); }
.tagx.good { background: var(--good-bg); }
.tagx.on { opacity: 1; transform: translate(-50%, -6px); }
.tagx i { width: .55em; height: .55em; border-radius: 50%; background: #c8463a; }
.tagx.good i { background: #2e9a5c; }
.ring { position: absolute; border-radius: 50%; border: 2.5px solid rgba(255,255,255,.95); transform: translate(-50%, -50%);
  pointer-events: none; opacity: 0; transition: opacity .4s, border-color .6s; box-shadow: 0 0 0 1px rgba(0,0,0,.15); }
.ring.on { opacity: 1; }
.ring.good { border-color: #59c287; }
.lens { position: absolute; width: calc(150px * var(--k)); height: calc(150px * var(--k)); border-radius: 50%; transform: translate(-50%, -50%) scale(.3); opacity: 0;
  transition: opacity .45s ease, transform .6s cubic-bezier(.2,.8,.2,1); cursor: grab; touch-action: none;
  box-shadow: 0 10px 30px rgba(0,0,0,.35), inset 0 0 0 1px rgba(255,255,255,.25); overflow: hidden; }
.lens.on { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.lens canvas { width: 100%; height: 100%; display: block; border-radius: 50%; }
.lens::after { content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  background: radial-gradient(120% 120% at 30% 25%, rgba(255,255,255,.28), rgba(255,255,255,0) 40%),
              radial-gradient(100% 100% at 50% 50%, rgba(255,255,255,0) 62%, rgba(255,255,255,.35) 72%, rgba(255,255,255,0) 75%);
  box-shadow: inset 2px 2px 1px rgba(255,255,255,.55), inset -2px -2px 2px rgba(255,255,255,.2); }
.lens.done { box-shadow: 0 10px 30px rgba(0,0,0,.35), 0 0 0 3px #59c287; }
.s1 .leader { position: absolute; height: 2px; background: rgba(255,255,255,.6); transform-origin: 0 50%; pointer-events: none; opacity: 0; transition: opacity .4s; }
.s1 .leader.on { opacity: .7; }

/* 3D replay: one canvas over both cards (a viewport per card); it dissolves in over the footage, pixel aligned */
.replay { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 3; touch-action: pan-y; opacity: 0; pointer-events: none;
  transition: opacity .6s ease; cursor: grab; }
.replay:active { cursor: grabbing; }
.cards.three .replay { pointer-events: auto; }
.cards.three.shown .replay { opacity: 1; }
.cards.three .tagx, .cards.three .lens, .cards.three .ring, .cards.three .leader, .cards.three .auto { opacity: 0 !important; pointer-events: none; }
.r3d-ui { position: absolute; left: max(0px, 2 * var(--rvDX)); right: max(0px, -2 * var(--rvDX)); top: var(--rvTop); z-index: 6; display: grid; place-items: start center; pointer-events: none; }
.r3d-ui > * { grid-area: 1 / 1; pointer-events: auto; white-space: nowrap; }
.r3d-ui > .r3d-reset.on { opacity: 1; pointer-events: auto; }
/* in the 3D replay the two clocks glide to the cards' lower inner corners (where phones keep them), so Reset view has
   the top centre as in every other 3D stage */
#cards .chip { transition: background .5s, transform .6s cubic-bezier(.45, 0, .2, 1); }
@media (min-width: 600px) { #cards.three .chip { transform: translateY(calc(var(--H) - 1.6em - 100%)); } }
/* the 3D loading, in each card (not across the gap between them) */
.cards.r3d-loading .card .ov::after { content: "Loading the 3D scene"; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 7;
  padding: 7px 14px; border-radius: 999px; font-size: 13px; font-weight: 600; color: #fff; background: rgba(30,30,32,.45); white-space: nowrap; pointer-events: none; }
@media (max-width: 599px) { .cards.r3d-loading .card .ov::after { content: "Loading"; font-size: 12px; padding: 5px 11px; } }

/* more trials: the cards play the robot-camera recordings of the evaluation runs */
.media video.tv { display: none; inset: auto; left: 0; top: 0; object-fit: fill; }
.cards.trials .fv, .cards.trials .chip, .cards.trials .auto, .cards.trials .tagx, .cards.trials .lens, .cards.trials .ring, .cards.trials .leader { display: none; }
.cards.trials .tv { display: block; }
.media canvas.tv-hold { position: absolute; pointer-events: none; opacity: 0; display: none; }
.cards.trials .tv-hold { display: block; }

.transport { margin-top: 10px; display: flex; align-items: center; gap: 12px; padding: 6px 8px 6px 6px; border-radius: 999px; flex-wrap: nowrap; }
.round { width: 40px; height: 40px; border-radius: 50%; border: 0; flex: none; display: grid; place-items: center;
  background: linear-gradient(180deg, rgba(255,255,255,.22), rgba(255,255,255,.1)); box-shadow: inset 0 1px 0 rgba(255,255,255,.4); }
.round svg { width: 20px; height: 20px; fill: #fff; }
.round .i-replay .arc { fill: none; stroke: #fff; stroke-width: 2.7; stroke-linecap: round; }
.round .i-pause, .round .i-replay { display: none; }
.round.playing .i-play { display: none; }
.round.playing .i-pause { display: block; }
.round.ended .i-play { display: none; }
.round.ended .i-replay { display: block; }
.scrub { position: relative; flex: 1; height: 40px; min-width: 90px; cursor: pointer; touch-action: none; }
.scrub .track { position: absolute; left: 0; right: 0; top: 50%; height: 6px; margin-top: -3px; border-radius: 3px; background: rgba(255,255,255,.14); overflow: hidden; }
.scrub .fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: rgba(255,255,255,.75); border-radius: 3px; }
.scrub .rail { position: absolute; top: 0; bottom: 0; left: 14px; right: 14px; }    /* the knob stays inside the bar */
.scrub .marks { position: absolute; inset: 0; pointer-events: none; }
.scrub .mk { position: absolute; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%; box-shadow: 0 0 0 2px rgba(0,0,0,.25); }
.scrub .mk.bad { background: #e2675a; }
.scrub .mk.good { background: #59c287; }
.scrub .fast { position: absolute; top: 50%; height: 6px; margin-top: -3px; background: rgba(255,214,140,.45); border-radius: 3px; }
.scrub .knob { position: absolute; top: 50%; left: 0; width: 28px; height: 28px; margin: -14px 0 0 -14px; border-radius: 50%;
  background: rgba(255,255,255,.16); -webkit-backdrop-filter: blur(2px) saturate(180%); backdrop-filter: blur(2px) saturate(180%);
  box-shadow: inset 1.5px 1.5px 0 rgba(255,255,255,.75), inset -1px -1px 0 rgba(255,255,255,.3), 0 3px 10px rgba(0,0,0,.3); transition: transform .15s; }
.scrub:active .knob { transform: scale(1.18); }
.clock { font-variant-numeric: tabular-nums; color: var(--ink2); font-size: 13.5px; white-space: nowrap; }
.clock .tot { color: var(--ink3); }
#trialSeg .s { display: none; }

.score { margin-top: 14px; padding: 12px 18px 11px; border-radius: 22px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 32px; }
.sc-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.score .lbl { color: var(--ink); font-weight: 650; font-size: 14.5px; }
.score .lbl .sub { color: var(--ink3); font-weight: 500; }
.score .num { font-size: 24px; font-weight: 700; letter-spacing: -.02em; line-height: 1.1; font-variant-numeric: tabular-nums; }
.trk { position: relative; margin-top: 7px; height: 38px; display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); gap: 5px; align-items: end; }
.trk .col { position: relative; height: 100%; border: 0; padding: 0; border-radius: 6px; background: rgba(0,0,0,.05);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.07), inset 0 0 0 1px rgba(0,0,0,.025); overflow: hidden; cursor: default; }
.trk .col i { position: absolute; left: 0; right: 0; bottom: 0; height: 0; border-radius: 6px; transition: height .7s cubic-bezier(.2,.8,.2,1);
  background-image: linear-gradient(180deg, rgba(255,255,255,.42), rgba(255,255,255,.08) 55%, rgba(0,0,0,.04)); box-shadow: inset 0 1px 0 rgba(255,255,255,.55); }
.sc[data-side="js"] .col i { background-color: var(--js); } .sc[data-side="ours"] .col i { background-color: var(--ours); }
.trk .col.pick { cursor: pointer; }
.trk .col.pick::after { content: ""; position: absolute; left: 50%; top: 5px; width: 0; height: 0; margin-left: -3px; border-left: 6px solid rgba(29,29,31,.55);
  border-top: 4px solid transparent; border-bottom: 4px solid transparent; opacity: .0; transition: opacity .2s; }
.trk .col.pick:hover::after, .trk .col.pick:focus-visible::after { opacity: 1; }
.trk .col.pick:hover { outline: 1.5px solid rgba(29,29,31,.35); outline-offset: 2px; }
.trk .col.on, .trk .col.on:hover { outline: 2px solid rgba(29,29,31,.78); outline-offset: 2px; }
.trk .mean { position: absolute; left: 0; right: 0; height: 0; border-top: 1.5px dashed rgba(29,29,31,.45); bottom: 0; transition: bottom .7s cubic-bezier(.2,.8,.2,1); pointer-events: none; z-index: 2; }
.ours-c { color: var(--ours); } .js-c { color: var(--js); }
.ours-bg { background: var(--ours); } .js-bg { background: var(--js); }
.score-note { grid-column: 1 / -1; margin: 9px 0 0; font-size: 12.5px; text-align: left; }
.dotc { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex: none; }
.score-note { margin-top: 8px; font-size: 12.5px; }
.why { margin-top: 10px; }
.why summary { cursor: pointer; font-size: 15px; font-weight: 650; list-style: none; display: inline-flex; align-items: center; gap: 6px; }
.why summary::-webkit-details-marker { display: none; }
.why summary::after { content: ""; width: 7px; height: 7px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg) translateY(-3px);
  opacity: .6; transition: transform .25s; }
.why[open] summary::after { transform: rotate(-135deg) translate(-2px, -1px); }
.why-body { overflow: hidden; }
.why p { margin: 0; padding-top: 6px; max-width: 980px; color: var(--ink2); font-size: 14.5px; line-height: 1.55; }

/* narrower stage: the task line goes */
@container s1 (max-width: 820px) { .task-line { display: none; } }

/* ------------------------------------------------------------ section 1 on the white opening */
:is(.opening, .s4) .seg button[aria-selected="true"], :is(.opening, .s4) .seg button[aria-pressed="true"] { color: var(--ink); }
:is(.opening, .s4) .seg-thumb { background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.08), 0 3px 10px rgba(0,0,0,.08), inset 0 0 0 1px rgba(0,0,0,.04); }
:is(.opening, .s4) .seg.small { background: rgba(0,0,0,.045); box-shadow: inset 0 0 0 1px rgba(0,0,0,.04); }
:is(.opening, .s4) .seg.small button[aria-pressed="true"] { background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.08), 0 2px 8px rgba(0,0,0,.07); }
:is(.opening, .s4) .card { background: #e9e9ec; box-shadow: 0 14px 40px rgba(0,0,0,.13), 0 2px 6px rgba(0,0,0,.06); }
:is(.opening, .s4) .round { background: rgba(29,29,31,.9); box-shadow: inset 0 1px 0 rgba(255,255,255,.18), 0 2px 8px rgba(0,0,0,.18); }
:is(.opening, .s4) .round svg { fill: #fff; }
:is(.opening, .s4) .scrub .track { background: rgba(0,0,0,.09); }
:is(.opening, .s4) .scrub .fill { background: rgba(29,29,31,.72); }
:is(.opening, .s4) .scrub .fast { background: rgba(201,162,39,.38); }
:is(.opening, .s4) .scrub .knob { background: rgba(255,255,255,.7); box-shadow: inset 1.5px 1.5px 0 #fff, 0 0 0 1px rgba(0,0,0,.07), 0 3px 10px rgba(0,0,0,.18); }
:is(.opening, .s4) .bar { background: rgba(0,0,0,.07); }
:is(.opening, .s4) .ours-c { color: var(--ours-ink); } :is(.opening, .s4) .js-c { color: var(--js-ink); }

/* white -> the video's studio grey, where the live 3D begins */
.bleed { position: relative; height: clamp(100px, 10.5vw, 160px); background: linear-gradient(180deg, #f4f4f6 0.0%, #f3f3f5 8.3%, #eeeef0 16.7%, #e2e2e4 25.0%, #d0d0d1 33.3%, #b8b8b9 41.7%, #9e9e9e 50.0%, #848383 58.3%, #6c6b6b 66.7%, #5a5958 75.0%, #4e4d4c 83.3%, #494847 91.7%, #484746 100.0%); }

/* an author's name opens in place into the video end card's contact capsule (js/authors.js). Inline (room on its
   line, js/fit.js keeps it free): the photo grows out of the name's left edge while its space opens, and the glass forms
   around them; the glass reaches above and below without changing the line, so the other lines never move. */
.au { position: relative; display: inline-flex; align-items: baseline; isolation: isolate; border-radius: 999px; padding: 0;
  transition: padding .38s cubic-bezier(.2,.8,.2,1); }
.au::before { content: ""; position: absolute; z-index: -1; inset: -.3em 0; border-radius: 999px; pointer-events: none;
  background: rgba(20,20,22,.74); -webkit-backdrop-filter: blur(10px) saturate(160%); backdrop-filter: blur(10px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.2), inset 0 0 0 1px rgba(255,255,255,.06), 0 6px 18px rgba(0,0,0,.18);
  opacity: 0; transition: opacity .3s ease; }
.au-ph { position: relative; align-self: center; flex: none; width: 0; height: 1.6em; margin: -.35em 0;
  transition: width .38s cubic-bezier(.2,.8,.2,1), margin-right .38s cubic-bezier(.2,.8,.2,1); }
.au-ph img { position: absolute; right: 0; top: 0; width: 1.6em; height: 1.6em; border-radius: 50%; box-shadow: 0 0 0 1px rgba(255,255,255,.5);
  opacity: 0; transform: scale(.35); transform-origin: 100% 50%; transition: transform .38s cubic-bezier(.2,.8,.2,1), opacity .22s ease; }
.au a { transition: color .3s ease, background-size .25s ease; }
.au .eqc { position: relative; top: -.62em; transition: color .3s ease; }   /* a flex item: raised by position, as vertical-align .62em was */
.au.open { padding: 0 .8em 0 .24em; }
.au.open::before { opacity: 1; }
.au.open .au-ph { width: 1.6em; margin-right: .45em; }
.au.open .au-ph img { opacity: 1; transform: none; }
.au.open a { color: #fff; background-size: 0 1px; }
.au.open .eqc { color: rgba(255,255,255,.75); }
@media (max-width: 599px) {                                 /* phones: a slightly more compact capsule (js/fit.js keeps 2.8 em free) */
  .au-ph { height: 1.45em; margin: -.3em 0; } .au-ph img { width: 1.45em; height: 1.45em; }
  .au.open { padding: 0 .7em 0 .2em; } .au.open .au-ph { width: 1.45em; margin-right: .4em; }
}


/* ------------------------------------------------------------ section 2 */
/* One system for the tour (like section 1): the page column, a row with the steps and the tour button, the step's
   caption, then the stage. Every panel on the stage sits --in from the stage edge, panels stack --gp apart, and all share
   one padding and radius; on phones the panels leave the stage and follow it (js/stage2.js sets the stage height). */
.s2 { position: relative; margin-top: -2px; padding: 26px 0 28px; --in: 16px; --gp: 10px; --pad: 12px 14px; --rad: 18px;
  background: var(--studio); }                          /* section 3's bleed follows it */
.s2-in { max-width: var(--w); margin: 0 auto; padding: 0 var(--gut); }
.s2 .sec-head { max-width: none; margin: 0; padding: 0; }
.s2-top { margin-top: 18px; display: flex; align-items: center; gap: 10px 14px; }
.beats { display: flex; gap: 2px; padding: 4px; border-radius: 999px; min-width: 0; overflow-x: auto; scrollbar-width: none; scroll-snap-type: x proximity; }
.beats::-webkit-scrollbar { display: none; }      /* scrolls sideways only where the six steps do not fit (setStep keeps the current one in view) */
.beats button { position: relative; display: inline-flex; align-items: center; gap: 7px; border: 0; background: none; padding: 7px 14px 9px; min-height: 38px;
  border-radius: 999px; color: var(--ink3); font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; flex: none; }
.beats button .n { width: 20px; height: 20px; display: grid; place-items: center; border-radius: 50%; background: rgba(255,255,255,.1); font-size: 12px; }
.beats { position: relative; }
.beats button { z-index: 1; transition: color .3s; }
.beats button[aria-current="true"] { color: #fff; }                 /* the sliding glass thumb (.seg-thumb) marks it */
.beats button[aria-current="true"] .n { background: #fff; color: #2a2a2a; }
.beats button i { position: absolute; left: 14px; right: 14px; bottom: 4px; height: 2px; border-radius: 1px; background: rgba(255,255,255,.75); transform-origin: 0 50%; transform: scaleX(0); }
.tour { margin-left: auto; flex: none; border-radius: 999px; padding: 2px; }
.tour button { display: inline-flex; align-items: center; gap: 6px; border: 0; background: none; padding: 7px 14px 7px 10px; min-height: 38px; border-radius: 999px; font-weight: 600; font-size: 14px; }
.tour svg { width: 18px; height: 18px; fill: #fff; }
.tour .i-play { display: none; }
.tour.paused .i-play { display: block; }
.tour.paused .i-pause { display: none; }
/* the stage: the video's two cards (carousel), one canvas drawing into both, the overlays above it */
.m-stage { position: relative; margin-top: 14px; height: var(--s2H, 600px); overflow: hidden; border-radius: 22px; touch-action: pan-y;
  overflow-anchor: none; -webkit-user-select: none; user-select: none; }   /* overlays move every frame: never a scroll anchor; drags never select text */
.m-bg, .m-ov { position: absolute; left: 0; top: 0; will-change: transform, width; border-radius: 22px; }
.m-bg { background: radial-gradient(120% 90% at 55% 40%, #4f4e4d, #474645 70%); box-shadow: inset 0 0 0 1px rgba(255,255,255,.07), inset 0 1px 0 rgba(255,255,255,.1), 0 14px 40px rgba(0,0,0,.22); }
#mcanvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; z-index: 1; pointer-events: none; }
.m-ov { z-index: 2; pointer-events: none; overflow: hidden; }
.m-ov > * { pointer-events: auto; }
.m-ov .pill { top: 16px; font-size: clamp(13px, 1.1vw, 16px); padding: .4em .95em; }
.m-ov .pill.js { left: 16px; } .m-ov .pill.ours { right: 16px; }
.m-cap { position: absolute; left: 50%; bottom: 22px; transform: translateX(-50%); margin: 0; max-width: calc(100% - 40px); padding: 9px 18px; border-radius: 999px;
  font-size: clamp(15px, 1.45vw, 21px); font-weight: 600; color: #fff; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: rgba(30,30,32,.42); -webkit-backdrop-filter: blur(12px) saturate(160%); backdrop-filter: blur(12px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.18), 0 6px 20px rgba(0,0,0,.2); opacity: 0; pointer-events: none !important; }
.m-lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none !important; }
.m-lines line { stroke: rgba(255,255,255,.9); stroke-width: 2; stroke-linecap: round; filter: drop-shadow(0 1px 2px rgba(0,0,0,.35)); }
.m-posts { position: absolute; inset: 0; pointer-events: none !important; }
.m-post { position: absolute; margin: 0; width: calc(248px * var(--k3, 1)); padding: 6px; border-radius: 16px; opacity: 0; pointer-events: none;
  background: rgba(30,30,33,.4); -webkit-backdrop-filter: blur(12px) saturate(160%); backdrop-filter: blur(12px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.18), inset 0 0 0 1px rgba(255,255,255,.06), 0 10px 26px rgba(0,0,0,.28); }
.m-post-m { position: relative; aspect-ratio: 4 / 3; border-radius: 11px; overflow: hidden; background: #222; }
.m-post-m img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.m-post { cursor: pointer; }
.m-bead { position: absolute; width: 14px; height: 14px; margin: -7px 0 0 -7px; border-radius: 50%; opacity: 0; pointer-events: none !important;
  background: radial-gradient(circle at 35% 30%, rgba(255,255,255,.85), rgba(225,184,78,.85) 45%, rgba(146,114,30,.9));
  box-shadow: 0 0 0 1.5px rgba(255,255,255,.55), 0 2px 8px rgba(0,0,0,.35); transition: transform .2s; }
.m-bead.on { transform: scale(1.3); }
.m-bead.hover { width: 18px; height: 18px; margin: -9px 0 0 -9px; background: none; box-shadow: 0 0 0 2px rgba(255,255,255,.9), 0 0 12px rgba(225,184,78,.9); }
.m-pcl { position: absolute; transform: translate(-50%, -50%); padding: 5px 11px; border: 0; border-radius: 999px; font-size: 13px; font-weight: 650; color: #fff; cursor: pointer;
  background: color-mix(in srgb, var(--c) 72%, transparent); -webkit-backdrop-filter: blur(8px) saturate(170%); backdrop-filter: blur(8px) saturate(170%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 3px 10px rgba(0,0,0,.25); opacity: 0; transition: box-shadow .2s; }
.m-pcl.on { box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 0 0 2px rgba(255,255,255,.8), 0 3px 10px rgba(0,0,0,.25); }
.m-handtag { position: absolute; transform: translate(-50%, -50%); padding: 7px 14px; border-radius: 999px; font-size: 15px; font-weight: 650; color: #fff; opacity: 0;
  background: color-mix(in srgb, var(--c, #e1b84e) 72%, transparent); -webkit-backdrop-filter: blur(8px) saturate(170%); backdrop-filter: blur(8px) saturate(170%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 4px 14px rgba(0,0,0,.25); pointer-events: none !important; white-space: nowrap; }
.m-ego { position: absolute; opacity: 0; border-radius: 18px; padding: 0; overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.12), 0 14px 36px rgba(0,0,0,.35); background: #1d1d1f; }
.m-ego-media { position: absolute; inset: 0; overflow: hidden; }
.m-ego-media video { position: absolute; transform: scaleX(-1); max-width: none; }
.m-ego-media canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.m-ego-t { position: absolute; left: 14px; top: 14px; padding: 5px 12px; border-radius: 999px; font-size: 13.5px; font-weight: 600; color: #fff;
  background: rgba(18,18,18,.6); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
.m-ego-replay { position: absolute; right: 12px; bottom: 12px; width: 40px; height: 40px; border-radius: 50%; border: 0; display: none; place-items: center; cursor: pointer; }
.m-ego-replay svg { width: 20px; height: 20px; fill: #fff; } .m-ego-replay .arc { fill: none; stroke: #fff; stroke-width: 2.7; stroke-linecap: round; }
.m-ego.ended .m-ego-replay { display: grid; }
.m-stage { cursor: grab; }                                  /* the hand can be turned; the lit points and controls set their own */
.m-stage.grabbing { cursor: grabbing; }
.m-reset.on { opacity: 1; pointer-events: auto; }
.m-stage .loading { z-index: 4; }
.m-stage.ready .loading { opacity: 0; }
.m-under { display: flex; align-items: center; gap: 12px 20px; margin-top: 12px; min-height: 40px; flex-wrap: wrap; }
.m-capn { display: none; }
.m-sub { margin: 0; flex: 1 1 420px; max-width: 760px; color: var(--ink2); font-size: 14.5px; line-height: 1.5; }
.m-scale { display: none; align-items: center; gap: 12px; padding: 6px 16px; border-radius: 999px; font-size: 13.5px; color: var(--ink2); margin-left: auto; }
.m-scale.on { display: inline-flex; }
.m-scale input { width: 200px; }
.m-dirs { display: none; gap: 8px; margin-left: auto; }
.m-dirs.on { display: flex; }
.m-dir { display: inline-flex; align-items: center; gap: 10px; padding: 4px 14px; border-radius: 999px; font-size: 13.5px; font-weight: 650; color: #fff; }
.m-dir span { min-width: 3.1em; color: color-mix(in srgb, var(--c) 55%, #fff); }
.m-dir input { width: 130px; --fill: color-mix(in srgb, var(--c) 70%, transparent); }
.m-dir input::-webkit-slider-runnable-track { background: linear-gradient(90deg, transparent 49.4%, rgba(255,255,255,.45) 49.4% 50.6%, transparent 50.6%), color-mix(in srgb, var(--c) 35%, rgba(255,255,255,.1)); }
.m-dir input::-moz-range-track { background: color-mix(in srgb, var(--c) 35%, rgba(255,255,255,.1)); }
.m-scale output { font-variant-numeric: tabular-nums; width: 44px; text-align: right; color: var(--ink); }

/* glass slider */
input[type=range] { -webkit-appearance: none; appearance: none; height: 32px; background: none; margin: 0; cursor: pointer; touch-action: none; }
input[type=range]::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: rgba(255,255,255,.16); }
input[type=range]::-moz-range-track { height: 6px; border-radius: 3px; background: rgba(255,255,255,.16); }
input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 24px; height: 24px; margin-top: -9px; border-radius: 50%; border: 0;
  background: #ededf0; box-shadow: 0 2px 8px rgba(0,0,0,.35), 0 0 0 3px var(--fill, rgba(255,255,255,.0)); }
input[type=range]::-moz-range-thumb { width: 24px; height: 24px; border-radius: 50%; border: 0; background: #f4f4f6; box-shadow: 0 2px 8px rgba(0,0,0,.35), 0 0 0 3px var(--fill, transparent); }

.loading { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: var(--ink3); font-size: 14px; pointer-events: none; transition: opacity .6s; }
.loading.done { opacity: 0; }
.spinner { width: 22px; height: 22px; border-radius: 50%; border: 2px solid rgba(255,255,255,.2); border-top-color: #fff; display: inline-block; margin-right: 10px; vertical-align: -6px; animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ------------------------------------------------------------ Fig. 1, alive (js/fig1.js) */
/* the paper's four panels, drawn by its own generator, on light glass cards in section 1's page column; each panel builds
   itself when the row comes into view (axes, command, samples, hands, verdict), then fresh samples keep lighting up */
.fig1 { margin-top: 56px; }
.fig1-title { margin: 0 0 14px; font-size: 20px; font-weight: 650; letter-spacing: -.005em; }
.fig1-cap { margin: -6px 0 16px; max-width: 760px; color: var(--ink2); font-size: 15px; line-height: 1.5; text-wrap: pretty; }   /* what the panels plot, then the one-line takeaway */
.fig1-grid { position: relative; -webkit-user-select: none; user-select: none; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
.f1-gl { position: absolute; left: 0; top: 0; z-index: 2; pointer-events: none; }      /* js/fig1hands.js: every hand, live */
.fig1.live3d .f1-svg :is(.hand, .res-hand) image { visibility: hidden; }
/* a hand, large, in its own card (js/fig1hands.js): a light layer over the plot while the hand grows on it; drag to orbit */
.f1-zoom { position: absolute; z-index: 1; border-radius: 14px; opacity: 0; touch-action: none; cursor: grab; -webkit-user-select: none; user-select: none;
  background: radial-gradient(110% 90% at 50% 42%, rgba(255,255,255,.98), rgba(243,243,244,.97) 72%); box-shadow: inset 0 0 0 1px rgba(0,0,0,.04); }
.f1-zoom:active { cursor: grabbing; }
.f1-zh { position: absolute; left: 50%; bottom: 8px; transform: translateX(-50%); font-size: 11.5px; font-weight: 600; color: #8c8c8c; white-space: nowrap; pointer-events: none; }
.f1-zx { position: absolute; right: 7px; top: 7px; width: 30px; height: 30px; display: grid; place-items: center; padding: 0 0 2px; border: 0; border-radius: 50%;
  font: 400 20px/1 var(--font); color: #3a3a3a; background: rgba(0,0,0,.06); cursor: pointer; transition: background .2s; }
.f1-zx:hover { background: rgba(0,0,0,.11); }
.f1-zx:focus-visible { outline-color: rgba(0,0,0,.6); }
.f1p { container-type: inline-size; margin: 0; padding: 8px 8px 14px; border-radius: 22px; display: flex; flex-direction: column; position: relative; color: #262626;
  background: linear-gradient(180deg, rgba(255,255,255,.95), rgba(255,255,255,.86));
  box-shadow: inset 0 1px 0 #fff, inset 0 0 0 1px rgba(0,0,0,.05), 0 1px 2px rgba(0,0,0,.08), 0 12px 30px rgba(0,0,0,.2); }
.f1-svg { aspect-ratio: 280 / 344.9; }
.f1-svg svg { width: 100%; height: auto; overflow: visible; }
.f1-rule { margin-top: auto; padding: 6px 6px 0; display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }
.f1-rule .eqline { font-family: "Times New Roman", Times, serif; font-style: italic; font-size: min(17px, 6.1cqi); line-height: 1.25; color: #262626; white-space: nowrap; }
.f1-rule .eqline sub, .f1-rule .eqline sup { font-size: .68em; line-height: 0; }
.f1-rule .eqline sup.st { font-family: "STIX Two Math", "Cambria Math", "Apple Symbols", "Segoe UI Symbol", serif; font-style: normal; font-size: .95em; vertical-align: .32em; margin-left: .04em; }
.f1-rule .a { color: #2E6688; } .f1-rule .n { color: #95651D; }
.f1-meta { display: flex; align-items: center; gap: 10px; min-height: 28px; }
.f1-rule .dims { font-size: 13px; font-weight: 600; color: #686868; }
/* the entrance (only once js/fig1.js runs: without it the figure is simply there): each card's content fades up at once,
   the cards a moment apart; the whole row is in within about .7 s */
.fig1 .cloud circle { transform-box: fill-box; transform-origin: center; }
.fig1.anim .f1p > * { opacity: 0; transform: translateY(6px); transition: opacity .45s ease, transform .5s cubic-bezier(.2,.8,.2,1); }
.fig1.anim .f1p.go > * { opacity: 1; transform: none; }
.fig1.anim .f1p.done > * { transition: none; }
/* ------------------------------------------------------------ section 3: training. The video's training studio, carried
   onto the page: the section is the studio's own gradient (sampled from the cards: js/s3.js), so the two cards sit in
   it without edges; warm dark method section above, the dark footer below (bleeds both ways) */
:root { --s3a: #575757; --tgTop: #757575; --tgBot: #b4b4b4; --stTop: 250px; --stH: 483px;
  --tg: linear-gradient(180deg, #757575 0%, #616161 10%, #626262 20%, #6f6f6f 30%, #8d8d8d 40%, #a1a1a1 50%, #ababab 60%, #b1b1b1 70%, #b4b4b4 80%, #b4b4b4 100%); }
/* the studio's grain (site_lab/tools/make_grain.py, matched to the cards'): one overlay over the whole section, faded in
   across the bleed from section 2 and out before the bleed into the footer, so no line shows where it starts or stops */
.bleed.b23 { height: clamp(100px, 10.5vw, 160px); background: linear-gradient(180deg, #484746 0.0%, #484746 8.3%, #494847 16.7%, #4a4948 25.0%, #4b4a4a 33.3%, #4d4c4c 41.7%, #4f4f4e 50.0%, #525151 58.3%, #545453 66.7%, #555555 75.0%, #565656 83.3%, #575757 91.7%, #575757 100.0%); }
.bleed.b23::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: url(../assets/s3/grain.png) 0 100% / 256px 256px;
  mix-blend-mode: soft-light; -webkit-mask-image: linear-gradient(180deg, transparent, #000); mask-image: linear-gradient(180deg, transparent, #000); }
.s3 { --H3: 520px; --band: 168px; position: relative; overflow-x: clip; isolation: isolate;
  /* painted in fixed-size layers, so the section growing (the paper's figure opening) never repaints them: the studio
     floor's grey (the section itself); the wall's gradient and the cards' own gradient behind them (::before, its
     height fixed by the stage's place); the grain over all of it (::after, a tiled image blended on the GPU) */
  background: var(--tgBot); }
.s3::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: calc(var(--stTop) + var(--stH)); z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, var(--s3a), var(--tgTop) calc(100% - 2px)) 0 0 / 100% calc(var(--stTop) + 2px) no-repeat, var(--tg) 0 var(--stTop) / 100% var(--stH) no-repeat; }
.s3::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; background: url(../assets/s3/grain.png) 0 0 / 256px 256px; mix-blend-mode: soft-light;
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 180px), transparent); mask-image: linear-gradient(180deg, #000 calc(100% - 180px), transparent); }
.s3-in { max-width: var(--w); margin: 0 auto; padding: 26px var(--gut) 28px; }
.s3 .sec-head { max-width: none; margin: 0; padding: 0; }
.s3 .seg-thumb { transition: none; }                       /* it travels with the playhead (s3.js), frame by frame */
.t-top { margin-top: 18px; display: flex; align-items: center; gap: 10px 14px; }
#tStops button { padding: 7px 15px; min-height: 38px; font-size: 14.5px; font-variant-numeric: tabular-nums; }
#tPlay { margin-left: auto; }
/* the two cards; one canvas draws into both (clipped to their shapes). Behind them, as wide as the page, the studio's
   gradient at the cards' own heights: the cards have no edge against it */
.t-stage { position: relative; margin-top: 12px; height: var(--H3); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px;
  touch-action: pan-y; -webkit-user-select: none; user-select: none; overflow-anchor: none; cursor: grab; }
.t-stage.grabbing { cursor: grabbing; }
.t-card { position: relative; border-radius: 22px; overflow: hidden; font-size: 14px; background: var(--tg); }
.t-card .pill { z-index: 3; }
.t-canvas { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 2; pointer-events: none; }
.t-stage .loading { z-index: 4; color: rgba(255,255,255,.9); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 14px; }
.t-stage .loading > span { display: inline-flex; align-items: center; justify-content: center; min-width: 0; white-space: nowrap; }   /* one in each card */
.t-stage .loading .l { white-space: pre; }                   /* a flex item: keep its leading space ("Loading the …") */
@media (max-width: 759px) { .t-stage .loading { column-gap: 8px; font-size: 12.5px; } .t-stage .loading .spinner { width: 18px; height: 18px; margin-right: 7px; } .t-stage .loading .l { display: none; } }
.t-stage.ready .loading { opacity: 0; }
.t-reset.on { opacity: 1; pointer-events: auto; }
/* the curve band: the video's dark glass slab (tint 42, 42, 47), the plot drawn in it; drag along it to scrub */
.t-band { position: relative; margin-top: 12px; height: var(--band); border-radius: 22px; color: #fff; touch-action: none; cursor: pointer; }
.t-band, .t-paper { background: rgba(42, 42, 47, .86); -webkit-backdrop-filter: blur(16px) saturate(150%); backdrop-filter: blur(16px) saturate(150%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16), inset 0 0 0 1px rgba(255,255,255,.06), 0 12px 32px rgba(0,0,0,.18); }
.t-paper { background: rgba(40, 40, 45, .9); -webkit-backdrop-filter: none; backdrop-filter: none; }   /* over a smooth grey a live blur looks the same: none, so opening it stays light */
.t-plot { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; font-family: var(--font); }
.t-plot text { fill: rgba(255,255,255,.62); font-size: 12px; font-weight: 500; font-variant-numeric: tabular-nums; }
.t-plot .tt { fill: rgba(255,255,255,.92); font-size: 14.5px; font-weight: 650; }
.t-plot .rv { fill: #fff; font-size: 17px; font-weight: 700; }
.t-plot .rk { fill: rgba(255,255,255,.58); font-size: 12px; }
.t-tag { position: absolute; padding: 4px 11px; border-radius: 999px; font-size: 12.5px; font-weight: 650; color: #fff; white-space: nowrap; pointer-events: none;
  background: rgba(236, 104, 82, .82); box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 4px 14px rgba(236,104,82,.35); opacity: 0; transform: translateY(6px);
  transition: opacity .4s ease, transform .5s cubic-bezier(.2,.8,.2,1); }
.t-tag.on { opacity: 1; transform: none; }
.t-more-row { margin-top: 14px; display: flex; justify-content: center; }
.t-more { min-height: 40px; padding: 8px 14px 8px 18px; font-size: 14.5px; color: #fff; }
.s3 .t-more.glass { background: rgba(42, 42, 47, .82); }          /* on the studio floor's light grey: the band's dark glass */
.s3 .t-more.glass:hover { background: rgba(52, 52, 58, .9); }
.t-more svg { width: 16px; height: 16px; transition: transform .35s cubic-bezier(.2,.8,.2,1); }
.t-more[aria-expanded="true"] svg { transform: rotate(180deg); }

/* the paper's Fig. 3 (js/fig3panel.js), drawn like the band: dark glass, glowing curves, glass bars */
.t-paper { border-radius: 22px; color: #fff; }                 /* its spacing is inside, so the open / close glide has nothing left to snap */
.t-paper-in { padding: 14px 18px 12px; }
.f3-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px; }
.f3-head h3 { margin: 0; font-size: 14.5px; font-weight: 650; color: rgba(255,255,255,.92); }
.f3-legend { display: flex; flex-wrap: wrap; gap: 4px 6px; margin-left: auto; }
.f3-legend button { display: inline-flex; align-items: center; gap: 6px; border: 0; padding: 4px 10px 4px 8px; min-height: 28px; border-radius: 999px; font-weight: 600; font-size: 12.5px;
  color: rgba(255,255,255,.86); background: rgba(255,255,255,.07); box-shadow: inset 0 0 0 1px rgba(255,255,255,.08); transition: background .25s, box-shadow .25s; }
.f3-legend i { width: 9px; height: 9px; border-radius: 50%; background: var(--c); box-shadow: 0 0 6px var(--c); }
.f3-legend .s { display: none; }
.f3-legend button[aria-pressed="true"] { background: rgba(255,255,255,.16); box-shadow: inset 0 0 0 1.5px var(--c); }
.f3-groups { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 26px; margin-top: 10px; }
.f3-g h4 { margin: 0 0 2px; font-size: 12.5px; font-weight: 600; color: rgba(255,255,255,.6); } .f3-g h4 b { color: #fff; }
.f3-row { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: 12px; }
.f3-c { position: relative; height: 168px; }
.f3-cv, .f3-ov { position: absolute; inset: 0; width: 100%; height: 100%; }
.f3-ov { overflow: visible; touch-action: pan-y; }
.f3-svg text { fill: rgba(255,255,255,.5); font-size: 11px; font-variant-numeric: tabular-nums; }
.f3-svg .f3-t { fill: rgba(255,255,255,.82); font-size: 12px; font-weight: 600; }
.f3-svg .f3-v { fill: rgba(255,255,255,.88); font-weight: 650; }
.f3-grid { stroke: rgba(255,255,255,.08); } .f3-base { stroke: rgba(255,255,255,.3); }
.f3-ci { stroke: rgba(255,255,255,.85); stroke-width: 1.3; fill: none; }
.f3-m { transition: opacity .3s; }
.t-paper[data-focus="jabs"] .f3-m:not([data-m="jabs"]), .t-paper[data-focus="eajr"] .f3-m:not([data-m="eajr"]),
.t-paper[data-focus="jaer"] .f3-m:not([data-m="jaer"]), .t-paper[data-focus="ours"] .f3-m:not([data-m="ours"]) { opacity: .16; }
.f3-rule { stroke: rgba(255,255,255,.55); stroke-width: 1; opacity: 0; } .f3-dot { opacity: 0; stroke: #fff; stroke-width: 1.5; }
.f3-c.reading .f3-rule, .f3-c.reading .f3-dot { opacity: 1; }
.f3-tip { position: absolute; top: 18px; display: grid; gap: 1px; padding: 5px 8px; border-radius: 10px; font-size: 11.5px; font-variant-numeric: tabular-nums; pointer-events: none; color: #fff;
  background: rgba(24,24,28,.9); box-shadow: inset 0 0 0 1px rgba(255,255,255,.1), 0 6px 18px rgba(0,0,0,.3); opacity: 0; transition: opacity .2s; white-space: nowrap; }
.f3-tip span { display: flex; align-items: center; gap: 6px; } .f3-tip i { width: 7px; height: 7px; border-radius: 50%; background: var(--c); }
.f3-c.reading .f3-tip { opacity: 1; }
.f3-cap { margin: 8px 0 0; font-size: 11.5px; line-height: 1.45; color: rgba(255,255,255,.52); text-wrap: pretty; }
.f3-cap .s, .f3-g h4 .s { display: none; }
@media (max-width: 999px) { .f3-groups { grid-template-columns: 1fr; } }
@media (max-width: 759px) {
  /* phones: the two cards side by side as squares, like section 1 */
  .s3 { --band: 138px; }
  .t-stage { height: auto; gap: 8px; }
  .s3-in { padding-bottom: 22px; }
  .t-card { aspect-ratio: 1; border-radius: 16px; font-size: 9.5px; }
  .t-card .pill { top: .7em; padding: .3em .75em; } .t-card .pill.js { left: .7em; } .t-card .pill.ours { right: .7em; }
  .t-band, .t-paper { border-radius: 18px; }
  .t-top { margin-top: 14px; }
  #tStops { flex: 1; min-width: 0; } #tStops button { flex: 1; padding: 6px 4px; min-height: 36px; font-size: 13px; }
  .t-plot .tt { font-size: 13px; } .t-plot .rv { font-size: 15px; } .t-plot text { font-size: 11px; }
  .t-tag { font-size: 11px; padding: 3px 9px; }
  /* the paper's figure, compact: one header row, one legend row, each panel's bars and curves side by side */
  .t-paper-in { padding: 10px 10px 8px; }
  .f3-head h3 { font-size: 13px; }
  .f3-legend { margin-left: 0; width: 100%; flex-wrap: nowrap; gap: 4px; }
  .f3-legend button { flex: 1; justify-content: center; padding: 3px 4px; min-height: 26px; font-size: 11px; gap: 4px; }
  .f3-legend .l { display: none; } .f3-legend .s { display: inline; }
  .f3-groups { gap: 6px; margin-top: 6px; }
  .f3-g h4 { font-size: 11.5px; }
  .f3-row { gap: 6px; }
  .f3-c { height: 122px; }
  .f3-svg text { font-size: 9.5px; } .f3-svg .f3-t { font-size: 10.5px; }
  .f3-cap { font-size: 10.5px; margin-top: 6px; }
  .f3-cap .l, .f3-g h4 .l { display: none; } .f3-cap .s, .f3-g h4 .s { display: inline; }
}

/* ------------------------------------------------------------ section 4: in-hand reorientation on the real Allegro hand.
   Light again, like the opening: the lab's warm white (its wall and table under soft light). The studio floor's grey
   above bleeds into it, the footer's dark below. The light glass rules are shared with the opening (:is(.opening, .s4)). */
:root { --s4bg: #efeeeb; }
.bleed.b34 { height: clamp(100px, 10.5vw, 160px); background: linear-gradient(180deg, color-mix(in oklab, var(--tgBot) 100.0%, var(--s4bg)) 0.0%, color-mix(in oklab, var(--tgBot) 99.5%, var(--s4bg)) 8.3%, color-mix(in oklab, var(--tgBot) 96.5%, var(--s4bg)) 16.7%, color-mix(in oklab, var(--tgBot) 89.6%, var(--s4bg)) 25.0%, color-mix(in oklab, var(--tgBot) 79.0%, var(--s4bg)) 33.3%, color-mix(in oklab, var(--tgBot) 65.3%, var(--s4bg)) 41.7%, color-mix(in oklab, var(--tgBot) 50.0%, var(--s4bg)) 50.0%, color-mix(in oklab, var(--tgBot) 34.7%, var(--s4bg)) 58.3%, color-mix(in oklab, var(--tgBot) 21.0%, var(--s4bg)) 66.7%, color-mix(in oklab, var(--tgBot) 10.4%, var(--s4bg)) 75.0%, color-mix(in oklab, var(--tgBot) 3.5%, var(--s4bg)) 83.3%, color-mix(in oklab, var(--tgBot) 0.5%, var(--s4bg)) 91.7%, color-mix(in oklab, var(--tgBot) 0.0%, var(--s4bg)) 100.0%); }
.bleed.b4f { height: clamp(100px, 10.5vw, 160px); background: linear-gradient(180deg, color-mix(in oklab, var(--s4bg) 100.0%, #2a2928) 0.0%, color-mix(in oklab, var(--s4bg) 99.5%, #2a2928) 8.3%, color-mix(in oklab, var(--s4bg) 96.5%, #2a2928) 16.7%, color-mix(in oklab, var(--s4bg) 89.6%, #2a2928) 25.0%, color-mix(in oklab, var(--s4bg) 79.0%, #2a2928) 33.3%, color-mix(in oklab, var(--s4bg) 65.3%, #2a2928) 41.7%, color-mix(in oklab, var(--s4bg) 50.0%, #2a2928) 50.0%, color-mix(in oklab, var(--s4bg) 34.7%, #2a2928) 58.3%, color-mix(in oklab, var(--s4bg) 21.0%, #2a2928) 66.7%, color-mix(in oklab, var(--s4bg) 10.4%, #2a2928) 75.0%, color-mix(in oklab, var(--s4bg) 3.5%, #2a2928) 83.3%, color-mix(in oklab, var(--s4bg) 0.5%, #2a2928) 91.7%, color-mix(in oklab, var(--s4bg) 0.0%, #2a2928) 100.0%); }
.s4 { --H: 440px; --k: 1; --cg: 14px; position: relative; color-scheme: light; background: var(--s4bg); color: var(--ink);
  --ink: #1d1d1f; --ink2: rgba(29, 29, 31, .74); --ink3: rgba(29, 29, 31, .52); --line: rgba(0, 0, 0, .08); --ours-ink: #9a780f; --js-ink: #47709a; }
.s4-in { max-width: var(--w); margin: 0 auto; padding: 26px var(--gut) 28px; }
.s4 .sec-head { max-width: none; margin: 0; padding: 0; }
.d-top { margin-top: 18px; }
.d-top #dSpeed { margin-left: auto; }
.s4 .seg.small button { min-height: 34px; padding: 5px 11px; font-size: 13.5px; }
.s4 .seg.small button .k { opacity: .6; font-weight: 500; }
/* the cards: the overview video's overscan canvas (the filmed frame on its static top extension, baked into the web
   video), placed by js/s4.js so the hand, the cube and the goal cube above it always show; the AR layer on a canvas */
.d-cards .media video.fv { inset: auto; left: 0; top: 0; width: auto; height: auto; object-fit: fill; background: #d9d8d5; }
.d-cards .card { background: #d9d8d5; }
/* each card's first frame, before any script runs (a direct jump here in the first seconds never shows an empty card);
   the video covers it as soon as it is placed */
.d-cards .card[data-side="js"] .media { background: url(../assets/footage/dex_js_wide.jpg) 52% 35% / cover no-repeat; }
.d-cards .card[data-side="ours"] .media { background: url(../assets/footage/dex_ours_wide.jpg) 52% 35% / cover no-repeat; }
@media (max-width: 759px) {
  .d-cards .card[data-side="js"] .media { background-image: url(../assets/footage/dex_js_sq.jpg); background-position: 50% 50%; }
  .d-cards .card[data-side="ours"] .media { background-image: url(../assets/footage/dex_ours_sq.jpg); background-position: 50% 50%; }
}
.d-ar { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 3; pointer-events: none; opacity: 0; transition: opacity .35s ease; }
.d-ar.on { opacity: 1; }
.d-snap, .v-snap { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 3; pointer-events: none; opacity: 0; }   /* the outgoing view's still (js/s1.js, js/s4.js) */                     /* the cubes appear once the video's 3D cube is ready (no stand-in first) */
/* how the run ends, as it happens (the baseline's drop, our run getting stuck): a second line in the counter's glass,
   its corner over the table. The count and its word stay together on the first line; the second line takes no room
   until it shows, then widens and opens smoothly */
.d-cards .d-count { display: inline-flex; flex-direction: column; align-items: flex-start; transition: border-radius .35s ease; }
.d-count .top { display: inline-flex; align-items: baseline; gap: .38em; }
.d-count .end { display: flex; align-items: center; gap: .4em; max-width: 0; max-height: 0; opacity: 0; overflow: hidden; font-size: .74em; font-weight: 600;
  color: rgba(29,29,31,.66); line-height: 1.25; white-space: nowrap;
  transition: max-width .45s cubic-bezier(.45, 0, .2, 1), max-height .4s cubic-bezier(.45, 0, .2, 1), opacity .35s ease, margin .4s cubic-bezier(.45, 0, .2, 1); }
.d-count.ended { border-radius: 1em; }
.d-count.ended .end { max-width: 24em; max-height: 2em; opacity: 1; margin-top: .1em; }
.d-count .end .s { display: none; }
.d-count .end i { width: .62em; height: .62em; border-radius: 50%; background: #c8463a; flex: none; }
.d-count .end i.stuck { background: #d39b45; }
.s4 .scrub .mk.stuck { background: #e1b84e; }
@media (max-width: 599px) { .d-count .end .l { display: none; } .d-count .end .s { display: inline; } }
/* the paper's Fig. 4 under the score (js/fig3panel.js initFig4): section 3's panel, in light glass on this light page */
.s4 .t-more { color: var(--ink); }
.d-paper { background: rgba(255,255,255,.74); color: var(--ink); box-shadow: inset 0 1px 0 #fff, inset 0 0 0 1px rgba(0,0,0,.05), 0 1px 2px rgba(0,0,0,.05), 0 8px 24px rgba(0,0,0,.07); }
.d-paper .f3-head h3 { color: var(--ink); }
.d-paper .f3-legend button { color: rgba(29,29,31,.78); background: rgba(0,0,0,.04); }
.d-paper .f3-legend button[aria-pressed="true"] { background: rgba(0,0,0,.07); }
.d-paper .f3-cap { color: var(--ink3); }
.d-paper .f3-rule { stroke: rgba(29,29,31,.45); }
.f3-groups.one { grid-template-columns: 1fr; }
.f3-groups.one .f3-row { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: 22px; }
@media (max-width: 759px) { .f3-groups.one .f3-row { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: 6px; } }
.d-cards .ov { overflow: hidden; border-radius: inherit; }
.d-count { position: absolute; left: .8em; bottom: .8em; display: inline-flex; align-items: baseline; gap: .38em; padding: .34em .9em .4em;
  border-radius: 999px; background: rgba(255,255,255,.8); color: #1d1d1f; font-weight: 600; font-size: 1.02em; line-height: 1.2; white-space: nowrap;
  -webkit-backdrop-filter: blur(12px) saturate(170%); backdrop-filter: blur(12px) saturate(170%); box-shadow: 0 4px 14px rgba(0,0,0,.16), inset 0 1px 0 rgba(255,255,255,.9); }
.d-count .n { position: relative; display: inline-block; overflow: hidden; height: 1.2em; font-size: 1.45em; font-weight: 700; letter-spacing: -.01em;
  font-variant-numeric: tabular-nums; line-height: 1.2; vertical-align: -.12em; }
.d-count .n span { display: block; }
.d-count .w { font-weight: 550; color: rgba(29,29,31,.78); }
.d-goal { position: absolute; left: 0; top: 0; padding: .28em .8em; border-radius: 999px; font-size: .92em; font-weight: 650; color: #1d1d1f;
  background: rgba(255,255,255,.78); -webkit-backdrop-filter: blur(10px) saturate(170%); backdrop-filter: blur(10px) saturate(170%);
  box-shadow: 0 3px 10px rgba(0,0,0,.12), inset 0 1px 0 rgba(255,255,255,.9); white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity .4s ease; }
.d-goal.on { opacity: 1; }
.d-cards .tagx { z-index: 2; }
/* the 3D replay (js/dex3d.js) over both cards, as section 1's: the clock and the Goal bubble step back (the transport
   keeps the time); Reset sits at the top centre of the stage, between the two names */
.d-cards .chip { transition: background .5s, opacity .4s ease; }
.d-cards.three .chip, .d-cards.three .d-goal { opacity: 0 !important; pointer-events: none; }
.d-cards .tagx.neutral i { background: rgba(29,29,31,.45); }
.d-cards.trials .fv, .d-cards.trials .d-ar, .d-cards.trials .d-goal, .d-cards.trials .tagx { display: none; }
/* more trials: the reviewer site's clips (the same trials, cut and cube overlay), rendered without their text
   (tools/render_dex_trials_web.py) and cropped to the card by js/s4.js; the counter, the speed, the notes and the goal
   are the page's own glass, from the clips' timelines */
.d-cards.trials .chip { display: inline-flex; }
.d-cards.trials .chip.fast { background: rgba(255, 214, 140, .85); }
.d-tgoal { position: absolute; top: .8em; display: none; flex-direction: column; align-items: center; gap: .1em; padding: .35em .45em .3em; border-radius: .9em;
  background: rgba(255,255,255,.78); color: #1d1d1f; font-size: .86em; font-weight: 650; line-height: 1.1;
  -webkit-backdrop-filter: blur(10px) saturate(170%); backdrop-filter: blur(10px) saturate(170%); box-shadow: 0 3px 10px rgba(0,0,0,.14), inset 0 1px 0 rgba(255,255,255,.9); }
.d-tgoal canvas { width: 3.4em; height: 3.4em; display: block; }
.card[data-side="js"] .d-tgoal { right: .8em; } .card[data-side="ours"] .d-tgoal { left: .8em; }
.d-cards.trials .d-tgoal { display: flex; }
.d-cards.trials .chip { top: auto; bottom: .8em; }
.d-cards.trials .card[data-side="js"] .chip { right: .8em; left: auto; } .d-cards.trials .card[data-side="ours"] .chip { right: .8em; left: auto; }

.scrub .tk { position: absolute; top: 50%; width: 2px; height: 5px; margin-left: -1px; border-radius: 1px; pointer-events: none; }
.scrub .tk.js { margin-top: -9px; background: var(--js); }
.scrub .tk.ours { margin-top: 4px; background: var(--ours); }
#dTrial .s, #dView .s { display: none; }
.d-note { margin: 10px 2px 0; font-size: 13px; max-width: 900px; }      /* js/s4.js gives it the height of its tallest text: nothing below moves */
/* the paper's 40 evaluation trials per method: each trial's successes, sorted, with the mean (dashed), on one scale */
.d-score { margin-top: 12px; padding: 12px 18px 11px; border-radius: 22px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 32px; }
.d-score .sc-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.d-score .lbl { color: var(--ink); font-weight: 650; font-size: 14.5px; }
.d-score .lbl .sub { color: var(--ink3); font-weight: 500; }
.d-score .num { font-size: 24px; font-weight: 700; letter-spacing: -.02em; line-height: 1.1; font-variant-numeric: tabular-nums; white-space: nowrap; }
.d-score .num small { font-size: 13px; font-weight: 650; letter-spacing: 0; margin-left: 6px; color: var(--ours-ink); }
.d-score .trk { grid-template-columns: repeat(40, minmax(0, 1fr)); gap: 2px; height: 46px; }
.d-score .trk .col { border-radius: 3px; overflow: visible; background: rgba(0,0,0,.03); box-shadow: none; }        /* 40 a side: faint slots, the bars carry it */
.d-score .trk .col i { border-radius: 3px; }
.d-score .trk .col.pick { background: rgba(0,0,0,.075); }
.d-score .trk .col.pick::before { content: ""; position: absolute; left: -5px; right: -5px; top: -4px; bottom: -4px; }         /* a bigger target */
.d-score .trk .col.pick::after { top: auto; bottom: calc(100% + 3px); left: 50%; margin-left: -2.5px; width: 5px; height: 5px; border: 0; border-radius: 50%;
  background: rgba(29,29,31,.5); opacity: 1; }
.d-score .trk .col.pick:hover::after, .d-score .trk .col.on::after { background: rgba(29,29,31,.9); }
.d-score .score-note { grid-column: 1 / -1; margin: 9px 0 0; font-size: 12.5px; text-align: left; }
@media (max-width: 599px) {
  .s4 { --cg: 8px; }
  .s4-in { padding-bottom: 22px; }
  .s2 { padding-bottom: 22px; }
  .s4 .sec-head h2 { font-size: 25px; }
  .s4 .lead { font-size: 15px; line-height: 1.5; }
  .d-top { margin-top: 12px; gap: 8px; }
  .d-top { flex-wrap: nowrap; }
  .d-top #dView { flex: 1 1 auto; min-width: 0; }
  .d-top #dView button { flex: 1; padding-left: 4px; padding-right: 4px; }
  #dView .l { display: none; } #dView .s { display: inline; }
  .d-cards .pill { top: .5em; font-size: .94em; padding: .26em .66em; }       /* clear of the goal cube above the hand */
  .d-cards .pill.js { left: .55em; } .d-cards .pill.ours { right: .55em; }
  .s4 .seg.small button { padding-left: 8px; padding-right: 8px; }
  .d-cards .chip, .d-cards.trials .chip { display: none; }          /* the transport has the time; trials: the note carries the speed */
  .d-count { left: .7em; bottom: .7em; padding: .26em .7em .3em; }
  .d-goal { font-size: .86em; padding: .22em .6em; }
  #dTrial { order: 5; flex: 1 1 100%; }
  #dTrial button { flex: 1; }
  #dTrial .l { display: none; } #dTrial .s { display: inline; }
  .d-note { font-size: 12px; }
  .d-score { padding: 12px 12px 10px; gap: 0 16px; border-radius: 18px; }
  .d-score .num { font-size: 19px; }
  .d-score .num small { font-size: 11.5px; margin-left: 4px; }
  .d-score .sc-head { flex-direction: column-reverse; gap: 0; }
  .d-score .lbl { font-size: 12.5px; }
  .d-score .lbl .sub { display: none; }
  .d-score .trk { height: 40px; gap: 1px; }
  .d-score .trk .col, .d-score .trk .col i { border-radius: 1.5px; }
  .d-score .score-note { font-size: 12px; }
}

/* ------------------------------------------------------------ section 5: DexMachina, then SPIDER, in section 3's format.
   Section 3's look throughout: its white headers, its dark-page glass controls (the capsule with the glass thumb, the
   round glass play button), its stage, dark band and fold-out, at its sizes and gaps (the top row 18 px under the text,
   14 on narrow screens, then 12, 12 and 14 px; the band 168 px, 138). Each player is section 3's stage on its own
   studio: the two cards are one canvas clipped to them (js/p5_3d.js) and the studio's gradient, sampled from the render
   at the card edges (js/s5.js), is painted behind them across the page (two layers, so a change of task cross-fades),
   with section 3's grain. The studios' colours are registered colours (--dmTop / --dmBot / --spTop / --spBot, set by
   js/s5.js), and every boundary uses the same one on both sides: section 4 -> bleed -> the heading and DexMachina's top
   (--dmTop, flat down to its stage) -> its stage -> its floor (--dmBot) -> bleed -> SPIDER's top (--spTop) -> its stage
   -> its floor (--spBot) -> bleed -> the footer. Where two layers meet they overlap by 2 px, so no sub-pixel gap shows
   a line at any zoom. Seams as everywhere on the page: 28 px under the last content (22 on phones), the bleed, 26 px
   above the next heading */
@property --dmTop { syntax: '<color>'; inherits: true; initial-value: rgb(165, 163, 160); }
@property --dmBot { syntax: '<color>'; inherits: true; initial-value: rgb(216, 214, 211); }
@property --spTop { syntax: '<color>'; inherits: true; initial-value: rgb(136, 134, 132); }
@property --spBot { syntax: '<color>'; inherits: true; initial-value: rgb(198, 196, 193); }
:root { transition: --dmTop .45s ease, --dmBot .45s ease, --spTop .45s ease, --spBot .45s ease; }
/* the bleeds; each also paints its end colours 2 px past both of its edges (a solid shadow), under or over the neighbour */
.bleed.b45 { height: clamp(100px, 10.5vw, 160px); background: linear-gradient(180deg, color-mix(in oklab, var(--s4bg) 100.0%, var(--dmTop)) 0.0%, color-mix(in oklab, var(--s4bg) 99.5%, var(--dmTop)) 8.3%, color-mix(in oklab, var(--s4bg) 96.5%, var(--dmTop)) 16.7%, color-mix(in oklab, var(--s4bg) 89.6%, var(--dmTop)) 25.0%, color-mix(in oklab, var(--s4bg) 79.0%, var(--dmTop)) 33.3%, color-mix(in oklab, var(--s4bg) 65.3%, var(--dmTop)) 41.7%, color-mix(in oklab, var(--s4bg) 50.0%, var(--dmTop)) 50.0%, color-mix(in oklab, var(--s4bg) 34.7%, var(--dmTop)) 58.3%, color-mix(in oklab, var(--s4bg) 21.0%, var(--dmTop)) 66.7%, color-mix(in oklab, var(--s4bg) 10.4%, var(--dmTop)) 75.0%, color-mix(in oklab, var(--s4bg) 3.5%, var(--dmTop)) 83.3%, color-mix(in oklab, var(--s4bg) 0.5%, var(--dmTop)) 91.7%, color-mix(in oklab, var(--s4bg) 0.0%, var(--dmTop)) 100.0%);
  box-shadow: 0 -2px 0 var(--s4bg), 0 2px 0 var(--dmTop); }
/* between the two players: the same seam around it, a shorter bleed (one section, two studios) */
.bleed.b5m { height: clamp(72px, 7.5vw, 112px); background: linear-gradient(180deg, color-mix(in oklab, var(--dmBot) 100.0%, var(--spTop)) 0.0%, color-mix(in oklab, var(--dmBot) 99.5%, var(--spTop)) 8.3%, color-mix(in oklab, var(--dmBot) 96.5%, var(--spTop)) 16.7%, color-mix(in oklab, var(--dmBot) 89.6%, var(--spTop)) 25.0%, color-mix(in oklab, var(--dmBot) 79.0%, var(--spTop)) 33.3%, color-mix(in oklab, var(--dmBot) 65.3%, var(--spTop)) 41.7%, color-mix(in oklab, var(--dmBot) 50.0%, var(--spTop)) 50.0%, color-mix(in oklab, var(--dmBot) 34.7%, var(--spTop)) 58.3%, color-mix(in oklab, var(--dmBot) 21.0%, var(--spTop)) 66.7%, color-mix(in oklab, var(--dmBot) 10.4%, var(--spTop)) 75.0%, color-mix(in oklab, var(--dmBot) 3.5%, var(--spTop)) 83.3%, color-mix(in oklab, var(--dmBot) 0.5%, var(--spTop)) 91.7%, color-mix(in oklab, var(--dmBot) 0.0%, var(--spTop)) 100.0%);
  box-shadow: 0 -2px 0 var(--dmBot), 0 2px 0 var(--spTop); }
.bleed.b5f { height: clamp(100px, 10.5vw, 160px); background: linear-gradient(180deg, color-mix(in oklab, var(--spBot) 100.0%, #2a2928) 0.0%, color-mix(in oklab, var(--spBot) 99.5%, #2a2928) 8.3%, color-mix(in oklab, var(--spBot) 96.5%, #2a2928) 16.7%, color-mix(in oklab, var(--spBot) 89.6%, #2a2928) 25.0%, color-mix(in oklab, var(--spBot) 79.0%, #2a2928) 33.3%, color-mix(in oklab, var(--spBot) 65.3%, #2a2928) 41.7%, color-mix(in oklab, var(--spBot) 50.0%, #2a2928) 50.0%, color-mix(in oklab, var(--spBot) 34.7%, #2a2928) 58.3%, color-mix(in oklab, var(--spBot) 21.0%, #2a2928) 66.7%, color-mix(in oklab, var(--spBot) 10.4%, #2a2928) 75.0%, color-mix(in oklab, var(--spBot) 3.5%, #2a2928) 83.3%, color-mix(in oklab, var(--spBot) 0.5%, #2a2928) 91.7%, color-mix(in oklab, var(--spBot) 0.0%, #2a2928) 100.0%);
  box-shadow: 0 -2px 0 var(--spBot), 0 2px 0 #2a2928; }
/* the grain: fades in across the bleed from section 4 (which has none), lies over the whole section at one strength,
   and fades out across the bleed into the footer, so it never starts or stops at a line */
.bleed.b45::after, .bleed.b5m::after, .bleed.b5f::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: url(../assets/s3/grain.png) 0 0 / 256px 256px; mix-blend-mode: soft-light; opacity: .7; }
.bleed.b45::after { -webkit-mask-image: linear-gradient(180deg, transparent, #000); mask-image: linear-gradient(180deg, transparent, #000); }
.bleed.b5f::after { -webkit-mask-image: linear-gradient(180deg, #000, transparent); mask-image: linear-gradient(180deg, #000, transparent); }
.bleed.b5f + .foot > :first-child { margin-top: 0; }         /* the footer's seam: 26 px above its first line, as every heading */
.s5 { --cg: 14px; --band: 168px; position: relative; isolation: isolate; background: var(--dmTop); }
.s5::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;      /* the heading's grain (each player paints its own) */
  background: url(../assets/s3/grain.png) 0 0 / 256px 256px; mix-blend-mode: soft-light; opacity: .7; }
.s5 .sec-head { max-width: none; margin: 0; padding: 0; }
.h-blk { position: relative; isolation: isolate; overflow-x: clip; }
/* the studio layers reach 2 px past the block on both sides (over the bleeds' overlap, in the same colours) */
.h-bgs { position: absolute; left: 0; right: 0; top: -2px; bottom: -2px; z-index: -1; pointer-events: none; }
/* one layer: the flat top colour above the stage, the sampled stage gradient across the stage, the flat floor colour
   below. The flat top runs 2 px into the stage, under the gradient's own first rows */
.h-bg { position: absolute; inset: 0; --y: calc(var(--stTop, 200px) + 2px);
  background: var(--tg) 0 var(--y) / 100% var(--stH, 400px) no-repeat,
              linear-gradient(180deg, var(--c0) 0, var(--c0) calc(var(--y) + 2px), var(--c1) calc(var(--y) + 2px), var(--c1) 100%); }
/* above DexMachina's stage its top colour, flat, up to the bleed from section 4 (and SPIDER's the same way); the
   registered colours, so each boundary has the same colour on both sides (js/s5.js sets the layer's own --tg) */
.h-blk[data-kind="dm"] .h-bg { --c0: var(--dmTop); --c1: var(--dmBot); --tg: linear-gradient(180deg, var(--dmTop), var(--dmBot)); }
.h-blk[data-kind="sp"] .h-bg { --c0: var(--spTop); --c1: var(--spBot); --tg: linear-gradient(180deg, var(--spTop), var(--spBot)); }
.h-bgs::after { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; background: url(../assets/s3/grain.png) 0 2px / 256px 256px; mix-blend-mode: soft-light; opacity: .7; }
.h-in { max-width: var(--w); margin: 0 auto; padding: 26px var(--gut) 28px; }   /* section 3's (.s3-in) */
/* the top row is section 3's (.t-top, #tStops, #tPlay): the task switch as its glass capsule with a sliding glass
   thumb, then the speed and the round glass play button */
.h-top .h-speed { margin-left: auto; }
.h-shot { display: inline-grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.h-shot .seg-thumb { left: 4px; width: calc((100% - 10px) / 2); transition: transform .45s cubic-bezier(.45, 0, .2, 1); }
.h-shot:has(> button:nth-of-type(2)[aria-pressed="true"]) .seg-thumb { transform: translateX(calc(100% + 2px)); }
.h-shot button { padding: 7px 15px; min-height: 38px; font-size: 14.5px; text-align: center; }
.h-shot button .k { margin-left: 6px; font-weight: 500; opacity: .62; }
.s5 .seg.small button { min-height: 32px; padding: 4px 10px; font-size: 13px; }
.s5 .t-stage { height: var(--H5, 440px); }
.h-blk[data-kind="dm"] .t-card { background: var(--tg, linear-gradient(180deg, var(--dmTop), var(--dmBot))); }
.h-blk[data-kind="sp"] .t-card { background: var(--tg, linear-gradient(180deg, var(--spTop), var(--spBot))); }
.h-snap { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 2; pointer-events: none; opacity: 0; }
/* the band: section 3's (the video's dark glass slab, its height and radius), the plot on the run's time axis, also the scrubber */
.h-pw { position: absolute; inset: 0; }
/* the fold-out: section 3's dark glass button on the studio floor, and its panel */
.s5 .t-more.glass { background: rgba(42, 42, 47, .82); }
.s5 .t-more.glass:hover { background: rgba(52, 52, 58, .9); }
.s5 .t-paper { color: #fff; }
/* the studios blend over ALL the space between them, not only across a bleed (user: "diffuse in general"): from
   DexMachina's stage to SPIDER's (its band, its button, the seam, SPIDER's heading and controls), and from SPIDER's
   stage into the footer, one smooth gradient each. Each element it crosses paints its own slice of it (js/s5.js sets
   --s1y / --s1h and --s2y / --s2h on each: where the gradient starts above it and how long it is) */
:root { --span1: linear-gradient(180deg, color-mix(in oklab, var(--dmBot) 100.0%, var(--spTop)) 0.0%, color-mix(in oklab, var(--dmBot) 99.5%, var(--spTop)) 8.3%, color-mix(in oklab, var(--dmBot) 96.5%, var(--spTop)) 16.7%, color-mix(in oklab, var(--dmBot) 89.6%, var(--spTop)) 25.0%, color-mix(in oklab, var(--dmBot) 79.0%, var(--spTop)) 33.3%, color-mix(in oklab, var(--dmBot) 65.3%, var(--spTop)) 41.7%, color-mix(in oklab, var(--dmBot) 50.0%, var(--spTop)) 50.0%, color-mix(in oklab, var(--dmBot) 34.7%, var(--spTop)) 58.3%, color-mix(in oklab, var(--dmBot) 21.0%, var(--spTop)) 66.7%, color-mix(in oklab, var(--dmBot) 10.4%, var(--spTop)) 75.0%, color-mix(in oklab, var(--dmBot) 3.5%, var(--spTop)) 83.3%, color-mix(in oklab, var(--dmBot) 0.5%, var(--spTop)) 91.7%, color-mix(in oklab, var(--dmBot) 0.0%, var(--spTop)) 100.0%); --span2: linear-gradient(180deg, color-mix(in oklab, var(--spBot) 100.0%, #2a2928) 0.0%, color-mix(in oklab, var(--spBot) 99.5%, #2a2928) 8.3%, color-mix(in oklab, var(--spBot) 96.5%, #2a2928) 16.7%, color-mix(in oklab, var(--spBot) 89.6%, #2a2928) 25.0%, color-mix(in oklab, var(--spBot) 79.0%, #2a2928) 33.3%, color-mix(in oklab, var(--spBot) 65.3%, #2a2928) 41.7%, color-mix(in oklab, var(--spBot) 50.0%, #2a2928) 50.0%, color-mix(in oklab, var(--spBot) 34.7%, #2a2928) 58.3%, color-mix(in oklab, var(--spBot) 21.0%, #2a2928) 66.7%, color-mix(in oklab, var(--spBot) 10.4%, #2a2928) 75.0%, color-mix(in oklab, var(--spBot) 3.5%, #2a2928) 83.3%, color-mix(in oklab, var(--spBot) 0.5%, #2a2928) 91.7%, color-mix(in oklab, var(--spBot) 0.0%, #2a2928) 100.0%); }
.s5 .h-bg { background: var(--tg) 0 var(--y) / 100% var(--stH, 400px) no-repeat,
  var(--span1) 0 var(--s1y, -9999px) / 100% var(--s1h, 0px) no-repeat, var(--span2) 0 var(--s2y, -9999px) / 100% var(--s2h, 0px) no-repeat,
  linear-gradient(180deg, var(--c0) 0, var(--c0) calc(var(--y) + 2px), var(--c1) calc(var(--y) + 2px), var(--c1) 100%); }
.bleed.b5m.span { background: var(--span1) 0 var(--s1y) / 100% var(--s1h) no-repeat, var(--spTop); box-shadow: none; }
.bleed.b5f.span { background: var(--span2) 0 var(--s2y) / 100% var(--s2h) no-repeat, #2a2928; box-shadow: 0 2px 0 #2a2928; }   /* the slices meet the players' layers, which run 2 px over them */
@media (max-width: 759px) { .s5 { --band: 138px; } .s5 .t-stage { height: auto; } }      /* section 3's phones: square cards, the stage as tall as they are */
@media (max-width: 599px) {
  /* phones: section 3's phone layout (square cards side by side, its pills, band and type), one compact top row */
  .s5 { --cg: 8px; }
  .h-in { padding-bottom: 22px; }
  .h-top { gap: 8px; }
  .h-shot { flex: 1 1 auto; min-width: 0; }
  .h-shot button { min-width: 0; padding: 6px 4px; min-height: 36px; font-size: 13px; overflow: hidden; text-overflow: ellipsis; }
  .h-shot button .k { display: none; }                      /* short labels: the task (the hand is in the cards) */
  .s5 .seg.small.h-speed button { min-height: 30px; padding: 3px 8px; font-size: 12.5px; }
}
@media (max-width: 359px) {                                  /* the smallest phones: the row tightens so "Notebook" still fits */
  .h-top { gap: 6px; }
  .s5 .seg.small.h-speed button { padding: 3px 6px; }
  .h-shot button { padding: 6px 2px; font-size: 12.5px; }
}

/* BibTeX (js/bibtex.js): a light glass card that pops up under the hero's button, over the page */
.bib-card { position: absolute; z-index: 50; padding: 10px 12px 12px; border-radius: 18px; color: #1d1d1f; color-scheme: light;
  background: linear-gradient(180deg, rgba(255,255,255,.94), rgba(255,255,255,.86)); -webkit-backdrop-filter: blur(18px) saturate(160%); backdrop-filter: blur(18px) saturate(160%);
  box-shadow: inset 0 1px 0 #fff, inset 0 0 0 1px rgba(0,0,0,.06), 0 2px 6px rgba(0,0,0,.06), 0 18px 48px rgba(0,0,0,.16); }
.bib-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 6px 4px; font-size: 13px; font-weight: 650; color: rgba(29,29,31,.6); }
.bib-copy { border: 0; padding: 5px 13px; min-height: 30px; border-radius: 999px; font-size: 13px; font-weight: 600; color: #1d1d1f;
  background: rgba(0,0,0,.06); transition: background .2s, transform .2s ease; }
.bib-copy:hover { background: rgba(0,0,0,.1); } .bib-copy:active { transform: scale(.96); }
.bib-pre { margin: 0; padding: 10px 12px; border-radius: 12px; background: rgba(0,0,0,.04); overflow-x: auto; -webkit-overflow-scrolling: touch;
  font: 500 12.5px/1.55 ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace; color: #2a2a2c; white-space: pre; tab-size: 2; }
.bib-pre .l { display: block; white-space: pre-wrap; padding-left: 13ch; text-indent: -13ch; }     /* a long field wraps under its value */
.bib-card :focus-visible { outline: 2px solid rgba(0,0,0,.7); outline-offset: 2px; }
@media (max-width: 599px) { .bib-card { padding: 8px 8px 10px; border-radius: 16px; } .bib-pre { font-size: 11px; padding: 8px 10px; }
  .bib-pre .l { white-space: pre; padding-left: 0; text-indent: 0; } }                       /* phones: one line each, scrolled sideways */

.foot { padding: 26px var(--gut) 60px; text-align: center; color: var(--ink3); font-size: 13.5px; background: #2a2928; }
/* the paper's acknowledgments, word for word, in a glass bubble on the footer's dark (as wide as the leads) */
.ack { max-width: 760px; margin: 0 auto 26px; padding: 18px 22px 20px; text-align: left;
  background: linear-gradient(180deg, rgba(255,255,255,.075), rgba(255,255,255,.03)); box-shadow: inset 0 1px 0 rgba(255,255,255,.12), 0 10px 30px rgba(0,0,0,.28); }
.ack h2 { margin: 0 0 8px; font-size: 17px; font-weight: 650; letter-spacing: -.005em; line-height: 1.25; color: rgba(236,236,238,.86); }
.ack p { margin: 0; font-size: 14px; line-height: 1.55; color: rgba(236,236,238,.78); text-wrap: pretty; }
@media (max-width: 599px) { .ack { padding: 14px 16px 16px; border-radius: 18px; } .ack h2 { font-size: 16px; margin-bottom: 6px; } .ack p { font-size: 13px; } }

/* ------------------------------------------------------------ bubbles: justified prose */
/* every paragraph inside a glass bubble is justified (last line left), hyphenated only where needed and never inside
   a name (js/typeset.js wraps names in .nohy); equations, counts and one-line tags keep their own alignment */
.tldr, .glass.panel p:not(.eqline):not(.dims):not(.tag):not(.score-note) {
  text-align: justify; text-align-last: left; -webkit-hyphens: auto; hyphens: auto; hyphenate-limit-chars: 7 3 3;
}
.nohy { -webkit-hyphens: manual; hyphens: manual; }

/* ------------------------------------------------------------ responsive */
@media (max-width: 1279px) { .hero { column-gap: 16px; grid-template-columns: minmax(0, 1fr) minmax(0, 600px) minmax(0, 1fr); } }
/* narrow screens: the sprites frame the hero in a row above and a row below, like the end card's top and bottom */
@media (max-width: 999px) {
  .hero { display: block; padding-top: 24px; }
  .hero .btn { min-height: 40px; }
  /* one size, one shared baseline per row, evenly spaced: reads as a deliberate frame on a narrow screen */
  .spr-row { display: flex; justify-content: space-between; align-items: flex-end; max-width: 680px; margin: 0 auto; padding: 0 2%; }
  .spr-row.top { margin-bottom: var(--g2); }
  .spr-row.bot { margin-top: calc(var(--g2) + 4px); }
  .spr { margin: 0 !important; justify-self: auto; align-self: auto !important; }
  .subtitle { white-space: normal; text-wrap: balance; max-width: 560px; }
}
@media (max-width: 760px) {
  :root { --gut: 16px; }
  body { font-size: 16px; }
  .opening { --g2: 14px; }
  .title { font-size: 34px; }
  .subtitle { font-size: 16px; }
  .affil img { height: 20px; }
  .eqnote { font-size: 12.5px; }
  .hero .btn { min-height: 34px; padding: .42em .6em .42em .52em; gap: .34em; }
  .hero .btn .ic { width: 1.12em; height: 1.12em; }
  .hero .btn .ic.yt { width: 1.26em; height: 1.26em; }
  .links { gap: .34em; }
  .tldr { font-size: 14px; line-height: 1.52; padding: 12px 14px; border-radius: 16px; }
}
/* phones: two small square cards side by side (the footage uses its full width), full-width controls */
@media (max-width: 599px) {
  .s1 { --cg: 8px; padding: 96px 0 22px; }
  .card { height: auto; aspect-ratio: 1 / 1; }
  .s1 .sec-head h2 { font-size: 25px; }
  .s1 .lead { font-size: 15px; line-height: 1.5; }
  .stage-top { flex-wrap: wrap; margin-top: 12px; gap: 8px; }
  .s1 #taskSeg, .stage-top #viewSeg { flex: 1 1 100%; margin: 0; }
  .s1 #taskSeg button, .stage-top #viewSeg button { flex: 1; padding-left: 4px; padding-right: 4px; }
  .s1 #taskSeg button { min-height: 36px; font-size: 14px; }
  .cards { margin-top: 10px; }
  .auto { display: none; }
  .card[data-side="js"] .chip { top: auto; bottom: .7em; right: .7em; }
  .card[data-side="ours"] .chip { top: auto; bottom: .7em; left: .7em; }
  .pill { top: .7em; } .pill.js { left: .7em; } .pill.ours { right: .7em; }
  .transport { margin-top: 8px; gap: 8px; flex-wrap: wrap; border-radius: 24px; }
  .round { width: 36px; height: 36px; }
  #timingSeg button { padding-left: 9px; padding-right: 9px; }
  #trialSeg, #timingSeg { order: 5; flex: 1 1 100%; }
  #trialSeg button, #timingSeg button { flex: 1; }
  #trialSeg .l { display: none; } #trialSeg .s { display: inline; }
  .score { padding: 12px 12px 10px; gap: 0 16px; border-radius: 18px; }
  .score .num { font-size: 19px; }
  .sc-head { flex-direction: column-reverse; gap: 0; }
  .score .lbl { font-size: 12.5px; }
  .score .lbl .sub { display: none; }
  .trk { height: 34px; gap: 3px; }
  .score-note { font-size: 12px; }
  .why summary { font-size: 14.5px; }
  .why p { font-size: 13.5px; }
}
/* section 2 on phones: the steps scroll sideways; the cards stack their layers (cloud or clip on top, hand below) */
@media (max-width: 759px) {
  .s2-top { gap: 8px; }
  /* the six steps as numbers, evenly spread, the glass thumb sliding between them; the step's name is the caption
     under the stage (on phones the caption never sits on the scene) */
  .beats { flex: 1; gap: 0; }
  .beats button { flex: 1; justify-content: center; padding: 6px 0 8px; gap: 0; font-size: 13px; }
  .beats button .t { display: none; }
  .beats button i { left: 30%; right: 30%; }
  .m-stage .m-cap { display: none; }
  .m-capn { display: block; margin: 0; flex-basis: 100%; font-size: 16px; line-height: 1.35; font-weight: 650; color: var(--ink); text-wrap: balance; }
  .tour button { padding: 7px 9px; }
  .s2 .sec-head h2 { font-size: 25px; }
  .s2 .lead { font-size: 15px; line-height: 1.5; }
  .tour button span { display: none; }
  .m-stage { margin-top: 10px; border-radius: 18px; }
  .m-bg, .m-ov { border-radius: 18px; }
  .m-ov .pill { top: 10px; font-size: 12px; padding: 4px 10px; }
  .m-ov .pill.js { left: 10px; } .m-ov .pill.ours { right: 10px; }
  .m-cap { bottom: 12px; font-size: 13px; padding: 7px 13px; white-space: normal; width: max-content; max-width: calc(100% - 24px); }
  .m-post { padding: 4px; border-radius: 12px; }
  .m-post-m { border-radius: 8px; }
  .m-pcl { font-size: 11.5px; padding: 3px 8px; }
  .m-handtag { font-size: 13px; padding: 5px 11px; }
  .m-ego-t { font-size: 11.5px; left: 8px; top: 8px; padding: 4px 9px; }
  .m-sub { font-size: 13.5px; flex-basis: 100%; }
  .m-scale { margin-left: 0; width: 100%; }
  .m-dirs { margin-left: 0; width: 100%; flex-direction: column; gap: 6px; }
  .m-dir { width: 100%; padding: 2px 14px; }
  .m-dir input { flex: 1; width: auto; }
  .m-scale input { flex: 1; width: auto; }
}
@media (max-width: 999px) { .fig1-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 680px; margin: 0 auto; } }
/* narrow screens: all four at once, two by two: each tile is the plot (cropped to the plot and its hands, js/fig1.js),
   the panel's name and verdict, and its rule. Tap a hand to see it large (js/fig1hands.js). */
.f1-txt { display: none; }
@media (max-width: 759px) {
  .fig1 { margin-top: 40px; }
  .fig1-title { font-size: 18px; margin-bottom: 10px; }
  .fig1-cap { font-size: 13.5px; margin: -4px 0 12px; }
  .fig1-grid { grid-template-columns: 1fr 1fr; gap: 10px; }
  .f1p { padding: 10px 10px 12px; border-radius: 16px; }
  .f1-svg { aspect-ratio: auto; }
  .f1p .head, .f1p .verdict, .f1p .evec, .f1p .axes path[aria-label] { display: none; }
  .f1-txt { display: flex; flex-direction: column; gap: 1px; margin-top: 6px; font-family: ui-monospace, "DejaVu Sans Mono", Menlo, monospace; line-height: 1.3; }
  .f1-txt b { font-size: 12.5px; font-weight: 500; }
  .f1-txt span { display: none; }
  .f1-txt i { font-size: 10.5px; } .f1-txt i.bad { color: #A87870; } .f1-txt i.good { color: #698D73; }
  .f1-rule { margin-top: 4px; padding: 0; align-items: flex-start; text-align: left; }
  .f1-rule .eqline { font-size: 11.5px; white-space: normal; text-wrap: balance; }
  .f1-rule .eqline .a, .f1-rule .eqline .n { white-space: nowrap; }    /* a term never splits: lines break at a + */
  .f1-meta { display: none; }
  .f1-zh { font-size: 10.5px; bottom: 5px; }
  .f1-zx { width: 26px; height: 26px; font-size: 18px; right: 5px; top: 5px; }
}



@media (max-width: 359px) { .m-ov .pill { font-size: 10.5px; padding: 3px 8px; } .m-ov .pill.js { left: 8px; } .m-ov .pill.ours { right: 8px; } }
/* set by js/fit.js when even the smallest size cannot fit the first line: its two groups become two lines */
.authors.stack .arow:first-child { display: contents; }
/* phones: the author block may use the gutters too (more room for the names) */
/* phones: tighter name gaps so the names stay as large as possible inside the TL;DR width */
@media (max-width: 560px) { .arow, .agrp { gap: 0 .7em; } }
@media (max-width: 560px) {
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
