/* =========================================================================
   studio.css — ?studio=1 recording layout
   -------------------------------------------------------------------------
   Studio mode is a FLAG, not a fork. Every rule in this file is scoped under
   body.studio and reflows the DOM index.html already has into a 9:16 frame:

     #app-container        the 9:16 frame, and the Region Capture crop target
       #canvas-wrapper     row 1  1fr    breadboard + floating talking head
       #terminal-container display:contents, so its three children become
                           rows 2-4 directly
         #terminal-state   row 2  12%    the live numbers
         #terminal-log     row 3  14%    the terminal
         #inventory-panel  row 4  auto   toolbox, hugging one row of slots

   display:contents on #terminal-container is what makes this possible with
   zero markup change — its children join the grid, and grid-row puts STATE
   above LOG even though the DOM order is log, toolbox, state.

   Everything the operator needs but the audience must not see lives in
   #studio-rail, which sits OUTSIDE the frame and is therefore outside the
   crop region. Nothing in the rail can ever end up in a take.
   ========================================================================= */

/* Everything inside the frame is authored against a 1080-wide reference and
   multiplied by this. studio.js sets it on <html> to frameWidth / 1080, so the
   frame is the same PICTURE at any preview size — which is what lets the
   offscreen compositor render an identical image at the real output size.

   Declared on :root, NOT on body.studio: studio.js writes it as an inline
   style on <html>, and a declaration on body would be a nearer ancestor for
   everything in the frame and would quietly win. */
:root {
  --studio-k: 1;

  /* ---- studio typography, the single source of truth --------------------
     Unitless, authored against the same 1080-wide reference as --studio-k.
     compositor.js reads these off <html> every frame and multiplies by its
     own kd, so the recorded video and the live preview are guaranteed to
     agree. Change a size HERE and nowhere else — the canvas follows.
     (Before this existed the sizes were retyped in compositor.js and had
     drifted to 0.40-0.68x, so studio.css edits never reached the video.) */
  --st-state-head-fs: 22;
  --st-state-title-fs: 14;
  --st-state-row-fs: 22;
  --st-state-row-h: 34;
  --st-log-fs: 22;
  --st-log-chip-fs: 14;
  --st-slot-lbl-fs: 20;
  --st-divider-fs: 20;
  --st-badge-fs: 12;
  --st-cursor-ring: 38;
  --st-cursor-dot: 9;
}

body.studio {
  background: #0b0f14;
  overflow: hidden;
}

/* The frame. JS sets --studio-w/h to the largest 9:16 box that fits, capped
   at exactly 1080x1920 CSS px, and --studio-x/y to where it landed — the
   wiki bottom sheet is position:fixed and needs those to line up. */
body.studio #app-container {
  position: fixed;
  left: var(--studio-x, 0px);
  top: var(--studio-y, 0px);
  width: var(--studio-w, 1080px);
  height: var(--studio-h, 1920px);
  display: grid;
  /* The toolbox row is `auto` — it hugs one row of slots plus 2px of padding
     rather than claiming a fixed 18%. The breadboard takes `1fr`, so every
     pixel the strip does not need goes to the star of the shot: the board
     lands around 69% of the frame instead of 56%. */
  grid-template-rows: 1fr 12% 14% auto;
  grid-template-columns: 100%;
  background: var(--canvas-bg);
  box-shadow: 0 0 0 1px #223042;
  overflow: hidden;
  /* Region Capture crops to this box. An outline is painted OUTSIDE the
     border box, so the recording ring below never lands in the video. */
  outline: 0 solid transparent;
  outline-offset: 5px;
  transition: outline-color 0.15s linear;
}

body.studio.rec #app-container {
  outline-width: 4px;
  outline-color: #ff2d55;
  animation: studio-rec-ring 1.6s ease-in-out infinite;
}
@keyframes studio-rec-ring {
  0%,
  100% {
    outline-color: #ff2d55;
  }
  50% {
    outline-color: rgba(255, 45, 85, 0.35);
  }
}

