:root{ --bg:#0e1420; --panel:#141d2e; --ink:#e8eef7; --dim:#8aa0bf;
       --sand:#e3b666; --teal:#39c5bb; --grn:#7ee08a; --accent:#6ea8ff; --red:#ff6b6b;
       --barh:52px; }   /* toolbar height; JS grows it when the bar splits into two rows */
*{box-sizing:border-box}
html,body{margin:0;height:100%;background:var(--bg);color:var(--ink);
  font:14px/1.4 ui-sans-serif,system-ui,Segoe UI,Roboto,Helvetica,Arial}
#bar{position:fixed;top:0;left:0;right:0;height:52px;display:flex;gap:10px;
  align-items:center;padding:0 14px;background:linear-gradient(#182338,#101828);
  border-bottom:1px solid #24314b;z-index:10}
#bar b{position:absolute;left:50%;transform:translateX(-50%);color:var(--sand);font-weight:700;letter-spacing:.3px;white-space:nowrap;pointer-events:none}   /* centered title, out of flow so it never crowds the button groups */
#bar button{white-space:nowrap}
#bar > button, #bar .transport, #vizbtns, #weakctrls{flex:0 0 auto}   /* keep labels intact; only the explode animation collapses width */
#barbreak{display:none}
#menubtn{order:-1}   /* hamburger lives in the far-left corner in every view (single row and split) */
/* single-row placement mirrors the split one: ☰ + h-input flushed left; play controls, k/∘ and weak flushed right
   (via #rspacer's auto margin). Keeping the play controls out of the left group is also what stops it reaching the centered title. */
#hlbl{order:1} #vec{order:2} #vizbtns{order:3} #abctrls{order:4} #matrixbtn{order:5}
#rspacer{order:6} .transport{order:7} #weakctrls{order:8} #weakbtn{order:9}
@media (max-width:1180px){ #bar b{display:none} }   /* narrow: drop the centered title so the button groups have room */
/* two-row split (JS toggles body.barsplit when the single row overflows):
   row 1 = ☰ + mode buttons, weak (+ its k/∘ controls) flushed right;  row 2 = h-input flushed left, play controls flushed right */
body.barsplit #bar{height:auto;flex-wrap:wrap;row-gap:5px;padding-top:5px;padding-bottom:5px;align-content:center}
body.barsplit #barbreak{display:block;flex-basis:100%;width:100%;height:0;margin:0;order:20}
body.barsplit #vizbtns{order:2} body.barsplit #abctrls{order:3} body.barsplit #matrixbtn{order:4}
body.barsplit #rspacer{display:block;width:0;order:6}       /* its global margin-left:auto flushes weak + k/∘ right on row 1 (works even when weakctrls is exploded) */
body.barsplit #weakbtn{order:8}
body.barsplit #hlbl{order:21} body.barsplit #vec{order:22}
body.barsplit #weakctrls{order:23;margin-left:auto}         /* k/∘ sit on row 2, flushed right (only ever visible when the play controls are not) */
body.barsplit .transport{order:24;margin-left:auto}         /* play controls flushed right on row 2 */
select,input,button{background:var(--panel);color:var(--ink);border:1px solid #2b3a58;
  border-radius:8px;padding:6px 10px;font:inherit}
button{cursor:pointer}button:hover{border-color:var(--accent)}
button.primary{background:#1d3a6b;border-color:#2f5aa0}
#vec{width:130px}
label.small{color:var(--dim);font-size:12px}
#stage{position:fixed;inset:var(--barh) 0 0 0;touch-action:none;cursor:grab}
#stage.drag{cursor:grabbing}
#err{position:fixed;top:calc(var(--barh) + 4px);left:200px;background:#3a1420;border:1px solid var(--red);
  color:#ffd0d0;border-radius:8px;padding:6px 10px;font-size:12px;z-index:20;display:none}
#progress{position:fixed;top:calc(var(--barh) + 14px);left:50%;transform:translateX(-50%);max-width:80vw;
  z-index:60;display:none;flex-direction:column;gap:8px}
#progress.shown{display:flex}
.progjob{min-width:300px;background:#0d1626f2;border:1px solid #2f5aa0;border-radius:10px;padding:11px 13px;box-shadow:0 8px 30px #0009}
.progbar{height:4px;border-radius:3px;background:#1a2740;overflow:hidden;position:relative;margin-bottom:8px}
.progbar:before{content:'';position:absolute;top:0;height:100%;width:40%;border-radius:3px;
  background:linear-gradient(90deg,transparent,var(--accent),transparent);animation:progslide 1.1s ease-in-out infinite}
@keyframes progslide{0%{left:-40%}100%{left:100%}}
.progrow{display:flex;align-items:center;justify-content:space-between;gap:14px}
.progtxt{color:#cfe0f7;font-size:12px;font-variant-numeric:tabular-nums}
.progcancel{padding:2px 9px;font-size:12px;line-height:1.3;background:#1d2740;border:1px solid #2b3a58;color:var(--dim);border-radius:6px}
.progcancel:hover{border-color:var(--red);color:#ffd0d0}
#vec.locked,#vec:disabled{opacity:.5;cursor:not-allowed;border-color:#d0a040}
#hint{position:fixed;left:12px;bottom:12px;color:var(--dim);font-size:12px;
  background:#0d1626cc;border:1px solid #23324e;border-radius:8px;padding:8px 10px;max-width:360px}
#hinttext{padding-right:16px}
#hinthide{position:absolute;top:3px;right:4px;padding:0 5px;font-size:14px;line-height:1.3;
  background:transparent;border:none;color:var(--dim)}
#hinthide:hover{color:var(--accent);border-color:transparent}
#hintshow{position:fixed;left:12px;bottom:12px;display:none;width:26px;height:26px;padding:0;
  font-weight:700;color:var(--dim);background:#0d1626cc;border:1px solid #23324e;border-radius:8px;z-index:12}
#hint .katex{font-size:1em}
#hinttext p{margin:.4em 0}
#hinttext p:first-child{margin-top:0}
#hinttext p:last-child{margin-bottom:0}
#hinttext em{opacity:.6;font-style:normal}
.transport{display:inline-flex;gap:4px;align-items:center}
.transport button{padding:5px 9px;font-size:15px;line-height:1;min-width:34px}
.transport button.primary{min-width:40px}
#vizbtns{display:inline-flex;gap:8px}
#rspacer{margin-left:auto}                                          /* flush the weak/prim/menu group to the right */
#menubtn{font-size:18px;line-height:1;padding:5px 11px}
/* dynamic toolbar: buttons explode (blow up + vanish) when not needed and the rest flush in */
#bar .transport, #bar > #weakbtn, #bar > #matrixbtn, #weakctrls, #abctrls{
  transition:transform .34s cubic-bezier(.34,1.6,.6,1), opacity .2s ease, max-width .34s ease,
    margin-left .34s ease, padding .34s ease, border-width .12s ease;
  max-width:160px; overflow:hidden; white-space:nowrap; }
#abctrls{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto}
.explode{ transform:scale(1.75)!important; opacity:0!important; max-width:0!important;
  margin-left:-10px!important; padding-left:0!important; padding-right:0!important; border-width:0!important; pointer-events:none!important; }
#menu{position:fixed;top:calc(var(--barh) + 4px);right:12px;width:230px;background:#0d1626f5;border:1px solid #23324e;
  border-radius:10px;padding:10px 12px;display:none;z-index:30}
#menu .row{display:flex;justify-content:space-between;align-items:center;margin:9px 2px}
#menu .msep{border:none;border-top:1px solid #23324e;margin:10px 0 8px}
.pill{position:relative;display:inline-block;width:40px;height:22px;flex:0 0 auto}
.pill input{opacity:0;width:0;height:0}
.pill i{position:absolute;inset:0;background:#2b3a58;border-radius:22px;transition:.18s;cursor:pointer}
.pill i:before{content:'';position:absolute;height:16px;width:16px;left:3px;top:3px;background:#fff;border-radius:50%;transition:.18s}
.pill input:checked+i{background:#2f7d5a}
.pill input:checked+i:before{transform:translateX(18px)}
#warn{position:fixed;top:calc(var(--barh) + 10px);right:14px;background:#3a2a14;border:1px solid #d0a040;color:#ffe0a0;
  border-radius:8px;padding:6px 12px;font-size:12px;z-index:25;display:none}
@keyframes shake{0%,100%{transform:translateX(0)}20%{transform:translateX(-4px)}40%{transform:translateX(4px)}
  60%{transform:translateX(-3px)}80%{transform:translateX(3px)}}
.shake{animation:shake .42s}
#weakstat .katex{font-size:1.05em}
#weakbtn.active,#primbtn.active,#matrixbtn.active,.abbtn.active{background:#1d3a6b;border-color:#2f5aa0;color:#cfe0f7}
/* decomposition pull-tab: a vertical journal-separator tab docked to the left edge; rides the panel's right edge when open */
#decomptab{position:fixed;top:calc(var(--barh) + 76px);left:0;z-index:14;   /* ~2cm below the bar so it never clashes with the R(h) legend (which can wrap on mobile) */
  writing-mode:vertical-rl;text-orientation:mixed;white-space:nowrap;
  padding:16px 8px;cursor:grab;font-size:13px;letter-spacing:.6px;user-select:none;touch-action:none;
  color:var(--dim);background:linear-gradient(90deg,#182338,#101828);
  border:1px solid #24314b;border-left:none;border-radius:0 10px 10px 0;box-shadow:2px 2px 12px #0006;
  transition:color .18s, background .18s, border-color .18s}   /* NO left-transition: the tab tracks the panel edge in lockstep */
#decomptab:hover{border-color:var(--accent);color:var(--ink)}
#decomptab:active{cursor:ew-resize}
#decomptab.active{background:#1d3a6b;border-color:#2f5aa0;color:#cfe0f7}
#decomptab.tabhide{display:none}
body.ppopen #decomptab{left:var(--ppw,48vw)}
.abbtn{padding:5px 10px;font-family:ui-monospace,monospace;min-width:26px}
#weakctrls{display:inline-flex;align-items:center;gap:7px}
#weakctrls select{padding:5px 6px}
#weakstat,#polstat{position:fixed;right:12px;top:calc(var(--barh) + 10px);max-width:calc(100vw - 24px);background:#0d1626e6;border:1px solid #23324e;border-radius:8px;
  padding:6px 11px;font-size:12px;color:var(--dim);z-index:16;display:none}
#weakstat b,#polstat b{color:#cfe0f7}
#polstat .katex{font-size:1.05em}
body.ppopen #weakstat,body.ppopen #polstat{max-width:calc(100vw - var(--ppw,48vw) - 24px)}   /* right-flushed: cap the width so it can't run under the decomposition panel */
.posetlink{color:var(--accent);cursor:pointer;text-decoration:underline dotted;text-underline-offset:2px}
.posetlink:hover{color:#cfe0f7;text-decoration-style:solid}
#abstat{position:fixed;right:12px;top:calc(var(--barh) + 10px);max-width:calc(100vw - 24px);background:#0d1626e6;border:1px solid #23324e;
  border-radius:8px;padding:6px 11px;font-size:12px;color:var(--dim);z-index:16;display:none;white-space:nowrap}
#abstat b{color:#cfe0f7}
#abstat .ok{color:var(--grn)}
#abstat .bad{color:var(--red)}
#abstat .katex{font-size:1.05em;color:#cfe0f7}
/* primitive-decomposition panel: pannable grid of the KPR pieces P_w(-a) */
#primpanel{position:fixed;left:0;top:var(--barh);width:var(--ppw,48vw);height:calc(100vh - var(--barh));z-index:13;
  background:#0b1322;border-right:1px solid #23324e;display:none;flex-direction:column}
#primpanel.shown{display:flex}
#pp-title{padding:11px 74px 8px 16px;color:var(--dim);font-size:14px;line-height:1.5;border-bottom:1px solid #17243c}   /* right padding keeps the equation clear of the prim button */
#primpanel #primbtn{position:absolute;top:9px;right:12px;z-index:3;padding:5px 11px}   /* prim lives in the panel's top-right corner (pol & pol+prim) */
#pp-title .katex{font-size:1.02em;color:#cfe0f7}
#pp-title p{display:inline;margin:0}   /* markdown wraps the equation in <p>; keep it inline so the node canvas sits beside it */
#pp-title .sub{display:block;font-size:11px;opacity:.62;margin-top:5px}
#ppcanvas{flex:1;width:100%;min-height:0;display:block;cursor:grab;touch-action:none}
#ppcanvas:active{cursor:grabbing}
#pp-expl{padding:10px 16px 12px;border-top:1px solid #17243c;color:var(--dim);font-size:12px;line-height:1.5;max-height:38%;overflow:auto;flex:0 0 auto}
#pp-expl .katex{font-size:1em;color:#cfe0f7}
#pp-expl b,#pp-expl strong{color:#cfe0f7}
#pp-expl p{margin:.4em 0}
#pp-expl p:first-child{margin-top:0}
#pp-expl p:last-child{margin-bottom:0}
/* decomposition panel open: keep the graph-side hint visible, moved over the graph (right of the panel) */
body.ppopen #hint{left:calc(var(--ppw,48vw) + 12px);max-width:calc(100vw - var(--ppw,48vw) - 24px)}
body.ppopen #hintshow{left:calc(var(--ppw,48vw) + 12px)}
