/* =============================================================================
   _ministudio.css - the compact skin bench that opens IN PLACE.

   WHAT THIS SHEET IS
   The look for js/ministudio.mjs and nothing else. Every rule is scoped under
   `.ms`, so this file cannot reach a single element on any page it is loaded
   beside. It is the same house as _studio.css at a smaller size with fewer
   controls - not the same controls squashed.

   WHAT IT REFUSES TO DO
   * It REDEFINES NO SITE TOKEN. --bg --rule --rule-hot --blue --blue-dim
     --green --amber --red --mono --wide --pixel --t-* --sh-* --pad all come
     from _term.css and are only ever READ here. Everything this sheet invents
     is prefixed --ms- and declared once, at the top.
   * It authors NO opaque page background. The bench sits over the calm parked
     plate AND over body[data-subject="live"] (the lightning lab a sibling
     agent is building), so its ground is translucent ink and its accent is a
     token the live theme moves - never a colour that fights either one.
   * It does not style .act, .panel, .chip, .row, .slider or any other shared
     class name. _studio.css is NOT loaded on editor.html and this bench must
     look right without it, so every control here is its own .ms-* element.

   ★ THE LAWS THIS SHEET WAS BUILT AGAINST, EACH ONE ALREADY PAID FOR
   1. A DROPPED CSS DECLARATION IS SILENT. A bare `input[type="text"]` in a
      sheet loaded after this one is (0,1,1) and would beat `.ms-hex` (0,1,0),
      which is exactly how a hex field once showed "#E08" for "#E0883B". Every
      load-bearing control here is selected at THREE classes plus its element
      (`.ms .ms-ch input[type="text"].ms-hex`, (0,3,1)) so nothing a sibling
      can reasonably write outranks it. NOTHING here uses !important to win a
      cascade fight - the two !importants in this file are on `[hidden]` and on
      the reduced-motion kill, which are the sanctioned uses.
   2. `[hidden]` LOSES TO ANY AUTHORED `display`. Three elements in this bench
      are toggled with the `hidden` property AND carry an authored display, so
      each one has an explicit `[hidden]` rule that outranks its own display.
   3. NEVER A HEADING, A NAME OR A VALUE IN NEAR-WHITE BLUE. Headings are
      #79D9FF, values are #4BB4FC, labels are --blue-dim. He has rejected the
      pale look eight times.
   4. NO HORIZONTAL PAGE SCROLL. Every column is `minmax(0,1fr)`, every flex
      child that can hold long text carries `min-width:0`, and the one thing
      that can genuinely outgrow its box - the channel list - scrolls inside
      its own well rather than pushing the page sideways.
   ============================================================================= */

:root{
  /* Frame and ground. Translucent on purpose - see "no opaque page background". */
  --ms-line:rgba(30,111,224,.55);
  --ms-line-soft:rgba(30,111,224,.28);
  --ms-ink:rgba(1,4,10,.72);
  --ms-ink-deep:rgba(1,4,10,.86);
  --ms-well:rgba(0,4,12,.55);

  /* Type colours. Law 3 lives in these three lines. */
  --ms-head:#79D9FF;      /* headings and control text */
  --ms-val:#4BB4FC;       /* every number and every hex */
  --ms-accent:#4BB4FC;    /* the lit edge; the live theme moves this */

  /* Geometry. One place, so a resize is one edit. */
  --ms-pad:12px;
  --ms-gap:10px;
  --ms-stage-h:clamp(190px,25vh,286px);
  --ms-hex-w:70px;        /* proven: fits "#E0883B" whole at 11.5px mono */
  --ms-sw:30px;
}

/* THE LIVE LAB. Scoped to this bench's own root so it can never repaint the
   page around it. `--ed-live` is the sibling's token when their sheet declares
   one; the fallback is this bench's own hotter blue, so the bench is right
   whether _editor.css has landed yet or not. */