/* ---- rows ------------------------------------------------------------- */
body.studio #canvas-wrapper {
  grid-row: 1;
  min-height: 0;
  flex: none;
}
body.studio #terminal-container {
  display: contents;
}
body.studio #terminal-state {
  grid-row: 2;
  flex: none;
  min-height: 0;
  border-right: 0;
  border-top: 2px solid var(--border-color);
  padding: calc(10px * var(--studio-k)) calc(16px * var(--studio-k));
  /* auto, not hidden: at 12% of the frame the board stats can outgrow the
     row, and a line sliced through the middle looks like a rendering bug on
     camera. style.css already gives this pane the invisible-scrollbar
     treatment, so it scrolls without ever drawing one. */
  overflow-y: auto;
}
body.studio #terminal-log {
  grid-row: 3;
  flex: none;
  min-height: 0;
  border-right: 0;
  border-top: 2px solid var(--border-color);
  padding: calc(12px * var(--studio-k)) calc(16px * var(--studio-k));
}
body.studio #inventory-panel {
  grid-row: 4;
  flex: none;
  min-height: 0;
  border-right: 0;
  border-top: 2px solid var(--border-color);
}

/* The resizer is a real flex item between the two panes; in a fixed 4-row
   grid there is nothing to resize, so it goes away entirely. */
body.studio #terminal-resizer {
  display: none;
}

/* ---- chrome that must not appear on camera ---------------------------- */
body.studio #hud,
body.studio #tip,
body.studio #toolbar,
body.studio #timebase {
  display: none !important;
}

/* ---- row 2: state, wider and bigger, two columns ---------------------- */
body.studio .state-header {
  font-size: calc(var(--st-state-head-fs) * 1px * var(--studio-k));
  letter-spacing: 0.22em;
  padding-bottom: calc(6px * var(--studio-k));
}
body.studio #state-data {
  columns: 2;
  column-gap: calc(26px * var(--studio-k));
  font-size: calc(var(--st-state-row-fs) * 1px * var(--studio-k));
}
body.studio .srow {
  break-inside: avoid;
  padding: calc(3px * var(--studio-k)) 0;
}
body.studio .state-section-title {
  break-after: avoid;
  /* style.css sets a flat 10px here, which would NOT scale with the frame.
     Tokenised so it tracks --studio-k like everything else inside the box. */
  font-size: calc(var(--st-state-title-fs) * 1px * var(--studio-k));
}

/* ---- row 3: the log, sized to be readable on a phone ------------------ */
body.studio .log-entry {
  font-size: calc(var(--st-log-fs) * 1px * var(--studio-k));
  margin-bottom: calc(6px * var(--studio-k));
}
body.studio .log-chip,
body.studio .log-pin {
  font-size: calc(var(--st-log-chip-fs) * 1px * var(--studio-k));
}

/* ---- row 4: toolbox as ONE horizontally-scrolling strip ---------------
   19+ palette entries plus three assembly families cannot be a 74px grid at
   1080px wide — it would be six rows tall. As a single nowrap flex row it is
   one flick of the trackpad on camera, which also reads better in a video
   than a wall of icons. */
body.studio .inv-header {
  display: none;
}
body.studio #inventory-grid {
  display: flex;
  flex-flow: row nowrap;
  align-items: center;
  gap: calc(14px * var(--studio-k));
  padding: calc(30px * var(--studio-k)) calc(30px * var(--studio-k));
  overflow-x: auto;
  overflow-y: hidden;
  scroll-behavior: smooth;
  overscroll-behavior-x: contain;
}
body.studio .slot {
  flex: 0 0 auto;
  width: calc(180px * var(--studio-k));
  height: calc(180px * var(--studio-k));
  gap: 1px;
  padding: calc(5px * var(--studio-k)) calc(4px * var(--studio-k))
    calc(4px * var(--studio-k));
  border-radius: calc(60px * var(--studio-k));
}
body.studio .slot canvas {
  width: calc(100px * var(--studio-k));
  height: calc(100px * var(--studio-k));
}
body.studio .slot .lbl {
  font-size: calc(var(--st-slot-lbl-fs) * 1px * var(--studio-k));
}
body.studio .slot.tool-slot::after,
body.studio .slot.assembly-slot::after {
  /* Was a flat 12px, so the RTL/CMOS/TOOL badges did not scale with the
     frame like everything else in it. compositor.js reads this back off the
     pseudo-element, so tokenising it fixes the preview and the take at once. */
  font-size: calc(var(--st-badge-fs) * 1px * var(--studio-k));
}
/* Section headings become slim vertical dividers between the families
   instead of full-width rows. */
