/* The Playground: the speculative-decoding and EELS scenes. Colors, the header and the menu
   come from site.css. */
html,body{height:100%;overflow:hidden}   /* the Playground fills the window and never scrolls */

.scenes{position:fixed;left:var(--gut);bottom:28px;display:flex;gap:12px;font-size:12px;z-index:2}
.scenes[hidden]{display:none}
.caption{position:fixed;bottom:16px;left:50%;transform:translateX(-50%);z-index:2;white-space:nowrap}

.ctrl{position:fixed;left:var(--gut);top:calc(50% - 60px);width:206px;z-index:2}
.ctrl input{width:100%;-webkit-appearance:none;appearance:none;height:1px;background:var(--ink);margin:14px 0 10px;outline:none}
.ctrl input::-webkit-slider-thumb{-webkit-appearance:none;width:1px;height:11px;background:var(--ink)}
.ctrl input::-moz-range-thumb{width:1px;height:11px;background:var(--ink);border:0;border-radius:0}
.ends{display:flex;justify-content:space-between}
.batch{margin-top:26px}
.gpu{margin-top:10px;color:var(--mute);line-height:1.5}
.stats{margin-top:34px;line-height:1.75;color:var(--mute)}
.stats div{display:flex;justify-content:space-between}
.stats b{color:var(--ink);font-weight:400}

.stage{position:fixed;top:64px;bottom:64px;left:0;right:0}
.text{position:absolute;left:230px;top:calc(50% - 110px);width:min(400px,34vw);font-family:'IBM Plex Sans',sans-serif;font-size:18px;line-height:2.5;letter-spacing:-.01em;transition:opacity .3s,transform .35s cubic-bezier(.2,.7,.2,1)}
.text.leave{opacity:0;transform:translateY(-1em)}
.text.enter{opacity:0;transform:translateY(1em);transition:none}
.tok{position:relative;transition:color .8s,opacity .35s}
.tok.new{color:var(--accent);transition:none}
.tok.bonus{color:var(--accent)}
.tok.pending{opacity:0;transition:none}
/* a kept word on its way from the tree into the sentence */
.fly{position:absolute;white-space:pre;font-family:'IBM Plex Sans',sans-serif;letter-spacing:-.01em;color:var(--ink);pointer-events:none;z-index:1}
.fly.bonus,.fly.go{color:var(--accent)}
/* scene 2: the draft run sits in the sentence as one bracketed group of cells */
.run{display:inline-block;position:relative;line-height:1.3;margin:0 .2em 0 .3em;padding-top:.45em;transition:opacity .25s}
.run::before{content:'';position:absolute;left:0;right:0;top:0;height:5px;border:1px solid var(--ink);border-bottom:0;opacity:0;transition:opacity .3s}
.run.check::before{opacity:1}
.run.out{opacity:0}
.cell{display:inline-block;position:relative;color:var(--mute);margin:0 .28em;min-width:30px;text-align:center;transition:color .3s,opacity .35s;animation:rise .3s ease}
.tag+.cell{margin-left:.1em}.cell:last-child{margin-right:.1em}
.cell .p{position:absolute;left:50%;top:calc(100% + 4px);transform:translateX(-50%);font:9px 'IBM Plex Mono',monospace;color:var(--mute);letter-spacing:0}
.cell.ok{color:var(--ink)}
.cell.bad{color:var(--mute);text-decoration:line-through}
.cell.fade{opacity:0}
@keyframes rise{from{opacity:0;transform:translateY(4px)}}
.text.roomy{line-height:2.9}
.run .tag{position:absolute;left:0;bottom:calc(100% + 4px);font:9px 'IBM Plex Mono',monospace;color:var(--mute);letter-spacing:.05em;white-space:nowrap}
.run .tag b{font-weight:400;color:var(--accent)}
.cell.drop{opacity:0;transform:translateY(7px);transition:opacity .22s,transform .22s}
.cell.bonus{color:var(--accent);min-width:38px;animation:land .4s cubic-bezier(.2,.7,.2,1)}
.cell.bonus .p{color:var(--accent)}
.mode{position:absolute;display:flex;align-items:center;gap:9px;color:var(--mute);letter-spacing:.03em;user-select:none;z-index:2}
.ctrl .mode{position:static;margin-bottom:30px}
.mode span{cursor:pointer;transition:color .3s}
.mode span.on{color:var(--ink)}
.sw{width:30px;height:16px;border-radius:999px;background:var(--faint);position:relative;transition:background .3s}
.sw i{position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:var(--bg);transition:transform .4s cubic-bezier(.3,.7,.2,1)}
.mode.spec .sw{background:var(--accent)}
.mode.spec .sw i{transform:translateX(14px)}
@keyframes land{from{opacity:0;transform:translateY(-10px)}}
.caret{display:inline-block;width:.5em;height:1em;background:var(--ink);vertical-align:-.12em;margin-left:2px;animation:blink 1s steps(1) infinite}
@keyframes blink{50%{opacity:0}}