body[data-subject="live"] .ms{
  --ms-accent:var(--ed-live,#64E6FF);
  --ms-line:rgba(100,230,255,.42);
  --ms-line-soft:rgba(100,230,255,.20);
}

/* ---------- the root: two locks on visibility ----------------------------
   The HOST is the page's element and its `hidden` can lose to a `display:`
   authored in a sheet this file does not own. So the root is display:none in
   ITS OWN sheet unless the module puts data-open on it. Law 2 guards both. */
.ms{display:none;min-width:0}
.ms[data-open]{display:block}
.ms[hidden]{display:none !important}

/* ---------- the panel ----------------------------------------------------- */
.ms .ms-panel{
  position:relative;min-width:0;
  border:1px solid var(--ms-line);
  background:var(--ms-ink);
  backdrop-filter:blur(10px) saturate(1.15);
  box-shadow:inset 3px 0 0 var(--ms-accent),0 0 60px -34px rgba(61,155,255,.9);
  padding:var(--ms-pad);
  display:flex;flex-direction:column;gap:var(--ms-gap);
}
/* The corner brackets the whole site draws on a frame. Pointer-events off so
   they can never eat a click meant for a control underneath. */
.ms .ms-panel::before,.ms .ms-panel::after{
  content:"";position:absolute;width:9px;height:9px;pointer-events:none;
  border:1px solid var(--ms-accent);opacity:.9}
.ms .ms-panel::before{left:-1px;top:-1px;border-right:0;border-bottom:0}
.ms .ms-panel::after{right:-1px;bottom:-1px;border-left:0;border-top:0}
.ms .ms-panel:focus{outline:none}
.ms .ms-panel:focus-visible{outline:1px solid var(--ms-accent);outline-offset:3px}

/* ---------- head ---------------------------------------------------------- */
.ms .ms-head{
  display:flex;align-items:center;justify-content:space-between;
  gap:10px;flex-wrap:wrap;min-width:0;
  padding-bottom:9px;border-bottom:1px solid var(--ms-line-soft)}
.ms .ms-head .ms-title{
  margin:0;min-width:0;flex:1 1 12ch;
  font-family:var(--wide);font-size:14px;font-weight:560;letter-spacing:.06em;
  color:var(--ms-head);text-shadow:var(--sh-body);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ms .ms-head .ms-headr{display:flex;align-items:center;gap:9px;flex:none}
.ms .ms-head .ms-sub{
  font-family:var(--pixel);font-size:10px;letter-spacing:.12em;
  color:var(--blue-dim);text-shadow:var(--sh-micro);white-space:nowrap}

/* ---------- the two columns ----------------------------------------------
   minmax(0,1fr) on BOTH, never `1fr`: a grid item's default min-width:auto is
   what lets one long word push a whole column past the viewport (law 4). */
.ms .ms-grid{
  display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);
  gap:var(--ms-gap);align-items:stretch;min-width:0}
.ms .ms-col{display:flex;flex-direction:column;gap:8px;min-width:0}

@media (max-width:900px){
  .ms .ms-grid{grid-template-columns:minmax(0,1fr)}
}

/* ---------- the specimen well --------------------------------------------
   `position:relative` is load-bearing: skinstage inserts its canvas as the
   first child with `position:absolute;inset:0` and the gate, the hud and the
   progress bar all sit over it. A static well would drop every one of them
   onto the page. */
/* ★ The stage GROWS to fill the left column (the grid stretches both columns
   to the taller one) rather than sitting at a fixed height with dead space
   under it. A design bench is judged on the animal, so the animal takes every
   pixel the instruments do not need. min-height is the floor for the case
   where the right column is the shorter of the two. */
.ms .ms-stage{
  position:relative;min-width:0;
  flex:1 1 auto;min-height:var(--ms-stage-h);
  border:1px solid var(--ms-line);
  background:
    radial-gradient(120% 90% at 50% 8%,rgba(30,111,224,.12),transparent 62%),
    var(--ms-well);
  overflow:hidden;
  touch-action:none}
.ms .ms-stage canvas{display:block}

/* The gate carries the ONE sentence that says why there is no animal: no
   WebGL, no model on this box, or a mesh still loading. It is never a spinner
   with no words. */
.ms .ms-gate{
  position:absolute;inset:0;z-index:2;
  display:flex;align-items:center;justify-content:center;
  padding:16px;text-align:center;
  background:linear-gradient(180deg,rgba(0,3,10,.55),rgba(0,3,10,.86))}
.ms .ms-gate[hidden]{display:none}          /* law 2 */
.ms .ms-gate .ms-gate-l{
  max-width:42ch;
  font-family:var(--mono);font-size:11.5px;line-height:1.75;letter-spacing:.06em;
  color:var(--ms-head);text-shadow:var(--sh-micro)}

.ms .ms-hud{
  position:absolute;top:7px;left:7px;z-index:3;pointer-events:none;
  padding:3px 7px;
  border:1px solid var(--ms-accent);background:var(--ms-ink-deep);
  font-family:var(--pixel);font-size:9.5px;letter-spacing:.14em;
  color:var(--ms-val);text-shadow:var(--sh-micro)}
.ms .ms-hud[hidden]{display:none}           /* law 2 */

.ms .ms-prog{
  position:absolute;left:0;right:0;bottom:0;z-index:3;
  display:block;height:2px;background:rgba(30,111,224,.20)}
.ms .ms-prog-f{
  display:block;height:100%;width:0;
  background:var(--ms-accent);
  box-shadow:0 0 10px -2px var(--ms-accent);
  transition:width .18s linear}

/* ---------- labels, rows, groups ------------------------------------------ */
.ms .ms-k{
  flex:none;font-family:var(--pixel);font-size:10px;letter-spacing:.13em;
  color:var(--blue-dim);text-shadow:var(--sh-micro);min-width:66px}
.ms .ms-row{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0;
  padding:7px 0;border-top:1px solid var(--ms-line-soft)}
.ms .ms-grp{display:flex;align-items:center;gap:5px;flex-wrap:wrap;min-width:0}
.ms .ms-grp-r{margin-left:auto}
/* "CLICK THE ANIMAL" is hidden whenever there is no animal, so it needs the
   law-2 guard against a `p{display:block}` in any sheet loaded beside this. */
.ms .ms-note{
  margin:0;font-family:var(--pixel);font-size:9.5px;letter-spacing:.11em;
  line-height:1.7;color:var(--blue-dim);text-shadow:var(--sh-micro)}
.ms .ms-note[hidden]{display:none}

/* ---------- buttons -------------------------------------------------------
   Selected at .ms + .ms-act + the element so a bare `button` rule in another
   sheet cannot take the border or the colour off them (law 1). */
.ms button.ms-act{
  position:relative;flex:none;
  font-family:var(--pixel);font-size:10.5px;letter-spacing:.11em;
  padding:6px 10px;
  color:var(--ms-head);text-shadow:var(--sh-micro);
  background:transparent;
  border:1px solid var(--ms-line);
  box-shadow:0 0 0 1px rgba(1,5,11,.9),inset 0 0 0 1px rgba(1,5,11,.7);
  cursor:pointer;
  transition:border-color .15s linear,color .15s linear,background .15s linear}
.ms button.ms-act:hover{border-color:var(--ms-accent);color:#A8E7FF}
.ms button.ms-act:focus-visible{outline:1px solid var(--ms-accent);outline-offset:2px}
.ms button.ms-act[disabled]{opacity:.36;cursor:default;pointer-events:none}
.ms button.ms-act.ms-go{padding:7px 14px;font-size:11px}
.ms button.ms-act.ms-hot{
  color:var(--ms-val);border-color:var(--ms-accent);
  background:rgba(30,111,224,.16);
  box-shadow:0 0 0 1px rgba(1,5,11,.9),inset 0 -2px 0 var(--ms-accent)}
.ms button.ms-act.ms-hot:hover{background:rgba(30,111,224,.28)}

/* ---------- chips: harmony and pattern ------------------------------------ */
.ms button.ms-chip{
  flex:none;
  font-family:var(--wide);font-size:9.5px;letter-spacing:.13em;
  padding:3px 7px;
  color:var(--blue-dim);background:transparent;
  border:1px solid var(--ms-line);
  text-shadow:var(--sh-micro);cursor:pointer;
  transition:color .14s linear,border-color .14s linear,background .14s linear}
.ms button.ms-chip:hover{color:var(--ms-head);border-color:var(--ms-accent)}
.ms button.ms-chip:focus-visible{outline:1px solid var(--ms-accent);outline-offset:2px}
.ms button.ms-chip.on,.ms button.ms-chip[aria-pressed="true"]{
  color:var(--ms-val);border-color:var(--ms-accent);
  background:rgba(30,111,224,.20);box-shadow:inset 0 -2px 0 var(--ms-accent)}
.ms button.ms-chip.ms-chip-n{min-width:22px;text-align:center;padding:3px 5px}

/* ---------- the seven channels -------------------------------------------
   The one thing in this bench that can genuinely outgrow its box, so it gets
   its own scroll well and the page never moves sideways for it (law 4). */
/* SEVEN rows is a FIXED list and it must not scroll on any ordinary screen -
   a scrollbar over a list you can count on one hand reads as a broken box.
   340px is measured, not guessed: a row is 38px and six gaps are 18, so the
   whole list is 284px. The vh term only bites on a genuinely short viewport
   (a landscape phone), and only then does the well scroll. */
.ms .ms-chans{
  display:grid;gap:3px;min-width:0;
  max-height:min(60vh,340px);overflow-y:auto;overscroll-behavior:contain;
  padding-right:2px}
.ms .ms-ch{
  display:flex;align-items:center;gap:8px;min-width:0;
  padding:5px 7px;
  background:rgba(1,4,10,.62);
  border:1px solid var(--ms-line-soft);
  transition:border-color .14s linear,background .14s linear}
.ms .ms-ch:hover{background:rgba(30,111,224,.10);border-color:var(--ms-line)}
.ms .ms-ch.ms-sel{
  background:rgba(30,111,224,.15);border-color:var(--ms-accent);
  box-shadow:inset 3px 0 0 var(--ms-accent)}
.ms .ms-ch.ms-bad{border-color:var(--red);box-shadow:inset 3px 0 0 var(--red)}
.ms .ms-ch.ms-bad input[type="text"].ms-hex{color:var(--red);border-color:var(--red)}

/* The swatch. The colour input is stretched over the whole tile and made
   invisible, so the CLICK TARGET is the tile itself at every browser's own
   idea of what a colour control looks like. */
.ms .ms-ch .ms-sw{
  position:relative;flex:none;display:block;
  width:var(--ms-sw);height:21px;
  border:1px solid rgba(1,5,11,.9);
  box-shadow:0 0 0 1px var(--ms-line-soft);
  overflow:hidden;cursor:pointer}
.ms .ms-ch input[type="color"].ms-swin{
  position:absolute;inset:-6px;width:calc(100% + 12px);height:calc(100% + 12px);
  padding:0;margin:0;border:0;background:transparent;cursor:pointer;
  -webkit-appearance:none;appearance:none}
.ms .ms-ch input[type="color"].ms-swin::-webkit-color-swatch-wrapper{padding:0}
.ms .ms-ch input[type="color"].ms-swin::-webkit-color-swatch{border:0}
.ms .ms-ch input[type="color"].ms-swin::-moz-color-swatch{border:0}
.ms .ms-ch input[type="color"].ms-swin:focus-visible{outline:2px solid var(--ms-accent)}

.ms .ms-ch .ms-chname{
  flex:1 1 auto;min-width:0;
  font-family:var(--wide);font-size:10px;letter-spacing:.12em;
  color:var(--ms-head);text-shadow:var(--sh-micro);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ★ LAW 1 LIVES HERE. (0,3,1) - three classes and the element - so a bare
   `input[type="text"]` (0,1,1) or a `.ed-thing input[type="text"]` (0,2,1) in
   a sibling's sheet cannot take the width off this field and truncate a hex
   to "#E08". The width is fixed and flex:none because a shrinking field is
   the same bug wearing a different hat. */
.ms .ms-ch input[type="text"].ms-hex{
  flex:none;box-sizing:border-box;
  width:var(--ms-hex-w);min-width:var(--ms-hex-w);
  padding:5px 5px;
  font-family:var(--mono);font-size:11.5px;letter-spacing:.01em;
  font-variant-numeric:tabular-nums;
  text-transform:uppercase;text-align:center;
  color:var(--ms-val);text-shadow:var(--sh-micro);
  background:rgba(1,4,10,.62);
  border:1px solid var(--ms-line);
  transition:border-color .15s linear}
.ms .ms-ch input[type="text"].ms-hex:focus{
  outline:none;border-color:var(--ms-accent);background:rgba(1,4,10,.85)}
.ms .ms-ch input[type="text"].ms-hex:focus-visible{
  outline:1px solid var(--ms-accent);outline-offset:1px}

/* ---------- sliders -------------------------------------------------------
   Drawn by hand so a range reads as a terminal readout rather than a pill.
   Same three-class guard as the hex field. */
.ms .ms-slide{
  display:flex;align-items:center;gap:9px;min-width:0;
  padding:7px 0;border-top:1px solid var(--ms-line-soft)}
.ms .ms-slide .ms-val{
  flex:none;min-width:46px;text-align:right;
  font-family:var(--mono);font-size:11px;letter-spacing:.06em;
  font-variant-numeric:tabular-nums;
  color:var(--ms-val);text-shadow:var(--sh-micro)}
.ms .ms-panel input[type="range"].ms-range{
  flex:1 1 auto;min-width:0;
  -webkit-appearance:none;appearance:none;
  height:16px;padding:0;margin:0;background:transparent;border:0;
  cursor:ew-resize}
.ms .ms-panel input[type="range"].ms-range::-webkit-slider-runnable-track{
  height:3px;border:0;
  background:linear-gradient(90deg,rgba(75,180,252,.55),rgba(30,111,224,.30))}
.ms .ms-panel input[type="range"].ms-range::-moz-range-track{
  height:3px;border:0;
  background:linear-gradient(90deg,rgba(75,180,252,.55),rgba(30,111,224,.30))}
.ms .ms-panel input[type="range"].ms-range::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;
  width:5px;height:16px;margin-top:-7px;border:0;border-radius:0;
  background:var(--ms-accent);
  box-shadow:0 0 0 1px rgba(1,5,11,.9),0 0 10px -2px var(--ms-accent)}
.ms .ms-panel input[type="range"].ms-range::-moz-range-thumb{
  width:5px;height:16px;border:0;border-radius:0;
  background:var(--ms-accent);box-shadow:0 0 0 1px rgba(1,5,11,.9)}
.ms .ms-panel input[type="range"].ms-range:focus-visible{
  outline:1px solid var(--ms-accent);outline-offset:4px}

/* ---------- foot ---------------------------------------------------------- */
.ms .ms-foot{
  display:flex;align-items:center;gap:9px;flex-wrap:wrap;min-width:0;
  padding-top:9px;border-top:1px solid var(--ms-line-soft)}
.ms .ms-foot .ms-msg{
  flex:1 1 16ch;min-width:0;margin:0;
  font-family:var(--pixel);font-size:9.5px;letter-spacing:.10em;line-height:1.6;
  color:var(--blue-dim);text-shadow:var(--sh-micro)}

/* The name field. Same (0,3,1) guard as the hex field, and it is allowed to
   shrink because a name is not a fixed-width value. */
.ms .ms-foot input[type="text"].ms-name{
  flex:1 1 12ch;min-width:0;box-sizing:border-box;max-width:22ch;
  padding:6px 8px;
  font-family:var(--mono);font-size:11px;letter-spacing:.06em;
  color:var(--ms-val);text-shadow:var(--sh-micro);
  background:rgba(1,4,10,.62);
  border:1px solid var(--ms-line);
  transition:border-color .15s linear}
.ms .ms-foot input[type="text"].ms-name::placeholder{
  color:var(--blue-dim);opacity:.7;letter-spacing:.10em}
.ms .ms-foot input[type="text"].ms-name:focus{
  outline:none;border-color:var(--ms-accent);background:rgba(1,4,10,.85)}
.ms .ms-foot input[type="text"].ms-name:focus-visible{
  outline:1px solid var(--ms-accent);outline-offset:1px}

/* ---------- the one-shot pick flash --------------------------------------
   700ms, then it settles. Transform and colour only: no layout, no filter on
   a large area, and never a permanent strobe. */
@keyframes ms-hit{
  0%{box-shadow:inset 3px 0 0 var(--ms-accent),0 0 0 0 rgba(75,180,252,.55)}
  40%{box-shadow:inset 3px 0 0 var(--ms-accent),0 0 16px -2px rgba(75,180,252,.75)}
  100%{box-shadow:inset 3px 0 0 var(--ms-accent),0 0 0 0 rgba(75,180,252,0)}
}
.ms .ms-ch.ms-hit{animation:ms-hit .7s cubic-bezier(.2,.8,.2,1) 1}

/* ---------- narrow ---------------------------------------------------------
   412px is a real phone and the bench has to be usable on one. The channel
   list keeps its swatch and its WHOLE hex - the NAME is what gives up room,
   because a truncated part name is a nuisance and a truncated hex is a bug. */
@media (max-width:520px){
  .ms{--ms-pad:10px;--ms-gap:8px;--ms-stage-h:clamp(170px,32vh,230px)}
  .ms .ms-k{min-width:0}
  .ms .ms-ch .ms-chname{flex:1 1 4ch;font-size:9.5px;letter-spacing:.08em}
  .ms .ms-foot .ms-msg{flex:1 1 100%;order:9}
  .ms .ms-foot input[type="text"].ms-name{max-width:none;flex:1 1 8ch}
}

/* ---------- reduced motion -------------------------------------------------
   Kills every animation and transition in the bench and leaves the colour.
   One of the two sanctioned !importants in this file: it must beat the
   author's own transitions above, and there is no specificity fight to win -
   only a global off switch. */
@media (prefers-reduced-motion:reduce){
  .ms *,.ms *::before,.ms *::after{
    animation:none !important;
    transition:none !important;
    scroll-behavior:auto !important}
}

/* ---------- forced colours -------------------------------------------------
   In a high-contrast forced-colours mode the browser repaints text and
   borders itself. The swatch tiles must not be repainted - a colour swatch
   whose colour has been overridden is a lie - so they opt out by name. */
@media (forced-colors:active){
  .ms .ms-ch .ms-sw{forced-color-adjust:none}
  .ms button.ms-act,.ms button.ms-chip{border-color:ButtonBorder}
}