/* Family dividers become slim vertical rules. The full heading text cannot
   fit at 86px tall, so main.js gives each section a data-short and this swaps
   it in — the badge on each slot already carries the same word. */
body.studio .inv-section {
  grid-column: auto;
  flex: 0 0 auto;
  writing-mode: vertical-rl;
  text-orientation: mixed;
  transform: rotate(180deg);
  height: calc(70px * var(--studio-k));
  margin: 0 3px;
  padding: 0 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-left: 1px solid #e6eaef;
  white-space: nowrap;
  overflow: hidden;
  font-size: 0; /* hides the long label; ::after supplies the short one */
}
body.studio .inv-section::after {
  content: attr(data-short);
  font-size: calc(var(--st-divider-fs) * 1px * var(--studio-k));
  font-weight: 600;
  letter-spacing: 0.16em;
  color: #97a3af;
}
body.studio .inv-section:first-child {
  border-left: 0;
}

/* =========================================================================
   The talking head — a draggable, resizable camera circle over the board
   ========================================================================= */
#studio-head {
  position: absolute;
  z-index: 40;
  width: 240px;
  height: 240px;
  border-radius: 50%;
  overflow: visible;
  cursor: grab;
  touch-action: none;
  transition: opacity 0.18s ease;
}
#studio-head.dragging {
  cursor: grabbing;
}
#studio-head.hidden {
  opacity: 0;
  pointer-events: none;
}
#studio-head video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
  background: #10161d;
  box-shadow:
    0 0 0 4px #ffffff,
    0 0 0 6px rgba(3, 102, 214, 0.55),
    0 14px 40px rgba(10, 20, 35, 0.34);
}
#studio-head.mirrored video {
  transform: scaleX(-1);
}
/* The grip stands ON the circle's rim at 45 degrees, not in the corner of the
   square box around it.

   It used to be right/bottom: 4%, which is a corner of the SQUARE — and the
   gap between a circle and its bounding box's corner grows with the radius.
   Measured: 3px inside the rim on a 101px head, 20px outside it at 253px,
   49px outside at 450px. Since #studio-head is border-radius: 50%, hit
   testing follows the circle, so out there the pointer is not over the head,
   :hover drops, and the grip — which is only revealed by :hover — fades out
   while you are reaching for it. The bigger the head, the wider that dead
   zone, which is why the resizer "disappeared" only when the head was large.

   0.5 + 0.5/sqrt(2) = 0.85355 is where the rim crosses the 45 degree line, so
   this sits on the circle at every size, always over a hoverable surface. */
#studio-head .sh-grip {
  position: absolute;
  left: 85.355%;
  top: 85.355%;
  transform: translate(-50%, -50%);
  width: max(22px, 6.5%);
  aspect-ratio: 1;
  border-radius: 50%;
  background: #0366d6;
  border: 3px solid #fff;
  box-shadow: 0 2px 8px rgba(10, 20, 35, 0.4);
  cursor: nwse-resize;
  /* Resting at a low opacity rather than at zero: a control you can only find
     by hovering the thing it is attached to is a control most people never
     find. It is forced to 0 during a take by the .rec rule below. */
  opacity: 0.38;
  transition: opacity 0.15s ease;
  touch-action: none;
}
#studio-head:hover .sh-grip,
#studio-head.resizing .sh-grip {
  opacity: 1;
}
/* Never show the grip in a take, however the mouse happens to be sitting. */
body.studio.rec #studio-head .sh-grip {
  opacity: 0 !important;
}