:root{--k:1}
svg.tree{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none;transition:opacity calc(.4s * var(--k))}
svg.tree.out{opacity:0}
.edge{fill:none;stroke:var(--mute);stroke-width:1;stroke-dasharray:1;stroke-dashoffset:1;vector-effect:non-scaling-stroke;transition:stroke-dashoffset calc(.3s * var(--k)) ease,stroke calc(.3s * var(--k)),opacity calc(.3s * var(--k))}
.edge.in{stroke-dashoffset:0}
.edge.ok{stroke:var(--ink)}
.edge.cut{stroke-dasharray:.015 .02;opacity:.35}
.edge.bonus{stroke:var(--accent)}
.edge.edge.gone{opacity:0}
.node.node.gone{opacity:0;transition:opacity calc(.12s * var(--k)),transform calc(.4s * var(--k)) cubic-bezier(.5,0,.9,.6)}
.lead{fill:none;stroke:var(--ink);stroke-width:1;stroke-dasharray:2 3}
.node{opacity:0;transition:opacity calc(.35s * var(--k)),transform calc(.55s * var(--k)) cubic-bezier(.2,.7,.2,1)}
.node.in{opacity:1}
.node .t{font:16px 'IBM Plex Sans',sans-serif;letter-spacing:-.01em;fill:var(--mute);transition:fill calc(.3s * var(--k))}
.node .p{font:11px 'IBM Plex Mono',monospace;fill:var(--mute)}
.node.ok .t{fill:var(--ink)}
.node.cut{opacity:.3}
.node.cut .t{text-decoration:line-through}
.node.bonus .t,.node.bonus .p{fill:var(--accent)}
.root{fill:var(--bg);stroke:var(--ink);transform-box:fill-box;transform-origin:center;transition:transform calc(.2s * var(--k))}
.root.off{transform:scale(0)}
.phase{font:11px 'IBM Plex Mono',monospace;fill:var(--mute);letter-spacing:.04em;transition:opacity calc(.2s * var(--k))}
.phase.gone{opacity:0}
.node .p{transition:opacity calc(.1s * var(--k))}
svg.fold .node .p{opacity:0}
.scan{fill:var(--ink);opacity:0;transition:transform calc(.35s * var(--k)) ease,opacity calc(.3s * var(--k))}
/* attention over the sentence, and re-ranking inside the tree */
.al{fill:none;stroke:var(--ink);stroke-width:1;stroke-dasharray:1;stroke-dashoffset:1;transition:stroke-dashoffset calc(.45s * var(--k)) ease}
.al.in{stroke-dashoffset:0}
.at{stroke:var(--ink);stroke-width:1;opacity:0;transition:opacity calc(.12s * var(--k))}
.aw{font:11px 'IBM Plex Mono',monospace;fill:var(--mute);text-anchor:middle;opacity:0;transition:opacity calc(.25s * var(--k)),fill calc(.3s * var(--k))}
.at.in,.aw.in{opacity:1}
#attn.tg .aw,.node.rs .p{fill:var(--ink)}
.node.tw{transition:opacity calc(.35s * var(--k))}
/* scene 3: memory meter */
.mem{position:absolute;display:none;width:352px;--cell:9px;font-size:10px;color:var(--mute);letter-spacing:.03em}
.mem .mrow{display:flex;justify-content:space-between;gap:20px;margin:12px 0 6px;white-space:nowrap}
.mem .mrow.foot{margin-top:14px}
.mem b{color:var(--ink);font-weight:400}
.mem .cells{display:flex;gap:2px;height:12px}
.mem .cells i{flex:none;width:var(--cell);height:12px;border:1px solid var(--faint)}
.mem .cells i.on{background:var(--ink);border-color:var(--ink)}
.mem .cells i.off{visibility:hidden}
/* scene 4: tree attention mask */
#mask{transition:opacity calc(.25s * var(--k))}
#mask.out{opacity:0}
#mask .mh{font:10px 'IBM Plex Mono',monospace;fill:var(--mute);letter-spacing:.03em}
#mask .mc{font:9px 'IBM Plex Mono',monospace;fill:var(--mute);text-anchor:middle}
#mask .ml{font:10px 'IBM Plex Mono',monospace;fill:var(--mute);text-anchor:end;transition:fill calc(.2s * var(--k))}
#mask .mrow{opacity:0;transition:opacity calc(.2s * var(--k)),transform calc(.35s * var(--k)) cubic-bezier(.2,.7,.2,1)}
#mask .mrow.in{opacity:1}
#mask.focus .mrow.in:not(.hot){opacity:.3}
#mask .mrow.gone{opacity:0}
#mask .mk{fill:none;stroke:var(--faint);opacity:0;transition:opacity calc(.2s * var(--k)),transform calc(.35s * var(--k)) cubic-bezier(.2,.7,.2,1),fill calc(.2s * var(--k))}
#mask .mk.on{fill:var(--mute);stroke:none}
#mask .mrow .mk:first-of-type,#mask .mk.in{opacity:1}
#mask .mk.gone{opacity:0}
#mask .mrow.hot .mk.on,#mask .mrow.hot .ml{fill:var(--ink)}
/* scene 5: words the dynamic draft chose to grow */
.node.xp .t,.node.vs .t{fill:var(--ink)}
/* the harness's verdict over each drafted level */
.ch{font:10px 'IBM Plex Mono',monospace;fill:var(--mute);letter-spacing:.02em;transition:opacity calc(.15s * var(--k))}
svg.fold .ch{opacity:0}
.text.line{white-space:nowrap;width:auto}
/* scene [2]: EELS */
.eels{position:absolute;left:var(--gut);right:var(--gut);top:0;bottom:0;width:calc(100% - 2 * var(--gut));height:100%;display:none}
svg.eels{overflow:visible;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}
svg.eels:active{cursor:grabbing}
canvas.eels{pointer-events:none}
/* the EELS steps, listed like Paradigm's scene 4: a rule, the names, a tick at the current one */
.esteps{position:absolute;left:var(--gut);top:calc(50% - 40px);display:none;flex-direction:column;gap:7px;border-left:1px solid var(--ink);padding-left:12px;z-index:3}
.esteps button{text-align:left;color:var(--mute);position:relative;letter-spacing:.03em}
.esteps button.on{color:var(--ink)}
.esteps button.on::before{content:'';position:absolute;left:-17px;top:50%;width:10px;height:1px;background:var(--ink)}
#eels text{font-family:'IBM Plex Mono',monospace;font-size:calc(10px * var(--fs, 1));fill:var(--mute);letter-spacing:.03em}
#eels .sent{font-family:'IBM Plex Sans',sans-serif;font-size:calc(var(--sent, 22px) * var(--fs, 1));fill:var(--ink);letter-spacing:-.01em;transition:opacity .3s}
#eels .phase{font-size:calc(11px * var(--fs, 1));letter-spacing:.04em}
#eels .lab{fill:var(--ink)}
#eels .L text{font-size:calc(10px * var(--fs, 1) / var(--ls, 1))}
#eels .cap{font-size:calc(12px * var(--fs, 1));fill:var(--ink)}
#eels .wipe{stroke:var(--ink);stroke-width:1}
#eels .fade{transition:opacity .6s}
#eels text[style]{transition:opacity .4s}
#eels .line{fill:none;stroke:var(--ink);stroke-width:1}
#eels .hair{stroke:var(--faint);stroke-width:1}
#eels .dash{fill:none;stroke:var(--mute);stroke-width:1;stroke-dasharray:3 3}
#eels .dot{fill:none;stroke:var(--mute);stroke-width:1;stroke-dasharray:1 3;stroke-linecap:round}
#eels .orig{fill:none;stroke:var(--ink);stroke-width:1}
#eels .recon{fill:none;stroke:var(--accent);stroke-width:1.4}
#eels .win{fill:var(--ink);opacity:.05}
#eels .gap{fill:var(--miss);opacity:.35;stroke:none}
#eels .win.hot{opacity:.09}
#eels .beam{stroke:var(--ink);stroke-width:1}
#eels .col{stroke:var(--accent);stroke-width:1.5}
#eels .ring{fill:none;stroke-width:1.5}
#eels .ring.found{stroke:var(--accent)}
#eels .ring.miss{stroke:#e5484d}
.text.line .caret{display:none}