/* ---- the drawn cursor -------------------------------------------------
   Lives on <body>, not inside #app-container, so it is never clipped by the
   frame's overflow:hidden and it appears in a screen-capture take too. Every
   size is a 1080-reference token like the rest of the frame, and
   compositor.js reads these elements back rather than carrying its own idea
   of what a cursor looks like. */
#studio-cursor {
  display: none;
}
body.studio #studio-cursor {
  display: block;
  position: fixed;
  left: 0;
  top: 0;
  z-index: 90;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s ease;
}
body.studio #studio-cursor.live {
  opacity: 1;
}
body.studio #studio-cursor i {
  --sc-scale: 1;
  position: absolute;
  display: block;
  border-radius: 50%;
  border-style: solid;
  border-color: transparent;
  border-width: 0;
  background: transparent;
  transform: translate(-50%, -50%) scale(var(--sc-scale));
  transition:
    transform 0.12s cubic-bezier(0.2, 0.9, 0.3, 1.4),
    background-color 0.12s ease,
    border-color 0.12s ease;
}
body.studio #studio-cursor .sc-ring {
  width: calc(var(--st-cursor-ring) * 1px * var(--studio-k));
  height: calc(var(--st-cursor-ring) * 1px * var(--studio-k));
  border-width: calc(3px * var(--studio-k));
  border-color: #0366d6;
  background: rgba(3, 102, 214, 0.1);
}
/* A precise hotspot inside a legible halo: the ring is what reads on a phone,
   the dot is what tells you exactly which pin is about to be clicked. */
body.studio #studio-cursor .sc-dot {
  width: calc(var(--st-cursor-dot) * 1px * var(--studio-k));
  height: calc(var(--st-cursor-dot) * 1px * var(--studio-k));
  background: #0366d6;
}
body.studio #studio-cursor .sc-pulse {
  width: calc(var(--st-cursor-ring) * 1px * var(--studio-k));
  height: calc(var(--st-cursor-ring) * 1px * var(--studio-k));
  border-width: calc(2px * var(--studio-k));
  border-color: #0366d6;
  opacity: 0;
}
body.studio #studio-cursor .sc-pulse.go {
  animation: sc-pulse 0.45s ease-out;
}
@keyframes sc-pulse {
  from {
    opacity: 0.55;
    transform: translate(-50%, -50%) scale(0.7);
  }
  to {
    opacity: 0;
    transform: translate(-50%, -50%) scale(2.6);
  }
}

/* Mode comes from the CSS `cursor` the app already declares — see cursor.js.
   Colour carries the meaning, size carries the emphasis. */
body.studio #studio-cursor[data-mode="point"] .sc-ring {
  --sc-scale: 0.78;
}
body.studio #studio-cursor[data-mode="grabbing"] .sc-ring {
  --sc-scale: 1.22;
  background: rgba(3, 102, 214, 0.26);
}
body.studio #studio-cursor[data-mode="draw"] .sc-ring {
  border-color: #6d3fc0;
  background: rgba(109, 63, 192, 0.13);
}
body.studio #studio-cursor[data-mode="draw"] .sc-dot,
body.studio #studio-cursor[data-mode="draw"] .sc-pulse {
  background-color: #6d3fc0;
  border-color: #6d3fc0;
}
body.studio #studio-cursor[data-mode="clone"] .sc-ring {
  border-color: #1a7f37;
  background: rgba(26, 127, 55, 0.13);
}
body.studio #studio-cursor[data-mode="clone"] .sc-dot,
body.studio #studio-cursor[data-mode="clone"] .sc-pulse {
  background-color: #1a7f37;
  border-color: #1a7f37;
}
body.studio #studio-cursor[data-mode="blocked"] .sc-ring {
  border-color: #cf222e;
  background: rgba(207, 34, 46, 0.13);
}
/* Press grows both, so a click is unmistakable at phone size. */
body.studio #studio-cursor.down .sc-ring {
  --sc-scale: 1.45;
  background: rgba(3, 102, 214, 0.32);
}
body.studio #studio-cursor.down .sc-dot {
  --sc-scale: 1.6;
}

/* During a take the drawn cursor REPLACES the system one inside the frame,
   so a screen-capture take does not show two pointers. The rail keeps its
   real cursor — you still have to be able to hit stop. */
body.studio.rec #app-container,
body.studio.rec #app-container * {
  cursor: none !important;
}

/* ---- 3-2-1, shown inside the frame BEFORE the recorder starts --------- */
#studio-count {
  position: absolute;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 190px;
  font-weight: 800;
  color: #0b1b2b;
  background: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(2px);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

/* =========================================================================
   #studio-rail — operator chrome. OUTSIDE the crop box, never recorded.
   ========================================================================= */
#studio-rail {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 300px;
  z-index: 300;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  overflow-y: auto;
  background: #0e141b;
  color: #c9d6e2;
  border-left: 1px solid #1e2a37;
  font:
    13px/1.45 -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    sans-serif;
}
/* If the frame is wide enough to collide with the rail, the rail floats over
   it translucently rather than shrinking the frame below 1080. */
@media (max-width: 1500px) {
  #studio-rail {
    background: rgba(14, 20, 27, 0.94);
    backdrop-filter: blur(6px);
  }
}
#studio-rail h4 {
  font-size: 10px;
  letter-spacing: 0.2em;
  color: #64798e;
  font-weight: 600;
  margin-top: 6px;
}
#studio-rail label {
  display: block;
  font-size: 11px;
  color: #8ea3b8;
  margin-bottom: 3px;
}
#studio-rail select,
#studio-rail button {
  width: 100%;
  font: inherit;
  border-radius: 7px;
  border: 1px solid #24333f;
  background: #16202b;
  color: #dbe6f0;
  padding: 7px 9px;
  cursor: pointer;
}
#studio-rail select:hover,
#studio-rail button:hover {
  border-color: #3a5670;
}
#studio-rail .sr-check {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: #a9bccf;
  cursor: pointer;
}
#studio-rail .sr-check input {
  width: 14px;
  height: 14px;
  accent-color: #0366d6;
  cursor: pointer;
}
#sr-record {
  padding: 13px;
  font-size: 15px;
  font-weight: 700;
  background: #d0202f;
  border-color: #ef3a4a;
  color: #fff;
}
#sr-record:hover {
  background: #e8263a;
}
body.studio.rec #sr-record {
  background: #1c2733;
  border-color: #ff2d55;
  color: #ff8095;
}
#sr-timer {
  font:
    700 30px/1 ui-monospace,
    "SF Mono",
    Menlo,
    monospace;
  color: #ff6b81;
  text-align: center;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}
#sr-res {
  font:
    11px/1.4 ui-monospace,
    Menlo,
    monospace;
  padding: 8px 9px;
  border-radius: 7px;
  background: #101a24;
  border: 1px solid #1e2a37;
  color: #8ea3b8;
}
#sr-res b {
  color: #e6eef6;
}
#sr-res.good {
  border-color: #1a5e37;
  color: #7fd6a2;
}
#sr-res.warn {
  border-color: #6b5312;
  color: #e4c063;
}
#sr-status {
  font-size: 11px;
  color: #7d93a8;
  min-height: 30px;
}
#sr-status.err {
  color: #ff8095;
}
#sr-keys {
  margin-top: auto;
  font-size: 11px;
  color: #64798e;
  line-height: 1.9;
  border-top: 1px solid #1e2a37;
  padding-top: 10px;
}
#sr-keys kbd {
  display: inline-block;
  min-width: 20px;
  text-align: center;
  padding: 1px 5px;
  border-radius: 4px;
  background: #1b2733;
  border: 1px solid #2c3d4d;
  color: #cfe0ee;
  font:
    600 11px ui-monospace,
    Menlo,
    monospace;
}
#sr-exit {
  margin-top: 2px;
  color: #9fb3c8;
  border-style: dashed;
}
#sr-exit:hover:not(:disabled) {
  color: #dbe6f0;
  border-style: solid;
}
#sr-exit:disabled {
  opacity: 0.5;
  cursor: default;
}