.dist{position:absolute;width:210px;display:none;line-height:1.95}
.dist .h{color:var(--mute);letter-spacing:.04em;margin-bottom:12px;white-space:nowrap}
.dist .r{display:flex;justify-content:space-between;color:var(--mute);transition:color .3s}
.dist .r.win{color:var(--accent)}
.dist .r.lose span:first-child{text-decoration:line-through}


.note{position:fixed;top:72px;left:50%;transform:translateX(-50%);color:var(--mute);text-align:center;z-index:2}

@media (max-width:1179px){
  .ctrl{top:auto;bottom:58px}
  .stats{display:none}
}
/* phones: a smaller margin and logo, the sentence near the top, the drawing below it */
@media (max-width:860px){
  .ctrl{display:none}
  .text{left:var(--gut);width:calc(100% - 2 * var(--gut));top:12%;font-size:16px;line-height:2.1}
  .dist{display:none!important}
  .scenes{bottom:72px}
  .caption{max-width:calc(100% - 2 * var(--gut));white-space:normal;text-align:center;line-height:1.5;font-size:10px}
  /* the EELS steps run along the top, the current one underlined */
  .esteps{top:0;flex-direction:row;gap:18px;border-left:0;padding-left:0}
  .esteps button.on::before{left:0;top:auto;bottom:-5px;width:100%;height:1px}
}