/* Hide the whole rail for a clean look-at-the-frame pass. */
body.studio.rail-hidden #studio-rail {
  display: none;
}

/* =========================================================================
   Field manual as a bottom sheet
   -------------------------------------------------------------------------
   The wiki overlay is position:fixed and full-viewport, which in a 9:16 frame
   would swallow the entire take. Here it is pinned to the frame's own rect
   (hence --studio-x/y/w/h) and rises from the bottom over ~62% of it, so the
   board stays visible above it while you read.
   ========================================================================= */
body.studio #wiki-overlay {
  inset: auto;
  left: var(--studio-x, 0px);
  top: var(--studio-y, 0px);
  width: var(--studio-w, 1080px);
  height: var(--studio-h, 1920px);
  align-items: flex-end;
}
body.studio .wiki-scrim {
  background: rgba(16, 24, 34, 0.3);
}
body.studio .wiki-panel {
  width: 100%;
  height: 62%;
  border-radius: 18px 18px 0 0;
  animation: studio-sheet-up 0.2s ease-out;
}
@keyframes studio-sheet-up {
  from {
    transform: translateY(14%);
    opacity: 0.4;
  }
}
/* A grab handle, so the sheet reads as a sheet on camera. */
body.studio .wiki-head {
  position: relative;
  padding-top: 20px;
}
body.studio .wiki-head::before {
  content: "";
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  width: 46px;
  height: 5px;
  border-radius: 3px;
  background: #cfd8e2;
}
body.studio .wiki-nav {
  flex: 0 0 220px;
}
body.studio .wiki-content {
  font-size: 16px;
}

/* Dialogs are position:fixed overlays; keep them centred on the FRAME rather
   than on the (much wider) viewport, or they land half under the rail. */
body.studio .dialog-overlay {
  left: var(--studio-x, 0px);
  top: var(--studio-y, 0px);
  width: var(--studio-w, 1080px);
  height: var(--studio-h, 1920px);
  right: auto;
  bottom: auto;
}

/* =========================================================================
   Rail restore tab
   -------------------------------------------------------------------------
   Sits on the right edge of the VIEWPORT, outside the frame's bounding box,
   so Region Capture never sees it. Visible only while the rail is hidden.
   ========================================================================= */
#studio-rail-tab {
  position: fixed;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  z-index: 320;
  display: none;
  align-items: center;
  padding: 16px 8px 16px 10px;
  border: 1px solid #24333f;
  border-right: 0;
  border-radius: 10px 0 0 10px;
  background: #0e141b;
  box-shadow: -3px 0 14px rgba(0, 0, 0, 0.35);
  cursor: grab;
  user-select: none;
  touch-action: none;
  transition:
    background 0.12s ease,
    box-shadow 0.12s ease;
}
body.studio.rail-hidden #studio-rail-tab {
  display: flex;
}
#studio-rail-tab:hover {
  background: #16202b;
  box-shadow: -4px 0 18px rgba(0, 0, 0, 0.5);
}
#studio-rail-tab.pulling {
  cursor: grabbing;
}
#studio-rail-tab span {
  writing-mode: vertical-rl;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.22em;
  color: #8ea3b8;
  pointer-events: none;
}

/* =========================================================================
   #studio-script — the script panel. LEFT of the frame, never recorded.
   -------------------------------------------------------------------------
   Mirror image of #studio-rail: position:fixed against the viewport edge,
   entirely outside #app-container's bounding box, so Region Capture crops
   it away and the native compositor never knows it exists. studio.js
   subtracts its width before it centres the 9:16 box.
   ========================================================================= */
#studio-script {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: 460px;
  z-index: 300;
  display: flex;
  flex-direction: column;
  background: #0e141b;
  border-right: 1px solid #1e2a37;
  color: #f2f6fa;

  /* The reading face. Deliberately NOT the app's UI stack: this is the one
     surface you read at a glance, mid-sentence, with your eyes mostly
     somewhere else. system-ui resolves to SF Pro Text on this machine and
     to Segoe UI Variable on Windows — both have the tall x-height and open
     apertures that survive a fast glance. The serif toggle swaps in the
     screen-serifs that ship with macOS, in descending order of quality. */
  --ss-fs: 20px;
  --ss-sans: system-ui, -apple-system, "Segoe UI Variable Text", "Segoe UI",
    Inter, Roboto, "Helvetica Neue", sans-serif;
  --ss-serif: "Iowan Old Style", "Charter", "Palatino", "Georgia",
    "Source Serif 4", serif;
  font: 13px/1.45 var(--ss-sans);
}
body.studio.script-hidden #studio-script {
  display: none;
}
/* Too narrow a display for both the panel and a usable frame: the panel
   stops claiming width and floats over the frame instead. ⇧S still takes
   it away entirely when you need to see the board underneath. */
#studio-script.yielding {
  background: rgba(14, 20, 27, 0.93);
  backdrop-filter: blur(6px);
  box-shadow: 6px 0 26px rgba(0, 0, 0, 0.5);
}

/* ---- header ----------------------------------------------------------- */
#studio-script .ss-head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 12px 12px 8px;
}
#studio-script .ss-title {
  flex: 1;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: #64798e;
}

/* ---- toolbars --------------------------------------------------------- */
#studio-script .ss-bar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 12px 8px;
  flex-wrap: wrap;
}
#studio-script .ss-btn {
  min-width: 30px;
  height: 28px;
  padding: 0 8px;
  font: 13px/1 var(--ss-sans);
  color: #c9d6e2;
  background: #16202b;
  border: 1px solid #24333f;
  border-radius: 7px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
#studio-script .ss-btn:hover {
  border-color: #3a5670;
  color: #f2f6fa;
}
#studio-script .ss-btn.on {
  background: #0366d6;
  border-color: #3d8ae5;
  color: #fff;
}
#studio-script .ss-b {
  font-weight: 800;
}
#studio-script .ss-i {
  font-style: italic;
  font-family: var(--ss-serif);
}
#studio-script .ss-u {
  text-decoration: underline;
}
#studio-script .ss-mark {
  color: #ffd60a;
}
#studio-script .ss-dl {
  min-width: 26px;
  height: 24px;
  padding: 0 7px;
}
#studio-script .ss-wide {
  flex: 1;
  font-weight: 600;
}
#studio-script #ss-prompt.on {
  background: #1d7a3c;
  border-color: #2ea355;
}
#studio-script .ss-sep {
  width: 1px;
  height: 18px;
  margin: 0 3px;
  background: #24333f;
}

/* ---- the page ---------------------------------------------------------
   White on near-black, set at a generous measure and leading. 1.62 is the
   ratio that keeps a line findable when your eyes come back to the panel
   after four seconds of looking at a wire. */
#studio-script #ss-editor {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 18px 45vh;
  outline: none;
  font-family: var(--ss-sans);
  font-size: var(--ss-fs);
  line-height: 1.62;
  color: #ffffff;
  -webkit-font-smoothing: antialiased;
  letter-spacing: 0.002em;
  caret-color: #4a9bff;
  scroll-behavior: smooth;
}
/* The bottom padding above is deliberate: it lets the LAST line of the
   script still scroll up to the read line instead of sticking to the floor
   of the panel, which is where you would otherwise be reading it from. */
#studio-script.serif #ss-editor {
  font-family: var(--ss-serif);
  line-height: 1.58;
}
#studio-script #ss-editor::-webkit-scrollbar {
  width: 8px;
}
#studio-script #ss-editor::-webkit-scrollbar-thumb {
  background: #24333f;
  border-radius: 4px;
}
#studio-script #ss-editor::-webkit-scrollbar-track {
  background: transparent;
}

#studio-script #ss-editor > * {
  margin: 0 0 0.62em;
}
#studio-script #ss-editor h2 {
  font-size: 0.72em;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #6fd3ff;
  margin: 1.4em 0 0.5em;
  font-family: var(--ss-sans);
}
#studio-script #ss-editor > *:first-child {
  margin-top: 0;
}
#studio-script #ss-editor blockquote {
  border-left: 3px solid #3a5670;
  padding-left: 0.7em;
  color: #9fb3c6;
  font-style: italic;
}
#studio-script #ss-editor ul,
#studio-script #ss-editor ol {
  padding-left: 1.15em;
}
#studio-script #ss-editor li {
  margin-bottom: 0.28em;
}
#studio-script #ss-editor b,
#studio-script #ss-editor strong {
  color: #ffffff;
  font-weight: 700;
}
/* execCommand paints the highlight as an inline background; force the text
   on top of it dark, or yellow-on-white is unreadable. */
#studio-script #ss-editor [style*="rgb(255, 214, 10)"] {
  color: #14202c;
  border-radius: 3px;
  padding: 0 2px;
}

/* ---- prompt mode ------------------------------------------------------
   Everything that is not the current block drops to a third of its weight.
   The current block gets a rule down its left edge — the same cue as a
   finger on the page. */
#studio-script #ss-editor > .cur {
  position: relative;
}
#studio-script #ss-editor > .cur::before {
  content: "";
  position: absolute;
  left: -12px;
  top: 0.14em;
  bottom: 0.14em;
  width: 3px;
  border-radius: 2px;
  background: #6fd3ff;
}
#studio-script.prompting #ss-editor > * {
  opacity: 0.3;
  transition: opacity 0.16s linear;
}
#studio-script.prompting #ss-editor > .cur {
  opacity: 1;
}
#studio-script.prompting #ss-editor {
  font-size: calc(var(--ss-fs) * 1.15);
  cursor: pointer;
}

/* ---- footer ----------------------------------------------------------- */
#studio-script .ss-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 12px;
  border-top: 1px solid #1e2a37;
  font-size: 11px;
  color: #64798e;
  font-variant-numeric: tabular-nums;
}
#studio-script .ss-spacer {
  flex: 1;
}
#studio-script .ss-saved.ok {
  color: #4aa96c;
}

/* ---- resize grip ------------------------------------------------------ */
#studio-script .ss-grip {
  position: absolute;
  top: 0;
  right: -3px;
  bottom: 0;
  width: 7px;
  cursor: col-resize;
  touch-action: none;
  z-index: 1;
}
#studio-script .ss-grip:hover,
#studio-script.dragging .ss-grip {
  background: rgba(3, 102, 214, 0.55);
}
#studio-script.dragging #ss-editor {
  pointer-events: none;
}

/* ---- restore tab ------------------------------------------------------
   Left edge of the VIEWPORT, outside the frame's box, same contract as the
   rail's tab on the right. */
#studio-script-tab {
  position: fixed;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  z-index: 320;
  display: none;
  align-items: center;
  padding: 16px 10px 16px 8px;
  border: 1px solid #24333f;
  border-left: 0;
  border-radius: 0 10px 10px 0;
  background: #0e141b;
  box-shadow: 3px 0 14px rgba(0, 0, 0, 0.35);
  cursor: pointer;
  user-select: none;
}
body.studio.script-hidden #studio-script-tab {
  display: flex;
}
#studio-script-tab:hover {
  background: #16202b;
}
#studio-script-tab span {
  writing-mode: vertical-rl;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.22em;
  color: #8ea3b8;
  pointer-events: none;
}
