/* studio.css — Creator Studio (the Blockly + Monaco game editor inside the Account app).

   Loaded AFTER account.css and only ever ADDS to it: every colour, font, radius and shadow here
   comes from the account.css design tokens (--blue / --grad-blue / --grad-panel / --panel-1|2 /
   --fg / --muted / --green / --red / --f-ui / --f-display / --f-mono / --shadow-btn) and its
   rgba(43,140,255,0.NN) border idiom. Nothing new is invented palette-wise.

   Structure (matching #tab-studio in index.html):
     shell breakout ▸ first run ▸ toolbar ▸ studio primitives ▸ view tabs ▸ body/panes/divider
     ▸ blocks pane ▸ sprites manager ▸ code pane ▸ validation bar ▸ run overlay
     ▸ history drawer ▸ preview bar ▸ modals ▸ responsive ▸ motion + focus */

/* ============================ shell breakout ============================
   The Studio is a focused workspace: it fills the viewport under the app bar and scrolls INSIDE its
   panes rather than scrolling the page. Driven purely by :has() so no JS class is needed on <body>.
   (The app bar and section tabs are full width for every tab — see account.css — so only the height
   behaviour and the tighter padding are Studio-specific.) */
.workspace:has(> #tab-studio:not([hidden])) {
  padding:16px 18px 0;
  display:flex; flex-direction:column; min-height:0;
}
/* Panels are capped to a readable column by default; a workspace wants the whole width. */
.tab-panel.studio { max-width:none; margin:0; }
/* …but the first-run and template screens are ordinary pages, not a workspace, so they sit in the
   same column as Creator Hub. Restoring the standard workspace padding while the editor is hidden
   means the two line up EXACTLY at every width, with no per-breakpoint fudge factor to keep in
   sync — the tighter 18px gutter above exists for the editor alone. */
.workspace:has(#tab-studio:not([hidden]) #studio-editor[hidden]) { padding:26px 22px 0; }
.workspace:has(> #tab-studio:not([hidden])) .tabs { margin-bottom:14px; }
/* the page footer would force the page to scroll; the Studio owns the full height instead */
main:has(#tab-studio:not([hidden])) .legal-footer { display:none; }

.tab-panel.studio { position:relative; }               /* run overlay + drawer anchor here */
.tab-panel.studio:not([hidden]) {
  display:flex; flex-direction:column; flex:1; min-height:0;
  padding-bottom:16px;
}

/* ============================ first run / templates ============================ */
/* Same column as every other .tab-panel, so "Creator Studio" starts at the same x as "Creator Hub". */
.studio-firstrun { max-width:1180px; margin:0 auto; width:100%; }
.studio-firstrun[hidden] { display:none; }
.studio-crumbs { display:flex; align-items:center; gap:9px; font-size:13px; color:var(--muted); margin-bottom:18px; }
/* Keep each crumb on one line — without this the flex items shrink and "Creator Hub" wraps to two. */
.studio-crumbs > * { flex:none; white-space:nowrap; }
.linkbtn {
  background:none; border:none; padding:4px 2px; margin:0; cursor:pointer;
  font-family:var(--f-ui); font-size:13px; font-weight:600; color:var(--blue);
}
.linkbtn:hover { text-decoration:underline; }
/* Carries .page-head too, so the title/sub spacing is Creator Hub's, not a second variant. */
.studio-firstrun-head { margin-bottom:24px; }

.starter-grid { display:grid; grid-template-columns:1fr 1fr; gap:18px; align-items:stretch; }
.starter-grid-3 { grid-template-columns:repeat(auto-fill,minmax(260px,1fr)); }
.starter-card {
  position:relative; display:flex; flex-direction:column; gap:12px; align-items:flex-start;
  padding:22px; border-radius:20px; border:1px solid rgba(43,140,255,0.22);
  background:var(--grad-panel); box-shadow:0 12px 40px rgba(0,0,0,0.35);
}
.starter-card > button { margin-top:auto; }
/* A template's cover art, full-bleed across the top of its card. Square and un-cropped on purpose:
   this is the exact picture the new game is created with, so the picker shows the whole of it. */
.starter-shot {
  align-self:stretch; width:calc(100% + 44px); margin:-22px -22px 0; display:block;
  aspect-ratio:1/1; object-fit:cover; border-radius:20px 20px 0 0;
  background:rgba(43,140,255,0.06); image-rendering:pixelated;
}
.starter-shot[hidden] { display:none; }
.starter-icon {
  width:44px; height:44px; border-radius:13px; display:flex; align-items:center; justify-content:center;
  font-size:22px; background:rgba(43,140,255,0.1); border:1px solid rgba(43,140,255,0.25);
}
/* A template card carries its cover instead of an emoji, and only falls back to one if that cover
   fails to load — so the badge has to actually disappear when hidden (display:flex ignores [hidden]). */
.starter-icon[hidden] { display:none; }
.starter-title { font-family:var(--f-display); font-weight:700; font-size:19px; margin:0 0 6px; }
.starter-desc { font-size:13.5px; color:var(--muted); line-height:1.5; margin:0; }

/* "Continue working on" — the Creator Hub's own cards, made clickable end to end. */
.studio-recent { margin-top:34px; }
.studio-recent[hidden] { display:none; }
.studio-recent .section-title { margin-bottom:14px; }
.studio-recent-card {
  position:relative; display:block; width:100%; padding:0; text-align:left; overflow:hidden;
  font-family:var(--f-ui); transition:border-color .15s, transform .15s;
}
.studio-recent-card:hover { border-color:rgba(43,140,255,0.55); transform:translateY(-2px); }
/* The card is a div now (the bin can't live inside a button), so the opening half is its own
   button filling the card — the whole thing stays clickable and keyboard-reachable as before. */
.studio-recent-open { display:block; width:100%; padding:0; margin:0; border:0; background:none;
  color:inherit; font:inherit; text-align:left; cursor:pointer; }
.studio-recent-open:focus-visible { outline:2px solid var(--blue); outline-offset:-2px; border-radius:inherit; }
/* Sits over the cover, top right. Always there rather than hover-only: it has to be reachable on a
   touchscreen, where there is no hover to reveal it. */
.studio-recent-del { position:absolute; top:10px; right:10px; z-index:1;
  background:rgba(8,8,24,0.72); backdrop-filter:blur(6px); }
.studio-recent-card .game-card-foot { display:flex; align-items:center; justify-content:space-between; gap:10px; }

/* ============================ studio primitives ============================ */
.iconbtn {
  display:inline-flex; align-items:center; justify-content:center; flex:none;
  width:36px; height:36px; padding:0; border-radius:10px;
  background:transparent; border:1px solid rgba(43,140,255,0.22); color:var(--muted-2);
  font-family:var(--f-ui); font-size:15px; line-height:1; cursor:pointer;
  transition:border-color .15s, color .15s, background .15s;
}
.iconbtn:hover:not(:disabled) { color:var(--blue); border-color:rgba(43,140,255,0.6); background:rgba(43,140,255,0.08); }
.iconbtn:disabled { opacity:.35; cursor:not-allowed; }
.studio-toolbar-spacer { flex:1 1 auto; min-width:0; }
.studio-toolbar-rule { flex:none; width:1px; height:22px; background:rgba(43,140,255,0.2); }
.primary.sm { padding:8px 14px; border-radius:10px; font-size:13px; }
.pill.is-running { color:var(--green); }
.pill.is-running::before {
  content:""; width:7px; height:7px; border-radius:50%; background:var(--green);
  box-shadow:0 0 8px var(--green); animation:wbpulsedot 1.4s ease-in-out infinite;
}

/* ============================ toolbar ============================
   One row: back · name + save status · game code chip · spacer · actions.
   Hierarchy is load-bearing: Run = green primary, Save = outline, everything else ghost. */
.studio-toolbar {
  display:flex; align-items:center; gap:10px; flex:none; flex-wrap:nowrap;
  padding:10px 14px; margin-bottom:12px; border-radius:16px;
  border:1px solid rgba(43,140,255,0.2); background:var(--grad-panel);
  box-shadow:0 10px 32px rgba(0,0,0,0.32);
}
/* Nowrap, so the toolbar never breaks into three ragged rows when the window narrows. Below the
   floor the whole editor scrolls sideways as one piece (see the small-screens section) — the
   toolbar goes with it rather than reflowing into something worse. The buttons hold their size so
   nothing gets crushed; only the spacer gives. */
.studio-toolbar > :not(.studio-toolbar-spacer) { flex:none; }
.studio-back { font-size:17px; }

.studio-identity { display:flex; flex-direction:column; gap:2px; min-width:0; }
.studio-name {
  width:auto; min-width:0; max-width:280px; padding:5px 9px; border-radius:9px;
  background:transparent; border:1px solid transparent;
  font-family:var(--f-display); font-weight:700; font-size:17px; color:var(--fg);
}
.studio-name:hover { border-color:rgba(43,140,255,0.25); background:rgba(5,3,15,0.4); }
.studio-name:focus { border-color:rgba(43,140,255,0.7); background:rgba(5,3,15,0.7); box-shadow:0 0 0 3px rgba(43,140,255,0.15); }
.studio-savestate { display:flex; align-items:center; gap:7px; margin:0; padding-left:9px; font-size:12px; color:var(--muted); }
/* The state line is the retry affordance now that the Save button is gone, so its text is a real
   button — which means undoing everything a button looks like by default. */
.studio-savestate .txt {
  appearance:none; background:none; border:none; padding:0; font:inherit; color:inherit;
  text-align:left; cursor:default;
}
.studio-savestate.is-failed .txt,
.studio-savestate.is-signedout .txt { cursor:pointer; text-decoration:underline; }
.studio-savestate .dot { flex:none; width:7px; height:7px; border-radius:50%; background:var(--green); box-shadow:0 0 7px rgba(70,224,138,0.7); }
.studio-savestate.is-dirty .dot { background:var(--muted); box-shadow:none; }
.studio-savestate.is-saving .dot { background:var(--blue); box-shadow:0 0 7px rgba(43,140,255,0.7); animation:wbpulsedot 1s ease-in-out infinite; }
/* `is-failed`/`is-signedout` are what renderSaveState actually emits — an earlier draft styled
   `is-error`, which nothing sets, so a failed save wore the same green dot as a healthy one. */
.studio-savestate.is-failed, .studio-savestate.is-signedout { color:var(--red); }
.studio-savestate.is-failed .dot,
.studio-savestate.is-signedout .dot { background:var(--red); box-shadow:0 0 7px rgba(255,93,108,0.7); }
/* A background version was kept. Deliberately understated — it appears, holds, and fades. */
.studio-autoversion {
  font-size:11px; font-weight:600; letter-spacing:.2px; color:var(--muted-2);
  padding:1px 7px; border-radius:999px;
  background:rgba(43,140,255,0.1); border:1px solid rgba(43,140,255,0.28);
  animation:studioBackedUp 4s ease-out forwards;
}
.studio-autoversion[hidden] { display:none; }
@keyframes studioBackedUp {
  0% { opacity:0; transform:translateY(2px); }
  12%, 62% { opacity:1; transform:none; }
  100% { opacity:0; transform:none; }
}

/* The label above the toolbar's status chip — "Game code", or "Not playable yet" while there is no
   code worth handing out. The chip itself is styled further down (.studio-statuschip). */
.studio-codechip { display:flex; flex-direction:column; gap:3px; flex:none; }
.studio-codelabel { font-size:10.5px; font-weight:700; letter-spacing:.4px; text-transform:uppercase; color:var(--muted); padding-left:2px; }

/* Run — the one green button on the page. Green analogue of account.css's .primary recipe. */
.studio-run {
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding:13px 24px; border-radius:12px; border:1px solid rgba(70,224,138,0.6);
  background:linear-gradient(135deg,#5ceb9c,#1fb968); color:#04210f;
  font-family:var(--f-ui); font-weight:800; font-size:15px; cursor:pointer;
  box-shadow:0 6px 18px rgba(31,185,104,0.35), inset 0 1px 0 rgba(255,255,255,0.28);
  transition:filter .15s, transform .05s;
}
.studio-run:hover:not(:disabled) { filter:brightness(1.07); }
.studio-run:active:not(:disabled) { transform:translateY(1px); }
.studio-run:disabled {
  background:rgba(138,147,173,0.12); border-color:transparent; color:#5a627a;
  box-shadow:none; cursor:not-allowed; filter:none;
}
/* Save — outline/secondary, deliberately quieter than Run but louder than the ghosts. */
.ghostbtn.studio-save { padding:11px 18px; border-color:rgba(43,140,255,0.5); color:var(--blue); font-size:14px; }
.ghostbtn.studio-save:hover { background:rgba(43,140,255,0.1); border-color:rgba(43,140,255,0.8); }

/* ============================ view tabs (narrow screens only) ============================ */
.studio-viewtabs {
  display:none; gap:8px; flex:none; padding:5px; margin-bottom:10px; border-radius:13px;
  background:rgba(12,18,48,0.5); border:1px solid rgba(43,140,255,0.16);
}
.studio-viewtab {
  flex:1; padding:10px 14px; border-radius:9px; background:transparent; border:none;
  color:var(--muted); font-family:var(--f-ui); font-size:13.5px; font-weight:600; cursor:pointer;
}
.studio-viewtab:hover { color:var(--fg); }
.studio-viewtab.is-active { background:rgba(7,104,255,0.18); color:var(--blue); }

/* ============================ editor body / panes / divider ============================ */
.studio-editor { display:flex; flex-direction:column; flex:1; min-height:0; }
.studio-editor[hidden] { display:none; }
.studio-body { display:flex; flex:1; min-height:0; min-width:0; }
.studio-pane {
  display:flex; flex-direction:column; min-height:0; min-width:0; overflow:hidden;
  border-radius:18px; border:1px solid rgba(43,140,255,0.2); background:var(--grad-panel);
  box-shadow:0 12px 40px rgba(0,0,0,0.35);
}
/* An author `display` always beats the UA's [hidden] rule, so a class that sets one must restate it
   — without this, hiding the blocks pane at level 2 would do nothing at all. (Same trap as
   .field[hidden] in account.css, which once exposed the admin-only game-code field to everyone.) */
.studio-pane[hidden] { display:none; }

/* Toolbar buttons share one height — a FIXED one, not a minimum. A colour emoji carries a taller
   line box than the text beside it, so a min-height still let one button grow past its neighbours;
   the clock is an SVG now, and the fixed height means no future glyph can do it again. */
.studio-toolbar .ghostbtn, .studio-toolbar .studio-run {
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  height:38px; padding-top:0; padding-bottom:0; line-height:1;
}
.btnicon { flex:none; }

/* ---- the toolbar sheds its labels before it sheds the panel ----
   The row is nowrap and every button is fixed-size, so its width is simply the sum of what is in
   it — and that sum outgrew the panel. At its longest it wanted about 1390px inside a panel whose
   floor is 1040, so on any ordinary laptop the buttons ran out past the rounded border. That was
   true before the Build Challenge button and it only became visible with it.
   Widening the floor would have been the wrong fix: it would put a horizontal scrollbar under a
   window that is perfectly big enough to work in. Instead the least important LABELS go, one band
   at a time, leaving the icon — each button keeps a title and an aria-label, so hiding the text
   costs a screen reader nothing and a mouse one hover. Run keeps its words at every width; it is
   the primary action and reading "▶" alone is a guess. */
.studio-toolbar .lbl { display:inline; }
@media (max-width:1400px) {
  /* First to go: the two that are rarely pressed and whose icons are unambiguous. */
  #studio-save-version .lbl, #studio-history-open .lbl, #studio-details-open .lbl { display:none; }
}
@media (max-width:1160px) {
  /* Then the competition button — the trophy carries it, and it is not an everyday action. */
  #studio-enter-open .lbl { display:none; }
}
@media (max-width:1060px) {
  /* Last: mebo's name. His face is the most recognisable thing in the row, so this is the label
     that survives longest and still loses nothing when it goes. */
  #studio-help-open .lbl { display:none; }
}

/* ============================ small screens ============================
   Creator Studio has a FIXED minimum width rather than a fluid collapse. Two panes, a toolbar and a
   code surface have a size below which they stop being usable, and reflowing them into something
   narrower produces a worse answer than simply keeping the layout and letting the page scroll to
   it. 1040px is the floor: it is the width the toolbar needs on one row (its buttons are fixed-size
   and there are a lot of them), and the panes are comfortable there too. iPad landscape clears it;
   portrait scrolls sideways, which is a familiar gesture and costs nothing to learn.

   The scroll lives on the workspace, so the app bar and section tabs stay put and only the editor
   moves. The floor applies ONLY while the editor is open — the first-run and template screens are
   ordinary pages that stay responsive down to a phone, so scoping this to a visible #studio-editor
   keeps them out of it. */
.workspace:has(#tab-studio:not([hidden]) #studio-editor:not([hidden])) { overflow-x:auto; }
.tab-panel.studio:not([hidden]):has(#studio-editor:not([hidden])) { min-width:1040px; }

/* And the PAGE must not scroll vertically while the editor is open.
   Every box from body down is already `flex:1; min-height:0`, which is right — but body carried
   `min-height:100vh`, an "at least", so the panes' own minimum content pushed the document 115px
   past the window and the whole editor slid under the fold. Selecting a block near the bottom of
   the workspace then highlighted its lines in a part of Monaco that was off-screen: the feature
   worked and you could not see it work.
   `height` rather than `min-height` gives the flex chain a definite size to divide, so the panes
   shrink and scroll INSIDE themselves — which is what a two-pane editor is supposed to do, and what
   makes "click a block, see its code" true at any window size. Scoped to the open editor, so every
   ordinary page on the site keeps scrolling normally. The horizontal scroll above is unaffected. */
body.app:has(#tab-studio:not([hidden]) #studio-editor:not([hidden])) {
  height:100vh;
  overflow:hidden;
}

/* ---- new file / new folder ---- */
.studio-kinds { display:grid; grid-template-columns:repeat(2, 1fr); gap:8px; margin-bottom:14px; }
.studio-kind {
  display:flex; flex-direction:column; align-items:flex-start; gap:2px; cursor:pointer;
  padding:10px 12px; border-radius:11px; text-align:left;
  background:rgba(5,3,15,0.4); border:1px solid var(--line-soft); color:var(--muted);
  transition:border-color .12s ease, background .12s ease;
}
.studio-kind:hover { border-color:var(--line); background:rgba(43,140,255,0.07); }
.studio-kind.is-active {
  border-color:rgba(43,140,255,0.5); background:rgba(43,140,255,0.11); color:var(--fg);
}
.studio-kind-icon { display:flex; margin-bottom:2px; color:var(--muted-2); }
.studio-kind.is-active .studio-kind-icon { color:var(--blue); }
.studio-kind-name { font-size:13.5px; font-weight:600; color:var(--fg); }
.studio-kind-what { font-size:11.5px; line-height:1.35; color:var(--muted); }

/* The extension lives in the field, so the whole filename is visible as you type it. */
.studio-nameinput { display:flex; align-items:stretch; }
.studio-nameinput input { border-top-right-radius:0; border-bottom-right-radius:0; }
.studio-nameext {
  display:flex; align-items:center; flex:none; padding:0 12px; border-radius:0 11px 11px 0;
  border:1px solid rgba(43,140,255,0.3); border-left:none; background:rgba(43,140,255,0.09);
  font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size:13px;
  color:var(--blue);
}
.studio-nameext[hidden] { display:none; }

/* Download sits with the files rather than in the toolbar — it acts on them, and it is a rare
   thing to want next to Run, which is not. */
.studio-files-foot { flex:none; border-top:1px solid rgba(43,140,255,0.14); }
.studio-files-foot .studio-filetree-note { border-top:none; }
.studio-downloadlink {
  display:block; width:100%; padding:9px 12px; cursor:pointer; text-align:left;
  background:none; border:none; border-top:1px solid rgba(43,140,255,0.1);
  font-family:var(--f-ui); font-size:12px; color:var(--muted);
  transition:color .12s ease, background .12s ease;
}
.studio-downloadlink:hover { color:var(--blue); background:rgba(43,140,255,0.07); }

/* ---- level 2: open tabs, and the preview surface ---- */
/* flex-direction is load-bearing: the base tab stacks a name over its caption for level 1, and
   without resetting it here the close button sat UNDER the filename instead of beside it. */
.studio-editor.is-code .studio-file {
  display:inline-flex; flex-direction:row; align-items:center; gap:7px; cursor:pointer;
}
.studio-file-x {
  appearance:none; border:none; background:none; cursor:pointer; padding:0 2px; line-height:1;
  font-size:11px; color:var(--muted); border-radius:4px; opacity:0; transition:opacity .12s, color .12s;
}
.studio-file:hover .studio-file-x, .studio-file.is-active .studio-file-x { opacity:.7; }
.studio-file-x:hover { opacity:1; color:var(--red); background:rgba(239,68,68,0.12); }

/* A picture or a sound opens as itself. Showing a PNG as bytes would be a worse answer than
   showing the PNG. */
.studio-preview {
  flex:1; min-height:0; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:14px; padding:24px; background:rgba(5,3,15,0.8);
}
.studio-preview[hidden] { display:none; }
.studio-preview-stage {
  display:flex; align-items:center; justify-content:center; max-width:100%; max-height:70%;
  padding:18px; border-radius:14px; border:1px solid rgba(43,140,255,0.18);
  background:repeating-conic-gradient(rgba(255,255,255,0.045) 0% 25%, transparent 0% 50%) 50% / 18px 18px;
}
/* Pixel art must not be smoothed — a 16x16 sprite blown up should look like a 16x16 sprite. */
.studio-preview-stage img {
  max-width:min(420px, 60vw); max-height:46vh; image-rendering:pixelated;
}
.studio-preview-meta {
  margin:0; font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size:12px; color:var(--muted);
}
.studio-preview-none { margin:0; font-size:13px; color:var(--muted); }

/* ---- level 2: the file tree ---- */
 /* A starting width, not a fixed one — the divider overrides flex-grow to resize it. Using a
    flex-basis here (rather than 0 0 210px) is what lets that work. */
.studio-pane-files { flex:0.19 1 0; min-width:150px; }
.studio-filetree { display:flex; flex-direction:column; gap:2px; padding:10px; overflow-y:auto; flex:1; }
.studio-filetree-group {
  margin:10px 0 4px; padding:0 6px; font-size:10.5px; font-weight:700; letter-spacing:.4px;
  text-transform:uppercase; color:var(--muted);
}
.studio-filetree-item {
  display:flex; align-items:center; gap:8px; width:100%; padding:7px 9px; border-radius:8px;
  border:1px solid transparent; background:none; cursor:pointer; text-align:left;
  font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size:12.5px;
  color:var(--muted); transition:background .12s ease, color .12s ease;
}
.studio-filetree-item:hover { background:rgba(43,140,255,0.08); color:var(--fg); }
.studio-filetree-item.is-active {
  background:rgba(43,140,255,0.14); border-color:rgba(43,140,255,0.3); color:var(--fg);
}
/* Shipped with every game and not the creator's to edit — listed so they know it is there, but it
   does not pretend to be openable. */
.studio-filetree-item.is-provided { cursor:default; opacity:.55; }
.studio-filetree-item.is-provided:hover { background:none; color:var(--muted); }
/* Line glyphs, not emoji: they take the row's own colour, so an icon dims with a provided file and
   lifts with a selected one instead of shouting in full colour on every row. */
.studio-fileicon { flex:none; opacity:.75; }
.studio-filetree-item.is-active .studio-fileicon { opacity:1; color:var(--blue); }
.studio-filetree-folder .studio-fileicon { opacity:.6; }
/* Folders are folders: nested, indented by depth, and each one a place things can be dropped. */
.studio-filetree-folder {
  display:flex; align-items:center; gap:7px; padding:6px 9px; border-radius:8px; width:100%;
  border:1px dashed transparent; background:none; cursor:pointer; text-align:left;
  font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size:12.5px;
  color:var(--muted-2);
}
.studio-filetree-folder:hover { color:var(--fg); }
/* A real chevron rather than a ▾ glyph: at the size this needs to be, a text arrow rendered as a
   couple of grey pixels and was easy to miss entirely. */
.studio-filetree-twist {
  flex:none; color:var(--muted-2); transition:transform .12s ease;
}
.studio-filetree-folder:hover .studio-filetree-twist { color:var(--blue); }
.studio-filetree-folder.is-shut .studio-filetree-twist { transform:rotate(-90deg); }
@media (prefers-reduced-motion:reduce) { .studio-filetree-twist { transition:none; } }
.studio-filetree-folder, .studio-filetree-item { padding-left:calc(9px + var(--depth, 0) * 13px); }
.studio-filetree-folder.is-dropping {
  border-color:rgba(70,224,138,0.6); background:rgba(70,224,138,0.1); color:#7ee08a;
}
/* One + per folder, so where a new thing lands is answered by which one you press. Revealed on
   hover so the tree stays quiet when you are only reading it. */
.studio-filetree-label { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; }
.studio-filetree-plus {
  flex:none; display:inline-flex; align-items:center; justify-content:center;
  width:18px; height:18px; margin-left:auto; border-radius:5px; cursor:pointer;
  font-size:13px; line-height:1; color:var(--muted); opacity:0; transition:opacity .12s, color .12s;
}
.studio-filetree-folder:hover .studio-filetree-plus,
.studio-filetree-group:hover .studio-filetree-plus,
.studio-filetree-plus:focus-visible { opacity:1; }
.studio-filetree-plus:hover { color:var(--blue); background:rgba(43,140,255,0.14); }
.studio-filetree-group { display:flex; align-items:center; }
.studio-newfile-kinds { margin-bottom:12px; }

.studio-filetree-drophint {
  margin:6px 0 0; padding:0 9px; font-size:11px; line-height:1.4; color:var(--muted); opacity:.8;
}
.studio-filetree-note {
  flex:none; margin:0; padding:10px 12px; font-size:11.5px; line-height:1.45; color:var(--muted);
  border-top:1px solid rgba(43,140,255,0.14);
}
.studio-pane-blocks { flex:1.15 1 0; }
.studio-pane-code { flex:1 1 0; }
.studio-graduation[hidden] { display:none; }
.studio-pane-head {
  display:flex; align-items:center; gap:10px; flex:none; flex-wrap:wrap;
  padding:10px 14px; border-bottom:1px solid rgba(43,140,255,0.14);
}
.studio-pane-title { font-family:var(--f-display); font-weight:600; font-size:15px; color:var(--fg); }
.studio-pane-hint { font-size:12px; color:var(--muted); }
.studio-pane-tools { display:flex; align-items:center; gap:6px; margin-left:auto; }
.studio-pane-tools[hidden] { display:none; }
.studio-modeswitch { flex:none; gap:6px; }
.studio-modeswitch .seg-btn { flex:none; padding:8px 13px; font-size:13px; border-radius:10px; }
.studio-gradswitch { flex:none; gap:6px; }
.studio-gradswitch .seg-btn { flex:none; padding:6px 11px; font-size:12px; border-radius:9px; cursor:default; }
.seg-btn.is-locked { color:#5a627a; border-color:rgba(138,147,173,0.25); background:rgba(138,147,173,0.06); }

/* draggable divider: 6px of visible rail, a wider invisible hit area, a visible grip */
.studio-divider {
  position:relative; flex:none; width:6px; margin:0 5px; cursor:col-resize;
  display:flex; align-items:center; justify-content:center; border-radius:999px;
  background:transparent; transition:background .15s;
}
.studio-divider::before { content:""; position:absolute; top:0; bottom:0; left:-8px; right:-8px; }  /* hit area */
.studio-divider span {
  width:4px; height:52px; border-radius:999px; background:rgba(43,140,255,0.3);
  transition:background .15s, height .15s;
}
.studio-divider:hover span, .studio-divider.is-dragging span { background:var(--blue); height:76px; }
.studio-divider.is-dragging { background:rgba(43,140,255,0.08); }

/* ============================ blocks pane ============================ */
.studio-workspace {
  flex:1; min-height:0; width:100%; position:relative;
  background:
    radial-gradient(circle at center, rgba(43,140,255,0.14) 1px, transparent 1.2px) 0 0/22px 22px,
    linear-gradient(180deg, rgba(5,3,15,0.55), rgba(5,3,15,0.8));
}
.studio-workspace[hidden] { display:none; }
.studio-workspace.is-readonly { opacity:.55; filter:grayscale(.35); }
.studio-workspace-empty {
  position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:8px; pointer-events:none; color:var(--muted); font-size:14px; text-align:center; padding:20px;
}

/* Toolbox category swatches. The Blockly workspace itself is themed in JS — these are the
   swatch colours (design doc §7) exposed both as tokens and as a ready-made dot class. */
.studio-pane-blocks {
  --cat-game:#b794ff; --cat-sprites:#78b4ff; --cat-input:#4fd6c4; --cat-collisions:#fb8ba0;
  --cat-world:#7ee08a; --cat-sound:#f79bd6; --cat-logic:#fbbf24; --cat-loops:#fb923c;
  --cat-variables:#818cf8; --cat-numbers:#38bdf8;
}
.studio-cat-swatch {
  display:inline-block; flex:none; width:12px; height:12px; border-radius:4px;
  background:var(--cat, var(--blue)); box-shadow:0 0 8px color-mix(in srgb, var(--cat, var(--blue)) 60%, transparent);
}
.studio-cat-swatch[data-cat="game"]       { --cat:var(--cat-game); }
.studio-cat-swatch[data-cat="sprites"]    { --cat:var(--cat-sprites); }
.studio-cat-swatch[data-cat="input"]      { --cat:var(--cat-input); }
.studio-cat-swatch[data-cat="collisions"] { --cat:var(--cat-collisions); }
.studio-cat-swatch[data-cat="world"]      { --cat:var(--cat-world); }
.studio-cat-swatch[data-cat="sound"]      { --cat:var(--cat-sound); }
.studio-cat-swatch[data-cat="logic"]      { --cat:var(--cat-logic); }
.studio-cat-swatch[data-cat="loops"]      { --cat:var(--cat-loops); }
.studio-cat-swatch[data-cat="variables"]  { --cat:var(--cat-variables); }
.studio-cat-swatch[data-cat="numbers"]    { --cat:var(--cat-numbers); }

/* an invalid block: red ring + pulse (class applied to the block's SVG group by studio.js) */
@keyframes studio-invalid-pulse {
  0%,100% { filter:drop-shadow(0 0 0 rgba(255,93,108,0.55)); }
  50%     { filter:drop-shadow(0 0 9px rgba(255,93,108,0.95)); }
}
.studio-invalid-block { animation:studio-invalid-pulse 1.3s ease-in-out infinite; }
.studio-invalid-block .blocklyPath { stroke:var(--red); stroke-width:3px; }

/* ============================ assets manager ============================ */
.studio-assets { flex:1; min-height:0; overflow-y:auto; padding:18px; }
.studio-assets[hidden] { display:none; }
.studio-assets-title { font-family:var(--f-display); font-weight:600; font-size:16px; margin:0 0 6px; }
.studio-assets-help { font-size:13px; color:var(--muted); line-height:1.5; margin:0 0 22px; max-width:560px; }
.studio-assets-help strong { color:var(--fg); font-weight:600; }

/* One section per kind, separated by a rule so the three don't run together. */
.asset-section + .asset-section { margin-top:26px; padding-top:22px; border-top:1px solid rgba(43,140,255,0.16); }
.asset-section-title {
  display:flex; align-items:center; gap:8px;
  font-family:var(--f-display); font-weight:700; font-size:15px; margin:0 0 5px;
}
.asset-section-note { font-size:12.5px; color:var(--muted); line-height:1.5; margin:0 0 14px; max-width:560px; }
.asset-section-note strong { color:var(--fg); font-weight:600; }
/* Which files will be accepted — said before the picker opens, not after it's rejected. */
.asset-types { color:var(--muted-2); font-weight:600; }

/* A sound or a picture: one file, one name, one row. */
.asset-row {
  display:flex; align-items:center; gap:12px; padding:10px 12px; margin-bottom:8px;
  border-radius:13px; border:1px solid rgba(43,140,255,0.2); background:rgba(7,104,255,0.05);
}
.asset-row-icon {
  flex:none; width:38px; height:38px; border-radius:11px; display:flex; align-items:center;
  justify-content:center; font-size:18px;
  background:rgba(43,140,255,0.1); border:1px solid rgba(43,140,255,0.25);
}
.asset-row-thumb {
  flex:none; width:38px; height:38px; border-radius:11px; overflow:hidden;
  background:rgba(43,140,255,0.06); border:1px solid rgba(43,140,255,0.25);
}
.asset-row-thumb img { width:100%; height:100%; object-fit:contain; image-rendering:pixelated; }
.asset-row-id { display:flex; flex-direction:column; gap:2px; min-width:0; margin-right:auto; }
.asset-row-name { font-family:var(--f-display); font-weight:600; font-size:14px; color:var(--fg); }
.asset-row-file {
  font-family:var(--f-mono); font-size:10.5px; letter-spacing:.5px; color:var(--muted);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* What kinds of file this dialog will take, sitting just above the picker button. */
.studio-asset-types { font-size:12px; color:var(--muted-2); font-weight:600; margin:0 0 4px; }

.sprite-card {
  border-radius:16px; border:1px solid rgba(43,140,255,0.2); background:rgba(7,104,255,0.05);
  padding:14px 16px; margin-bottom:14px;
}
.sprite-card-head { display:flex; align-items:center; gap:10px; margin-bottom:12px; }
.sprite-name {
  width:auto; max-width:220px; padding:5px 9px; border-radius:9px; background:transparent;
  border:1px solid transparent; font-family:var(--f-display); font-weight:600; font-size:15px; color:var(--fg);
}
.sprite-name:hover { border-color:rgba(43,140,255,0.25); }
.sprite-count { font-size:12px; color:var(--muted); }
.sprite-card-actions { display:flex; align-items:center; gap:6px; margin-left:auto; }

.sprite-states { display:flex; gap:12px; overflow-x:auto; padding-bottom:6px; }
.sprite-state, .sprite-state-add {
  flex:none; width:96px; border-radius:13px; display:flex; flex-direction:column;
  align-items:center; gap:6px; padding:9px; text-align:center;
}
.sprite-state { border:1px solid rgba(43,140,255,0.22); background:rgba(5,3,15,0.6); }
/* The thumbnail IS the swap button — clicking a picture to change it is the guess a child makes
   first, so it should be the thing that works. A real <button>, hence the appearance reset. */
.sprite-state-thumb {
  width:100%; aspect-ratio:1/1; border-radius:9px; background-size:contain;
  background-position:center; background-repeat:no-repeat;
  background-color:rgba(43,140,255,0.06); image-rendering:pixelated;
  appearance:none; border:none; padding:0; position:relative; cursor:pointer; overflow:hidden;
}
.sprite-state-swap {
  position:absolute; inset:auto 0 0 0; padding:3px 0; font-size:10.5px; font-weight:700;
  font-family:var(--f-ui); color:#eaf2ff; background:rgba(43,140,255,0.85);
  opacity:0; transition:opacity .12s;
}
.sprite-state-thumb:hover .sprite-state-swap,
.sprite-state-thumb:focus-visible .sprite-state-swap { opacity:1; }
.sprite-state-thumb:focus-visible { outline:2px solid var(--blue); outline-offset:2px; }
.sprite-state-label { font-size:12px; font-weight:600; color:var(--fg); }
.sprite-state-file { font-family:var(--f-mono); font-size:10px; letter-spacing:.5px; color:var(--muted); word-break:break-all; }
.sprite-state.is-uploading { opacity:.6; }
.sprite-state.is-failed { border-color:rgba(255,93,108,0.5); }

/* dashed dropzones: add-a-state tile + the new-sprite card */
.sprite-state-add, .sprite-new {
  border:1.5px dashed rgba(43,140,255,0.4); background:rgba(43,140,255,0.04);
  color:var(--muted-2); cursor:pointer; font-family:var(--f-ui);
  transition:border-color .15s, background .15s, color .15s;
}
.sprite-state-add { justify-content:center; min-height:120px; font-size:12.5px; font-weight:600; }
.sprite-state-add:hover, .sprite-new:hover,
.sprite-state-add.is-dropping, .sprite-new.is-dropping {
  border-color:var(--blue); background:rgba(43,140,255,0.1); color:var(--blue);
}
.sprite-new {
  display:flex; align-items:center; gap:16px; text-align:left; width:100%;
  padding:20px; border-radius:16px; margin-top:4px;
}
.sprite-new-icon {
  flex:none; width:48px; height:48px; border-radius:14px; display:flex; align-items:center; justify-content:center;
  font-size:22px; background:rgba(43,140,255,0.1); border:1px solid rgba(43,140,255,0.25); color:var(--blue);
}
.sprite-new-title { font-family:var(--f-display); font-weight:600; font-size:15px; margin:0 0 4px; color:var(--fg); }
.sprite-new-desc { font-size:12.5px; color:var(--muted); line-height:1.5; margin:0; }

/* Sprites are made group-first: this button makes an empty group, then you add looks into it. */
.sprite-group-add {
  display:flex; align-items:center; gap:10px; width:100%; padding:12px 16px; margin:0 0 10px;
  border:1.5px dashed rgba(43,140,255,0.4); background:rgba(43,140,255,0.04); border-radius:12px;
  color:var(--muted-2); cursor:pointer; font-family:var(--f-ui); font-weight:600; font-size:13.5px;
  transition:border-color .15s, background .15s, color .15s;
}
.sprite-group-add:hover { border-color:var(--blue); background:rgba(43,140,255,0.1); color:var(--blue); }
.sprite-group-add-icon {
  flex:none; width:26px; height:26px; border-radius:8px; display:flex; align-items:center; justify-content:center;
  font-size:17px; background:rgba(43,140,255,0.1); border:1px solid rgba(43,140,255,0.25); color:var(--blue);
}
/* The inline namer that opens under the button when you're naming a new group. */
.sprite-group-namer { display:flex; gap:8px; align-items:center; margin:0 0 10px; }
.sprite-group-namer input {
  flex:1; padding:9px 12px; border-radius:10px; border:1.5px solid var(--blue);
  background:var(--bg); color:var(--fg); font-family:var(--f-ui); font-size:14px;
}
/* A just-made group has no looks yet — a small nudge to add the first one. */
.sprite-empty-note { font-size:12.5px; color:var(--muted); margin:0 0 8px; }

/* "Browse the gallery" — pull shared assets in. Sits under the assets intro line. */
.studio-gallery-open {
  display:inline-flex; align-items:center; gap:7px; margin:2px 0 14px; padding:9px 14px;
  border-radius:10px; border:1px solid rgba(43,140,255,0.35); background:rgba(43,140,255,0.08);
  color:var(--blue); cursor:pointer; font-family:var(--f-ui); font-weight:600; font-size:13px;
  transition:background .15s, border-color .15s;
}
.studio-gallery-open:hover { background:rgba(43,140,255,0.16); border-color:var(--blue); }

/* The gallery browser modal (reuses the .studio-modal-wrap scrim). Wider than the naming dialog. */
.studio-gallery {
  position:relative; z-index:1; width:min(760px, 94vw); max-height:88vh; display:flex; flex-direction:column;
  background:var(--panel); border:1px solid var(--line); border-radius:18px; padding:20px 22px;
  box-shadow:0 24px 60px rgba(0,0,0,0.5);
}
.studio-gallery-head { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; }
.studio-gallery-head h3 { font-family:var(--f-display); font-size:19px; margin:0; color:var(--fg); }
.studio-gallery-sub { font-size:13px; color:var(--muted); margin:3px 0 0; }
/* Breadcrumb: All › Category › Sprite — you click down the tree instead of searching. */
.studio-gallery-crumbs { display:flex; flex-wrap:wrap; align-items:center; gap:4px; margin:14px 0 12px; }
.gallery-crumb {
  padding:4px 9px; border-radius:8px; border:none; background:transparent; cursor:pointer;
  color:var(--blue); font-family:var(--f-ui); font-size:13px; font-weight:600;
}
.gallery-crumb[data-crumb]:hover { background:rgba(43,140,255,0.1); }
.gallery-crumb.is-current { color:var(--fg); cursor:default; }
.gallery-crumb-sep { color:var(--muted); font-size:13px; }
.studio-gallery-grid {
  overflow-y:auto; display:grid; gap:12px; padding:2px;
  grid-template-columns:repeat(auto-fill, minmax(112px, 1fr));
}
.gallery-card {
  display:flex; flex-direction:column; align-items:center; gap:6px; padding:10px 8px;
  border:1px solid var(--line); border-radius:12px; background:var(--bg); cursor:pointer; text-align:center;
  transition:border-color .12s, background .12s, transform .06s;
}
.gallery-card:hover { border-color:var(--blue); background:rgba(43,140,255,0.06); }
.gallery-card:active { transform:scale(0.97); }
.gallery-card:focus-visible { outline:2px solid var(--blue); outline-offset:2px; }
.gallery-thumb {
  position:relative; width:64px; height:64px; border-radius:9px; display:flex; align-items:center; justify-content:center;
  /* a light checker so transparent PNGs read clearly on any theme */
  background-color:#c8c8c8;
  background-image:linear-gradient(45deg,#a9a9a9 25%,transparent 25%,transparent 75%,#a9a9a9 75%),
                   linear-gradient(45deg,#a9a9a9 25%,transparent 25%,transparent 75%,#a9a9a9 75%);
  background-size:14px 14px; background-position:0 0,7px 7px;
}
.gallery-thumb img { max-width:100%; max-height:100%; image-rendering:pixelated; }
.gallery-thumb.is-sound { background:rgba(43,140,255,0.1); font-size:26px; }
.gallery-play {
  position:absolute; right:-4px; bottom:-4px; width:22px; height:22px; border-radius:50%;
  border:none; background:var(--blue); color:#fff; font-size:10px; cursor:pointer; line-height:1;
}
.gallery-card-name { font-size:12.5px; font-weight:600; color:var(--fg); word-break:break-word; }
.gallery-card-meta { font-size:11px; color:var(--muted); }
@media (max-width:560px) {
  .studio-gallery-grid { grid-template-columns:repeat(auto-fill, minmax(92px, 1fr)); }
}

/* Blockly ships its own font stack, so the category list down the left (Game, Sprites, …) rendered
   in a system sans while everything around it is Nunito. The toolbox is OUR chrome, not part of the
   canvas, so it takes the site's display face. Block labels are left alone deliberately: Blockly
   measures those to lay blocks out, and changing the face there moves every block's geometry. */
/* The workspace bin: Blockly draws it dim (0.4). Make it more present, so it's an obvious place to
   drop a block you don't want. Its position is centred under the zoom controls by studio.js. */
.studio-workspace .blocklyTrash { opacity:0.9 !important; }

/* The "what is this category for" note, shown while a block flyout is open. Top-right so it never
   sits under the left-hand flyout; non-interactive so it never eats a drag. */
.studio-catnote {
  position:absolute; top:12px; right:14px; z-index:30;
  max-width:min(360px, 48%); margin:0; padding:10px 13px;
  background:rgba(10,14,38,0.95); border:1px solid rgba(122,182,255,0.32);
  border-radius:12px; box-shadow:0 8px 24px rgba(0,0,0,0.38);
  color:#cdd6ef; font-size:12.5px; line-height:1.45; pointer-events:none;
  animation:studio-catnote-in 140ms ease-out;
}
.studio-catnote[hidden] { display:none; }
.studio-catnote b { color:#fff; font-weight:700; }
.studio-catnote em { color:#7ab6ff; font-style:normal; font-weight:600; }
@keyframes studio-catnote-in { from { opacity:0; transform:translateY(-4px); } to { opacity:1; transform:none; } }

/* The "Create variable…" button that heads the Variables flyout. Blockly draws it as a pale grey
   pill that looks pasted-on over the dark canvas — restyle it to our blue action colour. These are
   SVG nodes, so we set fill/stroke, not background. */
.studio-workspace .blocklyFlyoutButtonShadow { display:none; }
.studio-workspace .blocklyFlyoutButtonBackground {
  fill:var(--blue, #2b8cff); stroke:rgba(255,255,255,0.22); stroke-width:1px;
}
.studio-workspace .blocklyFlyoutButton:hover .blocklyFlyoutButtonBackground { fill:#4a9cff; }
.studio-workspace .blocklyFlyoutButton .blocklyText { fill:#fff; font-weight:600; }

/* The little text box that opens when you click a number/text field on a block. Blockly colours it
   from the block, which on our dark blocks comes out dark-on-dark — you can't see what you type. Pin
   it to a readable dark box with white text and a blue caret. Not scoped to .studio-workspace because
   Blockly appends this widget to <body>. */
.blocklyHtmlInput {
  background:#0a0e26 !important; color:#ffffff !important;
  border:1.5px solid var(--blue, #2b8cff) !important; border-radius:6px !important;
  box-shadow:0 6px 18px rgba(0,0,0,0.45) !important; caret-color:var(--blue, #2b8cff);
}

.blocklyToolboxDiv, .blocklyTreeLabel, .blocklyToolboxCategory, .blocklyFlyoutLabelText {
  font-family:var(--f-display) !important;
}
.blocklyTreeLabel { font-size:13.5px !important; font-weight:600; letter-spacing:.1px; }

/* ---- the code + who-can-play chip, in the toolbar ---- */
.studio-statuschip {
  display:inline-flex; align-items:center; gap:6px; cursor:pointer; font:inherit; font-size:12.5px;
  padding:6px 11px; border-radius:9px; white-space:nowrap;
  background:rgba(43,140,255,0.08); border:1px solid var(--line); color:var(--fg);
  transition:border-color .12s ease, background .12s ease;
}
.studio-statuschip:hover { border-color:var(--line-strong); background:rgba(43,140,255,0.14); }
/* The icon takes the chip's colour, so each state is said once — by the glyph and the words
   together — rather than by an emoji insisting on its own palette. */
.studio-statuschip-text { display:inline-flex; align-items:center; gap:6px; }
/* The code itself, when there is one to show: the old chip's mono, spaced-out treatment, so it is
   read letter by letter — that is how it gets typed into a mebobox. */
.studio-statuschip-code { font-family:var(--f-mono); font-weight:600; font-size:14px; letter-spacing:2.5px; }
.studio-statuschip-sep { opacity:.45; }
.studio-statuschip-copy { font-size:12px; opacity:.7; }
.studio-statuschip.copied { background:rgba(70,224,138,0.22); border-color:rgba(70,224,138,0.6); }
/* Not built yet is the call to action, in the same amber the Details note uses, so the two agree at
   a glance; friends-only reads as fine, public as a real green light. */
.studio-statuschip[data-state="draft"]   { color:#f7d774; border-color:rgba(234,179,8,0.32); background:rgba(234,179,8,0.08); }
.studio-statuschip[data-state="draft"]:hover { border-color:rgba(234,179,8,0.6); background:rgba(234,179,8,0.14); }
.studio-statuschip[data-state="code"]    { color:var(--green); border-color:rgba(70,224,138,0.4); background:rgba(70,224,138,0.1); }
.studio-statuschip[data-state="code"]:hover { border-color:rgba(70,224,138,0.7); background:rgba(70,224,138,0.18); }
.studio-statuschip[data-state="waiting"] { color:#f7d774; border-color:rgba(234,179,8,0.32); background:rgba(234,179,8,0.08); }
.studio-statuschip[data-state="public"]  { color:#7ee08a; border-color:rgba(70,224,138,0.32); background:rgba(70,224,138,0.08); }

/* ---- game details ---- */
.studio-details {
  position:relative; z-index:1; width:min(560px, calc(100vw - 32px)); max-height:calc(100vh - 64px);
  overflow-y:auto; padding:20px; border-radius:16px; background:var(--panel-1);
  border:1px solid var(--line); box-shadow:0 24px 60px rgba(0,0,0,0.5);
}
.studio-details h3 {
  margin:0 0 14px; font-family:var(--f-display); font-weight:700; font-size:18px; color:var(--fg);
}
.studio-details .field { margin-bottom:16px; }
.studio-details textarea {
  width:100%; resize:vertical; min-height:66px; font:inherit; padding:9px 11px; border-radius:10px;
  background:rgba(5,3,15,0.5); border:1px solid var(--line); color:var(--fg);
}
.studio-details-count { margin:4px 0 0; text-align:right; font-size:11.5px; color:var(--muted); }
.studio-details-hint { margin:4px 0 0; font-size:12px; line-height:1.45; color:var(--muted); }

.studio-cover { display:flex; gap:14px; align-items:flex-start; margin-top:8px; }
.studio-cover-preview {
  flex:none; width:132px; aspect-ratio:4/3; display:flex; align-items:center; justify-content:center;
  overflow:hidden; border-radius:10px; background:rgba(5,3,15,0.6);
  border:1px dashed rgba(43,140,255,0.35);
}
.studio-cover-preview img { width:100%; height:100%; object-fit:cover; }
.studio-cover-empty { font-size:11.5px; color:var(--muted); text-align:center; padding:6px; }
.studio-cover-actions { display:flex; flex-direction:column; gap:8px; align-items:flex-start; }
.ghostbtn.sm { padding:8px 14px; border-radius:10px; font-size:13px; }
.ghostbtn.sm.danger { color:var(--red); border-color:rgba(239,68,68,0.35); }

.studio-visibility { border:none; margin:0 0 16px; padding:0; }
.studio-visibility legend {
  padding:0; margin-bottom:8px; font-size:13px; font-weight:600; color:var(--fg);
}
.studio-vis-option {
  display:flex; gap:10px; align-items:flex-start; padding:10px 11px; margin-bottom:8px;
  border-radius:10px; background:rgba(5,3,15,0.4); border:1px solid var(--line-soft); cursor:pointer;
}
.studio-vis-option:has(input:checked) {
  border-color:rgba(43,140,255,0.45); background:rgba(43,140,255,0.09);
}
/* account.css styles bare `input` as a full-width text field (width:100%, 12px padding). That is
   right for every other input on the site and very wrong for a radio, which it stretched across the
   row and left the text crushed into a column beside it. */
.studio-vis-option input[type="radio"] {
  width:auto; flex:none; margin:3px 0 0; padding:0; border:none; background:none;
}
.studio-vis-option > span { flex:1; min-width:0; }
.studio-vis-option.is-locked { opacity:.65; cursor:default; }
.studio-vis-locked { display:block; margin-top:6px; font-size:11.5px; font-style:normal; color:#f7d774; }
.studio-vis-option strong { display:block; font-size:13px; font-weight:600; color:var(--fg); }
.studio-vis-option em { display:block; margin-top:2px; font-size:12px; font-style:normal; color:var(--muted); }
.studio-vis-state {
  margin:2px 0 0; padding:9px 11px; border-radius:9px; font-size:12.5px; line-height:1.45;
  background:rgba(234,179,8,0.1); border:1px solid rgba(234,179,8,0.3); color:#f7d774;
}
.studio-vis-state[hidden] { display:none; }
@media (max-width:520px) {
  .studio-cover { flex-direction:column; }
}

/* ---- controls help, in the Run screen ---- */
.studio-keys { position:relative; display:flex; }
.studio-keys-menu {
  position:absolute; bottom:calc(100% + 10px); left:0; z-index:70; width:min(340px, calc(100vw - 40px));
  padding:14px; border-radius:12px; background:#0d1330; border:1px solid rgba(43,140,255,0.3);
  box-shadow:0 20px 44px rgba(0,0,0,0.5);
  /* It opens UPWARD from a button near the bottom of the screen, so its ceiling is the viewport,
     not its content — the full twelve-button table clipped its own title off the top of small
     windows until it learnt to scroll. */
  max-height:calc(100vh - 130px); overflow-y:auto;
}
.studio-keys-menu[hidden] { display:none; }
.studio-keys-title {
  margin:0 0 8px; font-family:var(--f-display); font-weight:700; font-size:13.5px; color:var(--fg);
}
.studio-keys-why { margin:8px 0 0; font-size:12px; line-height:1.5; color:var(--muted); }
.studio-keys-table { width:100%; margin-top:10px; border-collapse:collapse; font-size:12.5px; }
.studio-keys-table th {
  text-align:left; padding:4px 6px; font-size:10.5px; text-transform:uppercase; letter-spacing:.4px;
  color:var(--muted); border-bottom:1px solid var(--line-soft); font-weight:700;
}
.studio-keys-table td { padding:5px 6px; color:var(--fg); border-bottom:1px solid var(--line-soft); }
.studio-keys-table tr:last-child td { border-bottom:none; }
.studio-keys-table td:first-child { font-weight:600; }
kbd {
  display:inline-block; margin-right:3px; padding:1px 6px; border-radius:5px; font-size:11.5px;
  font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  background:rgba(43,140,255,0.14); border:1px solid rgba(43,140,255,0.32); color:#cfe0ff;
}

/* ---- the colour (Look) popover ---- */
.studio-look { position:relative; display:flex; }
.studio-look-menu {
  position:absolute; top:calc(100% + 8px); right:0; z-index:60; width:230px;
  padding:12px; border-radius:12px; background:#0d1330;
  border:1px solid rgba(43,140,255,0.28); box-shadow:0 18px 40px rgba(0,0,0,0.45);
}
.studio-look-menu[hidden] { display:none; }
.studio-look-title {
  margin:0 0 10px; font-family:var(--f-display); font-weight:600; font-size:13.5px; color:var(--fg);
}
.studio-look-row {
  display:flex; align-items:center; gap:10px; margin-bottom:8px; font-size:13px; color:var(--fg);
  cursor:pointer;
}
.studio-look-row input[type="color"] {
  flex:none; width:34px; height:26px; padding:0; cursor:pointer; background:none;
  border:1px solid rgba(43,140,255,0.3); border-radius:7px;
}
.studio-look-note { margin:10px 0 0; font-size:11.5px; line-height:1.45; color:var(--muted); }

/* ============================ code pane ============================ */
/* File tabs. One block makes three things, so the panel shows three files — and a tab carries a dot
   when the selected block put something in THAT file. Without the dot, selecting a "show text"
   block (an element and a rule, no TypeScript) would light up nothing at all with the code tab
   open, and the child would conclude the block does nothing. */
.studio-files { display:flex; align-items:center; gap:4px; flex-wrap:wrap; }
/* Each tab says what its file IS, not just what it's called. All three captions are visible at
   once on purpose: the three-way split — behaviour, structure, presentation — is the thing being
   taught, and it only reads as a set if you can see the set. */
.studio-file {
  position:relative; appearance:none; cursor:pointer; font:inherit; text-align:left;
  display:flex; flex-direction:column; gap:1px;
  padding:5px 11px 6px; border-radius:9px;
  border:1px solid transparent; background:transparent; color:var(--muted);
  transition:background .12s ease, color .12s ease, border-color .12s ease;
}
.studio-file-name {
  font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size:12.5px;
}
.studio-file-what { font-size:10.5px; line-height:1.2; color:var(--muted); opacity:.85; }
.studio-file.is-active .studio-file-what { color:#9fc2ff; opacity:1; }

/* At level 2 these stop being an explanation of generated output and become ordinary editor tabs:
   filename only, squared off, with the active one seated against the editor below it. The captions
   are teaching aids for level 1 — here they are noise above someone's own code. */
.studio-editor.is-code .studio-file-what { display:none; }
/* The tab strip IS the pane header — same height as "Files" opposite it, with the tabs running the
   full height so the open one meets the editor with no seam. Previously they floated in a padded
   header and read as detached from the thing they belong to. */
.studio-editor.is-code .studio-pane-code > .studio-pane-head {
  padding:0 10px; min-height:41px; align-items:stretch; gap:0;
}
.studio-editor.is-code .studio-files { gap:0; align-items:stretch; }
/* Inset from the top so the tab is a shape sitting IN the header rather than filling it. */
.studio-editor.is-code .studio-file {
  padding:0 14px; margin-top:5px; border-radius:8px 8px 0 0;
  border:1px solid transparent; border-bottom:none;
}
/* Outlined on three sides and open at the bottom — the classic document tab, where the missing
   edge is what joins it to the editor. A bar underneath said the opposite: it drew a line exactly
   where the tab and its file should meet. */
.studio-editor.is-code .studio-file.is-active {
  background:rgba(5,3,15,0.8); border-color:rgba(43,140,255,0.38); color:var(--fg);
}
.studio-editor.is-code .studio-pane-tools { align-items:center; }
.studio-file:hover { color:var(--fg); background:rgba(43,140,255,0.08); }
.studio-file.is-active {
  color:var(--fg); background:rgba(43,140,255,0.14); border-color:rgba(43,140,255,0.3);
}
/* Nothing in this file yet — still listed, because a tab that appears out of nowhere the first time
   you show something is a surprise, and "you haven't put anything on screen yet" is worth saying. */
.studio-file.is-empty { opacity:.5; }
.studio-file.has-link::after {
  content:''; position:absolute; top:3px; right:4px; width:6px; height:6px; border-radius:50%;
  background:var(--blue); box-shadow:0 0 0 2px rgba(8,10,28,0.9);
}
.studio-file.is-active.has-link::after { background:#46e08a; }

/* The tab a just-made edit landed in glows. Editing one block can rewrite a file you are not
   looking at — recolouring a shown variable changes a CSS rule while the code tab is open — and a
   change nobody sees is a change nobody learns from. */
@keyframes studioTabPulse {
  0%   { box-shadow:0 0 0 0 rgba(70,224,138,0); background:rgba(70,224,138,0.05); }
  35%  { box-shadow:0 0 0 3px rgba(70,224,138,0.28); background:rgba(70,224,138,0.2); }
  100% { box-shadow:0 0 0 0 rgba(70,224,138,0); background:rgba(70,224,138,0); }
}
.studio-file.just-changed { animation:studioTabPulse 1s ease-out; }
@media (prefers-reduced-motion:reduce) {
  .studio-file { transition:none; }
  /* No pulse, but the change still has to be findable — so hold a steady tint instead. */
  .studio-file.just-changed { animation:none; background:rgba(70,224,138,0.16); }
}

.studio-codebanner {
  flex:none; margin:0; padding:9px 14px; font-size:12.5px; line-height:1.45; color:#c2cadd;
  background:rgba(7,104,255,0.06); border-bottom:1px solid rgba(43,140,255,0.12);
}
.studio-monaco {
  flex:1; min-height:200px; width:100%; overflow:hidden; background:rgba(5,3,15,0.8);
}
.studio-monaco .monaco-editor .cursors-layer > .cursor { display:none; }   /* read-only: no caret */
.studio-graduation {
  display:flex; align-items:center; gap:12px; flex:none; flex-wrap:wrap;
  padding:12px 14px; border-top:1px solid rgba(43,140,255,0.14); background:rgba(7,104,255,0.05);
}
.studio-grad-icon { flex:none; font-size:19px; }
.studio-graduation p { flex:1; min-width:180px; margin:0; font-size:12.5px; line-height:1.45; color:var(--muted); }
.studio-graduation p strong { color:var(--fg); font-weight:600; }
.studio-graduation .ghostbtn:disabled { opacity:.5; cursor:not-allowed; }
/* Locked at account Level 1: the Edit button stays visible so a child can see the door, but it's
   dimmed and a note says how to open it. The note is a full-width flex item under the row. */
.studio-levelup.is-locked { opacity:.72; }
.studio-graduation.is-locked { border-color:rgba(234,179,8,0.28); background:rgba(234,179,8,0.05); }
.studio-graduation.is-locked::after {
  content:'🔒 Writing your own code comes with the Coder level — switch levels up in the top bar.';
  flex-basis:100%; font-size:12px; color:#f7d774; margin-top:2px;
}

/* ============================ validation bar ============================ */
.studio-valbar {
  display:flex; align-items:center; gap:12px; flex:none; flex-wrap:wrap;
  margin-top:12px; padding:12px 16px; border-radius:16px;
  border:1px solid rgba(43,140,255,0.18); background:var(--grad-panel); font-size:13.5px;
}
.studio-valbar[hidden] { display:none; }
.studio-val-resting, .studio-val-ok { display:flex; align-items:center; gap:10px; }
.studio-val-resting[hidden], .studio-val-ok[hidden], .studio-val-problems[hidden] { display:none; }
.studio-val-resting strong { color:var(--fg); font-weight:700; }
.studio-val-dot {
  flex:none; width:24px; height:24px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  font-size:11px; background:rgba(43,140,255,0.12); border:1px solid rgba(43,140,255,0.35); color:var(--blue);
}
.studio-val-dot.is-ok { background:rgba(70,224,138,0.12); border-color:rgba(70,224,138,0.45); color:var(--green); }
.studio-val-oktitle { font-weight:700; color:var(--green); }
.studio-val-counts { flex:none; margin-left:auto; font-size:12.5px; }

.studio-val-dot.is-bad { background:rgba(255,93,108,0.12); border-color:rgba(255,93,108,0.45); color:var(--red,#ff5d6c); }

/* The headline over the problem list, and the control that folds the list away. Kept visible when
   collapsed, so the panel always still says how many things are wrong. */
.studio-val-summary { display:flex; align-items:center; gap:10px; width:100%; font-weight:700; }
.studio-val-summary[hidden] { display:none; }
.studio-val-summary.is-warn .studio-val-dot {
  background:rgba(251,191,36,0.12); border-color:rgba(251,191,36,0.45); color:#fbbf24;
}
.studio-val-summary #studio-val-toggle { flex:none; font-weight:600; }

.studio-val-problems { display:flex; flex-direction:column; gap:10px; width:100%; }
/* Collapsed gives the canvas back — a long list pushes the editor up, and the editor is the only
   place the problems can actually be fixed. */
.studio-val-problems.is-collapsed { display:none; }
.val-problem {
  border-radius:13px; padding:12px 14px; border:1px solid rgba(255,93,108,0.35);
  background:rgba(255,93,108,0.08);
}
.val-problem.is-warning { border-color:rgba(251,191,36,0.4); background:rgba(251,191,36,0.08); }
.val-problem-title {
  display:flex; align-items:center; gap:8px; margin:0 0 5px;
  font-family:var(--f-display); font-weight:700; font-size:14.5px; color:var(--fg);
}
.val-problem-body { margin:0; font-size:13px; line-height:1.5; color:#e6b9bf; }
.val-problem.is-warning .val-problem-body { color:#e8d4a6; }
.val-problem.is-warning .val-problem-title { color:#fbbf24; }

/* ---- block <-> code linking ----
   Monaco applies these to the line content and to the gutter margin (see monaco.js highlight()).
   BLUE = "this is the code your selected block made". GREEN FLASH = "you just changed this block,
   and this is the code that moved" — a different question, so a different colour, and it fades back
   to blue rather than latching on. Without these the linking exists but is invisible. */
.studio-code-linked { background:rgba(43,140,255,0.16); }
.studio-code-linkedgutter { width:3px !important; margin-left:4px; background:var(--blue); }
.studio-code-changed { background:rgba(70,224,138,0.22); animation:studioCodeFlash 1.2s ease-out; }
@keyframes studioCodeFlash {
  from { background:rgba(70,224,138,0.55); }
  to { background:rgba(70,224,138,0.22); }
}
@media (prefers-reduced-motion: reduce) {
  .studio-code-changed { animation:none; }
}

/* The one-click repair on a problem card. Deliberately the most prominent thing on the card — for
   this audience "just fix it" beats "here is where the problem is". */
.val-problem-fix {
  padding:7px 13px; border-radius:9px; border:none; cursor:pointer;
  font-family:var(--f-ui); font-size:12.5px; font-weight:800;
  background:rgba(248,113,113,0.9); color:#3d0a0a;
}
.val-problem-fix:hover { filter:brightness(1.06); }
.val-problem.is-warning .val-problem-fix { background:rgba(251,191,36,0.9); color:#3d2a04; }

/* Warnings-only: the game launched, so the bar reads as information rather than a blocked run. */
.studio-val-problems.is-warnings-only { opacity:.95; }
.val-problem-actions { display:flex; flex-wrap:wrap; gap:8px; margin-top:10px; }
.val-problem-actions .ghostbtn { padding:7px 12px; font-size:12.5px; }
.val-detail {
  margin-top:10px; padding:9px 11px; border-radius:10px; background:rgba(5,3,15,0.6);
  font-family:var(--f-mono); font-size:11.5px; line-height:1.5; color:var(--muted-2);
  white-space:pre-wrap; overflow-x:auto;
}
.val-detail[hidden] { display:none; }

/* ============================ run overlay ============================
   Scoped to #tab-studio (absolute, not fixed) so the site nav stays visible above it. */
.studio-overlay {
  /* fixed, not absolute: an absolute overlay centres inside the studio panel, and a panel taller
     than the window pushed the dialog's bottom off-screen. */
  position:fixed; inset:0; z-index:70; display:flex; align-items:center; justify-content:center;
  padding:20px; background:rgba(3,2,10,0.78); backdrop-filter:blur(6px);
  animation:wbpop .18s ease-out;
}
.studio-overlay[hidden] { display:none; }
.studio-rundialog {
  display:flex; flex-direction:column; width:min(680px,90%);
  max-height:calc(100vh - 40px); min-height:0;
  border-radius:20px; overflow:hidden; border:1px solid rgba(43,140,255,0.32);
  background:linear-gradient(180deg,#0e1330,#0a0c20);
  box-shadow:0 30px 90px rgba(0,0,0,0.65),0 0 60px rgba(7,104,255,0.18);
}
/* The dialog holds the keyboard while a game runs (studio.js focusGame), so it is focused the whole
   time you are playing — a ring around the entire window would read as an error, not as a game. It
   has to out-specify the blanket #tab-studio :focus-visible ring further down, which is meant for
   the things you actually tab to. */
#tab-studio .studio-rundialog:focus,
#tab-studio .studio-rundialog:focus-visible { outline:none; }
.studio-run-head {
  display:flex; align-items:center; gap:10px; flex:none; padding:12px 14px;
  border-bottom:1px solid rgba(43,140,255,0.16); font-family:var(--f-display); font-weight:600; font-size:15px;
}

/* "It can't run yet" — same slot and shape as the run dialog, because it stands in for it. Amber,
   not red: the game is unfinished, which is the ordinary state of a game being built. */
.studio-rundialog.is-cantrun { border-color:rgba(251,191,36,0.4); }
.studio-rundialog.is-cantrun .studio-run-head { border-bottom-color:rgba(251,191,36,0.22); }
.studio-cantrun-body {
  flex:1 1 auto; min-height:0; overflow-y:auto; padding:14px; display:flex; flex-direction:column; gap:10px;
}
.cantrun-problem {
  border-radius:13px; padding:12px 14px;
  border:1px solid rgba(251,191,36,0.35); background:rgba(251,191,36,0.08);
}
.cantrun-problem-title { font-weight:700; margin-bottom:5px; }
.cantrun-problem-body { color:var(--muted); line-height:1.5; }
.cantrun-problem-actions { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:10px; }

/* Warnings ride with the game they did not stop, inside the run overlay. */
.studio-run-warnings { flex:none; padding:10px 14px 0; display:flex; flex-direction:column; gap:8px; }
.studio-run-warnings[hidden] { display:none; }
.run-warning {
  display:flex; gap:9px; align-items:flex-start; font-size:12.5px; line-height:1.5;
  border-radius:11px; padding:9px 11px;
  border:1px solid rgba(251,191,36,0.32); background:rgba(251,191,36,0.08); color:var(--muted);
}
.run-warning strong { color:var(--fg); }
.run-warning-mark { flex:none; color:#fbbf24; }
.studio-run-name { color:var(--blue); }
/* Matches the game's logical canvas (src/studio-build.js CANVAS_WIDTH/HEIGHT), so the preview shows
   exactly the shape the child is building against — no letterboxing inside the letterbox. */
/* The game keeps its 4:3 shape, but on a short window it is what shrinks — the title bar, the game
   code and the Restart/Stop/Back controls must stay reachable. */
.studio-run-viewport {
  position:relative; flex:1 1 auto; min-height:0; width:100%; aspect-ratio:4/3; background:#000;
}
.studio-run-viewport iframe { position:absolute; inset:0; width:100%; height:100%; border:0; display:block; background:#000; }
.studio-run-loading {
  position:absolute; inset:0; margin:0; display:flex; align-items:center; justify-content:center;
  color:var(--muted); font-size:14px; pointer-events:none;
}
.studio-run-loading[hidden] { display:none; }
.studio-run-tip {
  flex:none; margin:0; padding:11px 16px; font-size:12.5px; line-height:1.45; color:var(--muted);
  background:rgba(7,104,255,0.06); border-bottom:1px solid rgba(43,140,255,0.12);
}
.studio-run-code {
  font-family:var(--f-mono); font-weight:600; letter-spacing:3px; color:var(--green);
  text-shadow:0 0 10px rgba(70,224,138,0.5);
}
.studio-run-controls { display:flex; align-items:center; gap:10px; flex:none; flex-wrap:wrap; padding:12px 14px; }
.studio-run-hint { font-size:12.5px; }
.studio-rundialog.is-full { width:100%; height:100%; border-radius:0; }
.studio-rundialog.is-full .studio-run-viewport { flex:1; aspect-ratio:auto; }

/* ============================ version history drawer ============================ */
.studio-drawer-wrap { position:fixed; inset:0; z-index:60; display:flex; justify-content:flex-end; }
.studio-drawer-wrap[hidden] { display:none; }
.studio-drawer-scrim { position:absolute; inset:0; background:rgba(3,2,10,0.6); backdrop-filter:blur(3px); }
@keyframes studio-drawer-in { from { transform:translateX(100%); } to { transform:translateX(0); } }
.studio-drawer {
  position:relative; display:flex; flex-direction:column; width:390px; max-width:100%; height:100%;
  padding:18px; overflow-y:auto; border-left:1px solid rgba(43,140,255,0.3);
  background:linear-gradient(180deg,#0e1330,#0a0c20);
  box-shadow:-24px 0 70px rgba(0,0,0,0.6); animation:studio-drawer-in .22s cubic-bezier(.2,.8,.2,1);
}
.studio-drawer-head { display:flex; align-items:center; gap:10px; margin-bottom:8px; }
.studio-drawer-head h3 { font-family:var(--f-display); font-weight:700; font-size:17px; margin:0; }
.studio-drawer-desc { font-size:12.5px; color:var(--muted); line-height:1.5; margin:0 0 16px; }
.studio-drawer-list { display:flex; flex-direction:column; gap:10px; }

.version-item {
  border-radius:13px; border:1px solid rgba(43,140,255,0.2); background:rgba(7,104,255,0.05); padding:13px 14px;
}
.version-item.is-current { border-color:rgba(70,224,138,0.45); background:rgba(70,224,138,0.06); }
.version-head { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.version-name { font-family:var(--f-display); font-weight:600; font-size:14.5px; color:var(--fg); }
.version-badge {
  flex:none; font-size:10px; font-weight:700; letter-spacing:.4px; text-transform:uppercase;
  padding:2px 8px; border-radius:999px;
  color:var(--muted); background:rgba(138,147,173,0.12); border:1px solid rgba(138,147,173,0.35);
}
.version-badge.is-current { color:var(--green); background:rgba(70,224,138,0.12); border-color:rgba(70,224,138,0.45); }
.version-meta { font-size:12px; color:var(--muted); margin:5px 0 0; }
.version-actions { display:flex; flex-wrap:wrap; gap:8px; margin-top:11px; }
.version-actions .ghostbtn { padding:7px 12px; font-size:12.5px; }

/* ============================ preview (read-only) bar ============================ */
.studio-previewbar {
  display:flex; align-items:center; gap:12px; flex:none; flex-wrap:wrap;
  margin-top:12px; padding:12px 16px; border-radius:16px; font-size:13.5px; color:#e8d4a6;
  background:rgba(251,191,36,0.08); border:1px solid rgba(251,191,36,0.4);
}
.studio-previewbar[hidden] { display:none; }
.studio-previewbar strong { color:var(--fg); font-weight:700; }

/* ============================ modals (rollback / name a version) ============================ */
.studio-modal-wrap {
  position:fixed; inset:0; z-index:80; display:flex; align-items:center; justify-content:center; padding:20px;
}
.studio-modal-wrap[hidden] { display:none; }
.studio-modal-scrim { position:absolute; inset:0; background:rgba(3,2,10,0.72); backdrop-filter:blur(4px); }
.studio-rollback {
  position:relative; width:460px; max-width:100%; padding:26px; border-radius:20px; text-align:center;
  border:1px solid rgba(43,140,255,0.32); background:linear-gradient(180deg,#0e1330,#0a0c20);
  box-shadow:0 30px 90px rgba(0,0,0,0.65),0 0 60px rgba(7,104,255,0.15); animation:wbpop .18s ease-out;
}
.studio-rollback-icon {
  width:56px; height:56px; border-radius:50%; margin:0 auto 14px; display:flex; align-items:center; justify-content:center;
  font-size:25px; background:rgba(43,140,255,0.12); border:1px solid rgba(43,140,255,0.4);
  box-shadow:0 0 26px rgba(7,104,255,0.35);
}
.studio-rollback h3 { font-family:var(--f-display); font-weight:700; font-size:20px; margin:0 0 10px; }
.studio-rollback p { font-size:13.5px; color:var(--muted); line-height:1.55; margin:0 0 12px; }
.studio-rollback p strong { color:var(--fg); font-weight:600; }
.studio-rollback-note {
  padding:10px 12px; border-radius:11px; font-size:12.5px;
  background:rgba(7,104,255,0.07); border:1px solid rgba(43,140,255,0.2);
}
.studio-rollback input { text-align:left; margin-bottom:6px; }
.studio-rollback-actions { display:flex; justify-content:center; gap:10px; margin-top:18px; }

/* ============================ mebo: the help panel ============================
   A DRAWER, not a dialog, and the difference is the whole design. mebo's answer is "look at that
   block and drag it under start" — so the block has to be visible and draggable while the answer is
   on screen. A centred card put the answer on top of the thing it was pointing at.
   It docks right, over the CODE pane, so the blocks pane on the left stays clear. No scrim, nothing
   modal, and pointer-events are off on the wrapper so every click that is not on the panel itself
   goes straight through to the workspace underneath. Reuses .studio-drawer's shape and animation. */
.studio-askmebo { display:inline-flex; align-items:center; gap:7px; }
.studio-askmebo img { display:block; }

/* "Submit my game" — the only gold thing in the app, because it is the only button in this row that
   is not about making the game. Everything else here changes it; this one enters it. */
.studio-enter { color:#ffc74a; border-color:rgba(255,199,74,0.4); background:rgba(255,199,74,0.08); }
.studio-enter:hover { color:#ffe49a; border-color:rgba(255,199,74,0.75); background:rgba(255,199,74,0.16); }

.studio-help-wrap { pointer-events:none; }
.studio-help-wrap[hidden] { display:none; }
.studio-help {
  pointer-events:auto;                 /* the panel itself is live; the space beside it is not */
  width:400px; text-align:left;
}
.studio-help-head { display:flex; align-items:flex-start; gap:12px; margin-bottom:16px; }
.studio-help-head > div { flex:1; min-width:0; }
.studio-help-head h3 { font-family:var(--f-display); font-weight:700; font-size:19px; margin:0; color:var(--fg); }
.studio-help-mebo { flex:none; margin-top:-2px; }   /* bigger, so nudge it back into line */
.studio-help-sub { font-size:13px; color:var(--muted); margin:3px 0 0; }
.studio-help-sub:empty { display:none; }
/* Any class that sets `display` beats the UA's [hidden] rule — see the note in account.css. */
.studio-help-step[hidden], .studio-help-cards[hidden], .studio-help-actions[hidden] { display:none; }
.studio-help-lead { font-size:14px; font-weight:600; color:var(--fg); margin:0 0 12px; display:block; }

/* the free checks, shown before mebo is ever offered */
.studio-help-finding {
  display:block; padding:11px 13px; border-radius:12px; margin-bottom:9px;
  border:1px solid rgba(43,140,255,0.2); background:rgba(7,104,255,0.07);
}
.studio-help-finding.is-error { border-color:rgba(255,93,108,0.4); background:rgba(255,93,108,0.08); }
.studio-help-finding strong { display:block; font-size:13.5px; color:var(--fg); margin-bottom:3px; }
.studio-help-finding span { display:block; font-size:12.5px; color:var(--muted); line-height:1.5; }

/* The three ways in. Stacked, not three-across: the panel is 400px, and a row of three would give
   each card 120px and turn every label into three lines. */
.studio-help-cards { display:grid; grid-template-columns:1fr; gap:9px; }
.studio-help-card {
  display:grid; grid-template-columns:auto 1fr; grid-template-rows:auto auto;
  column-gap:11px; row-gap:2px; text-align:left; cursor:pointer;
  padding:12px 13px; border-radius:13px; color:var(--fg);
  border:1px solid rgba(43,140,255,0.25); background:rgba(7,104,255,0.06);
  transition:border-color .12s, background .12s;
}
.studio-help-card:hover { border-color:rgba(43,140,255,0.55); background:rgba(43,140,255,0.12); }
.studio-help-card-icon { grid-row:1 / span 2; align-self:center; font-size:20px; }
.studio-help-card-title { font-size:13.5px; font-weight:600; }
.studio-help-card-desc { font-size:12px; color:var(--muted); line-height:1.4; }

/* the questions answered for free */
.studio-help-common-list { display:flex; flex-direction:column; gap:7px; }
.studio-help-common {
  text-align:left; cursor:pointer; padding:11px 13px; border-radius:11px; font-size:13.5px; color:var(--fg);
  border:1px solid rgba(43,140,255,0.22); background:rgba(7,104,255,0.05);
}
.studio-help-common:hover { border-color:rgba(43,140,255,0.5); background:rgba(43,140,255,0.11); }

.studio-help textarea {
  width:100%; padding:12px 14px; border-radius:11px; font:inherit; font-size:13.5px; resize:vertical;
  color:var(--fg); background:rgba(5,3,15,0.7); border:1px solid rgba(43,140,255,0.25);
}
.studio-help textarea:focus {
  outline:none; border-color:rgba(43,140,255,0.7); box-shadow:0 0 0 3px rgba(43,140,255,0.15);
}
.studio-help-count { font-size:11.5px; color:var(--muted); margin:6px 0 0; }

/* thinking */
.studio-help-thinking { display:flex; align-items:center; gap:10px; font-size:13.5px; color:var(--muted); margin:22px 0; }
.studio-help-dots { display:inline-flex; gap:4px; }
.studio-help-dots i { width:6px; height:6px; border-radius:50%; background:var(--blue); animation:mb-help-dot 1.1s infinite ease-in-out; }
.studio-help-dots i:nth-child(2) { animation-delay:.16s; }
.studio-help-dots i:nth-child(3) { animation-delay:.32s; }
@keyframes mb-help-dot { 0%,80%,100% { opacity:.25; transform:translateY(0); } 40% { opacity:1; transform:translateY(-3px); } }
@media (prefers-reduced-motion:reduce) { .studio-help-dots i { animation:none; opacity:.6; } }

/* the answer */
.studio-help-bubble {
  padding:14px 16px; border-radius:14px;
  border:1px solid rgba(43,140,255,0.28); background:rgba(7,104,255,0.08);
}
.studio-help-bubble p { font-size:14px; color:var(--fg); line-height:1.6; margin:0; }
.studio-help-bubble ol { margin:11px 0 0; padding-left:20px; }
.studio-help-bubble ol[hidden] { display:none; }
.studio-help-bubble li { font-size:13px; color:var(--muted-2); line-height:1.6; margin-bottom:4px; }
.studio-help-bubble b { color:var(--fg); font-weight:600; }
.studio-help-note {
  font-size:12.5px; color:var(--muted); margin:11px 0 0; padding-left:20px; position:relative;
}
.studio-help-note::before { content:'↖'; position:absolute; left:2px; color:var(--blue); }
.studio-help-note[hidden], .studio-help-more[hidden] { display:none; }
.studio-help-more { font-size:12.5px; margin:9px 0 0; }
.studio-help-more a { color:var(--blue); }

/* The snippet card (code mode). Deliberately built like a little file rather than like more of
   mebo's speech: a header naming the file, then the code itself on the editor's own background, in
   the editor's own font. What is being shown IS a piece of a file, and it should look like one.
   Long lines scroll inside the card — the drawer is 380px and must never push the page sideways. */
.studio-help-code {
  margin-top:12px; border-radius:12px; overflow:hidden;
  border:1px solid rgba(43,140,255,0.24); background:#080a1c;
}
.studio-help-code[hidden] { display:none; }
.studio-help-code-head {
  display:flex; align-items:center; gap:8px; padding:9px 11px;
  border-bottom:1px solid rgba(43,140,255,0.18); background:rgba(7,104,255,0.07);
}
.studio-help-code-verb { font-size:11.5px; color:var(--muted); white-space:nowrap; }
.studio-help-code-file {
  font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size:12px; color:var(--blue); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.studio-help-code-file[hidden] { display:none; }
.studio-help-code-head .ghostbtn { min-height:26px; padding:0 10px; font-size:11.5px; }
.studio-help-code-where {
  margin:0; padding:9px 12px 0; font-size:12.5px; color:var(--muted-2); line-height:1.5;
}
.studio-help-code-where[hidden] { display:none; }
.studio-help-code-body {
  margin:0; padding:11px 12px 12px; overflow-x:auto;
  font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size:12.5px; line-height:1.65; white-space:pre; tab-size:2;
}
/* The COLOUR has to land on the <code>, not the <pre> around it. The site styles `code` blue for
   inline mentions of a filename or a block name, which is right there and wrong here: a whole
   snippet in #2b8cff on the editor's near-black reads as a smudge. This is the one place `code`
   means "a listing", so it takes the editor's own foreground. */
.studio-help-code-body code { color:#e8ecf6; font:inherit; }
.studio-help-code-body[hidden] { display:none; }

/* Which lines are the change, and which are only there so you can see where it lands. The bar down
   the side does the work — the tint alone is too quiet against this background, and colour alone
   would be the only signal for somebody who cannot see it.
   The rows bleed into the <pre>'s padding so the bar sits at the card's edge, and `min-width:100%`
   with `width:max-content` keeps the tint under the whole of a line that scrolls. */
.studio-help-code-line { display:block; margin:0 -12px; padding:0 12px 0 10px; border-left:2px solid transparent; }
/* The <pre> is the scroll container, so the CODE has to be as wide as its widest line — otherwise a
   highlighted row that scrolls off ends its tint at the fold. */
.studio-help-code-body code { display:block; min-width:100%; width:max-content; }
.studio-help-code-line.is-context { opacity:0.45; }
.studio-help-code-line.is-change { background:rgba(43,140,255,0.14); border-left-color:var(--blue); }
.studio-help-code-show {
  display:block; width:calc(100% - 24px); margin:0 12px 12px; min-height:32px; font-size:12px;
}
.studio-help-code-show[hidden] { display:none; }

/* .primary pads 12/20 and .ghostbtn pads 9/15, so side by side one stands taller than the other.
   Inside the panel they are one row of equals — same height, same vertical padding. */
/* The "learn more" fold. Closed by default and quiet when closed: it is an offer, not a lesson a
   child has to get past to reach the answer. */
.studio-help-learn {
  margin-top:12px; padding:10px 13px; border-radius:12px;
  border:1px solid rgba(43,140,255,0.2); background:rgba(7,104,255,0.05);
}
.studio-help-learn[hidden] { display:none; }
.studio-help-learn summary {
  cursor:pointer; font-size:12.5px; font-weight:600; color:var(--blue); list-style:none;
}
.studio-help-learn summary::-webkit-details-marker { display:none; }
.studio-help-learn summary::before { content:'💡 '; }
.studio-help-learn summary::after { content:' ▾'; color:var(--muted); }
.studio-help-learn[open] summary::after { content:' ▴'; }
.studio-help-learn p { font-size:12.5px; color:var(--muted-2); line-height:1.6; margin:9px 0 0; }

.studio-help-actions { display:flex; align-items:stretch; gap:10px; margin-top:16px; }
.studio-help-actions .primary,
.studio-help-actions .ghostbtn {
  display:inline-flex; align-items:center; justify-content:center;
  min-height:38px; padding-top:0; padding-bottom:0; font-size:13px;
}
.studio-help-actions .iconbtn { align-self:center; }
.studio-help-rate { align-items:center; }
.studio-help-rate .studio-help-rate-q { font-size:12.5px; color:var(--muted); }
.studio-help-rate.is-hidden-rate .studio-help-rate-q,
.studio-help-rate.is-hidden-rate [data-help-rate] { display:none; }

.studio-help-foot {
  font-size:11.5px; color:var(--muted); line-height:1.5; margin:18px 0 0;
  padding-top:13px; border-top:1px solid rgba(43,140,255,0.14);
}
.studio-help-foot a { color:var(--blue); }
/* How many asks are left today. Shown before they spend one, not sprung on them at zero — a child
   who can see "3 left" saves them for what they are actually stuck on. */
.studio-help-left {
  display:inline-block; margin-right:6px; padding:2px 8px; border-radius:999px;
  font-size:11px; font-weight:600; color:var(--muted-2);
  background:rgba(43,140,255,0.12); border:1px solid rgba(43,140,255,0.25);
}
.studio-help-left[hidden] { display:none; }
.studio-help-left.is-low { color:var(--red); background:rgba(255,93,108,0.1); border-color:rgba(255,93,108,0.35); }
.studio-mebo-left-wrap { margin:0 0 14px; padding-top:0; border-top:0; }
.studio-mebo-left-wrap[hidden] { display:none; }

/* ---------------------------- mebo: the new-game wizard ----------------------------
   A centred modal, unlike the help panel: there is no workspace behind it yet, so there is nothing
   for it to cover. Borrows the help panel's cards, lead text and dots wholesale. */
.studio-mebo {
  position:relative; width:560px; max-width:100%; max-height:calc(100vh - 40px); overflow-y:auto;
  padding:22px 24px; border-radius:20px; text-align:left;
  border:1px solid rgba(43,140,255,0.32); background:linear-gradient(180deg,#0e1330,#0a0c20);
  box-shadow:0 30px 90px rgba(0,0,0,0.65),0 0 60px rgba(7,104,255,0.15); animation:wbpop .18s ease-out;
}
.studio-mebo-step[hidden] { display:none; }
.studio-mebo-spaced { margin-top:18px; }
.studio-mebo-optional { font-weight:400; font-size:12px; color:var(--muted); }

.studio-mebo-rail { display:flex; gap:6px; list-style:none; padding:0; margin:0 0 18px; }
/* `display:flex` above beats the hidden attribute, so say it again — the rail is hidden when mebo
   is resting, where there are no steps left to be part-way through. */
.studio-mebo-rail[hidden] { display:none; }
.studio-mebo-rail li { flex:1; height:4px; border-radius:2px; background:rgba(43,140,255,0.16); }
.studio-mebo-rail li.is-active, .studio-mebo-rail li.is-done { background:linear-gradient(90deg,#0768ff,#2b8cff); }

.studio-mebo textarea {
  width:100%; padding:12px 14px; border-radius:11px; font:inherit; font-size:13.5px; resize:vertical;
  color:var(--fg); background:rgba(5,3,15,0.7); border:1px solid rgba(43,140,255,0.25);
}
.studio-mebo textarea:focus {
  outline:none; border-color:rgba(43,140,255,0.7); box-shadow:0 0 0 3px rgba(43,140,255,0.15);
}
/* The chosen card in the two-part "how do you win / how do you lose" step, which does not advance
   until both halves are answered — so the first answer has to stay visible. */
.studio-help-card.is-chosen { border-color:var(--blue); background:rgba(43,140,255,0.18); }

.studio-mebo-card {
  padding:16px 18px; border-radius:14px;
  border:1px solid rgba(43,140,255,0.28); background:rgba(7,104,255,0.08);
}
.studio-mebo-card h4 { font-family:var(--f-display); font-size:18px; margin:0; color:var(--fg); }
.studio-mebo-blurb { font-size:13px; color:var(--muted-2); margin:5px 0 12px; line-height:1.5; }
.studio-mebo-card ul { margin:0; padding-left:19px; }
.studio-mebo-card li { font-size:13px; color:var(--fg); line-height:1.65; }
.studio-made-name {
  margin:10px 0 4px; font-family:var(--f-display); font-weight:700; font-size:19px; color:var(--fg);
}
.studio-made-desc { margin:0; font-size:13.5px; line-height:1.55; color:var(--muted); }
.studio-made-legend-lead {
  margin:18px 0 8px; font-size:11px; text-transform:uppercase; letter-spacing:.5px;
  font-weight:700; color:var(--muted);
}
.studio-made-legend { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:7px; }
.studio-made-row {
  display:flex; align-items:center; gap:11px; padding:8px 11px; border-radius:10px;
  background:rgba(5,3,15,0.45); border:1px solid rgba(43,140,255,0.16);
}
/* A fixed box the picture is drawn INSIDE at its real proportions, so a tall thing reads as tall
   and a small thing as small — which is the whole point of showing it rather than describing it. */
/* The same light checker the gallery uses. A dark tile hid a black tree completely, and the whole
   point of this row is that you can see which thing it is — so the backing has to work for a black
   sprite and a white one at the same time. */
.studio-made-pic {
  flex:none; width:34px; height:34px; border-radius:7px; display:flex;
  align-items:center; justify-content:center; overflow:hidden;
  background-color:#c8c8c8;
  background-image:linear-gradient(45deg,#a9a9a9 25%,transparent 25%,transparent 75%,#a9a9a9 75%),
                   linear-gradient(45deg,#a9a9a9 25%,transparent 25%,transparent 75%,#a9a9a9 75%);
  background-size:10px 10px; background-position:0 0,5px 5px;
}
.studio-made-pic img { image-rendering:pixelated; object-fit:contain; }
.studio-made-text { display:flex; flex-direction:column; gap:1px; min-width:0; flex:1; }
.studio-made-text strong { font-size:13px; color:var(--fg); }
.studio-made-job { font-size:11.5px; color:var(--muted); }
.studio-made-next {
  margin:16px 0 0; padding:12px 14px; border-radius:11px;
  background:rgba(70,224,138,0.07); border:1px solid rgba(70,224,138,0.22);
}
.studio-made-next-lead { margin:0 0 7px; font-weight:700; font-size:13px; color:#8ff0b6; }
.studio-made-next ul { margin:0; padding-left:18px; }
.studio-made-next li { font-size:12.5px; line-height:1.6; color:var(--fg); }
.studio-mebo-name {
  width:100%; padding:9px 11px; border-radius:9px; font:inherit; color:var(--fg);
  background:rgba(5,3,15,0.55); border:1px solid rgba(43,140,255,0.28);
}
.studio-mebo-name:focus {
  outline:none; border-color:rgba(43,140,255,0.7); box-shadow:0 0 0 3px rgba(43,140,255,0.15);
}
/* The three things a good idea says. Stated, not folded away: a child cannot yet write a prompt,
   and an empty box with "tell me your idea" over it teaches them nothing. */
.studio-mebo-recipe {
  margin:0 0 9px; padding:9px 12px 9px 26px; border-radius:9px;
  background:rgba(43,140,255,0.06); border:1px solid rgba(43,140,255,0.16);
}
.studio-mebo-recipe li { font-size:12.5px; line-height:1.65; color:var(--muted); }
.studio-mebo-recipe strong { color:var(--fg); }
.studio-mebo-eg-box { margin-top:14px; }
.studio-mebo-eg-lead { margin:0 0 6px; font-size:12px; color:var(--muted); }
.studio-mebo-eg-why { display:flex; flex-direction:column; gap:2px; margin:7px 0 0; }
.studio-mebo-eg-why span { font-size:11.5px; color:var(--muted); }
.studio-mebo-eg-why em { color:#8ff0b6; font-style:normal; font-weight:600; }
.studio-mebo-eg-tap { margin:7px 0 0; font-size:11.5px; color:var(--muted-2); }
/* The same lesson by demonstration — tap one, then change it into your own. */
.studio-mebo-eg {
  display:block; width:100%; text-align:left; font:inherit; font-size:12.5px; line-height:1.45;
  color:var(--fg); padding:9px 12px; border-radius:9px; cursor:pointer;
  background:rgba(5,3,15,0.4); border:1px dashed rgba(43,140,255,0.3);
}
.studio-mebo-eg:hover { border-color:rgba(43,140,255,0.65); background:rgba(43,140,255,0.08); }
.studio-mebo-else-label { display:block; margin:14px 0 6px; font-size:12px; color:var(--muted); }
.studio-mebo-else { display:flex; gap:8px; }
.studio-mebo-else input {
  flex:1; padding:8px 11px; border-radius:9px; font:inherit; font-size:13px; color:var(--fg);
  background:rgba(5,3,15,0.55); border:1px solid rgba(43,140,255,0.28);
}
.studio-mebo-else input:focus {
  outline:none; border-color:rgba(43,140,255,0.7); box-shadow:0 0 0 3px rgba(43,140,255,0.15);
}
.studio-mebo-resting-note { font-size:13px; line-height:1.55; color:var(--muted); margin:8px 0 16px; }
.studio-mebo-art { font-size:12px; color:var(--muted); margin:12px 0 0; }
/* What mebo could not build. Amber, not red: this is honesty about the starting point, not an
   error — a child should read it and still press Build it. */
.studio-mebo-cannot {
  margin:12px 0 0; padding:10px 12px; border-radius:10px;
  background:rgba(255,176,32,0.08); border:1px solid rgba(255,176,32,0.28);
}
.studio-mebo-cannot-lead { margin:0 0 6px; font-size:12.5px; font-weight:700; color:#ffce70; }
.studio-mebo-cannot ul { margin:0; padding-left:18px; }
.studio-mebo-cannot li { font-size:12.5px; line-height:1.5; color:var(--fg); }
.studio-mebo-cannot-foot { margin:7px 0 0; font-size:12px; color:var(--muted); }
/* When the ask was a whole genre away, this is the headline rather than the footnote. */
.studio-mebo-cannot.is-big { background:rgba(255,176,32,0.13); border-color:rgba(255,176,32,0.45); }
.studio-mebo-after { font-size:12.5px; color:var(--muted); line-height:1.5; margin:13px 0 0; }

/* The first-run card that starts all this. mebo's face instead of an emoji, because he is a
   character the child is about to work with rather than a category of thing. */
.starter-card .starter-icon img { display:block; width:34px; height:auto; }

@media (max-width:560px) {
  .studio-help-cards { grid-template-columns:1fr; }
  .studio-help-actions { flex-wrap:wrap; }
}

/* ============================ responsive ============================
   The EDITOR does not reflow — it has a fixed 1040px floor and scrolls sideways below it (see the
   small-screens section above). So nothing here touches the toolbar, the panes or .studio-body:
   the old rules that collapsed them into one column at ≤1023px are exactly what made the file tree
   fill the screen (block layout, and the view-tab toggle only ever hid the blocks/code panes,
   never the files pane). What remains is for things that genuinely ARE viewport-responsive: the
   first-run / template screens (ordinary pages), and the fixed-position overlays and dialogs, none
   of which are inside the editor's scroll region. */
@media (max-width:640px) {
  .workspace:has(#tab-studio:not([hidden]) #studio-editor[hidden]) { padding:16px 14px 0; }
  .starter-grid { grid-template-columns:1fr; }
  .studio-drawer { width:100%; }
  .studio-run-controls .ghostbtn, .studio-run-controls .primary { flex:1; }
}
@media (max-width:520px) {
  .studio-assets { padding:14px; }
  .sprite-new { flex-direction:column; align-items:flex-start; gap:12px; }
  .studio-rollback { padding:20px; }
  .studio-rollback-actions { flex-direction:column-reverse; }
  .studio-rollback-actions > * { width:100%; }
}

/* ============================ focus + motion ============================
   Every interactive element gets a visible ring (the mockup had none). */
#tab-studio :focus-visible { outline:2px solid var(--blue); outline-offset:2px; }
#tab-studio .studio-name:focus-visible, #tab-studio .sprite-name:focus-visible { outline-offset:0; }
.studio-divider:focus-visible span { background:var(--blue); height:76px; }

@media (prefers-reduced-motion: reduce) {
  .studio-invalid-block { animation:none; filter:drop-shadow(0 0 7px rgba(255,93,108,0.9)); }
  .studio-drawer, .studio-overlay, .studio-rollback, .starter-card { animation:none; }
  .pill.is-running::before, .studio-savestate.is-saving .dot { animation:none; }
  /* No fade — it simply appears and is hidden again on the same timer by studio.js. */
  .studio-autoversion { animation:none; }
  .studio-divider span, .studio-divider:hover span { transition:none; }
}

/* Deleting a saved version is the one destructive thing in the history drawer, so it reads red —
   restoring is safe (it makes a recovery point), this is not. */
.studio-rollback-icon.is-danger {
  background:rgba(255,93,108,0.12); border-color:rgba(255,93,108,0.35); color:var(--red);
}
.version-del { width:30px; height:30px; font-size:13px; }
.iconbtn.danger { border-color:rgba(255,93,108,0.3); color:var(--red); }
.iconbtn.danger:hover:not(:disabled) {
  color:var(--red); border-color:rgba(255,93,108,0.6); background:rgba(255,93,108,0.1);
}

/* Asset thumbnails render an <img>, not a background — without this a 16x16 sprite draws at its
   natural size in the corner of the tile instead of filling it. Pixelated so small art scales up
   crisp rather than blurred. */
.sprite-state-thumb, .asset-row-thumb { display:flex; align-items:center; justify-content:center; overflow:hidden; }
.sprite-state-thumb img, .asset-row-thumb img {
  width:100%; height:100%; object-fit:contain; image-rendering:pixelated; padding:12%;
}

/* .workspace sets z-index:1, which creates a stacking context — so the now-fixed overlays are
   trapped inside it and paint UNDER the app bar (z-index:40), hiding the run dialog's title bar.
   Their own z-index can't escape an ancestor's context, so lift the workspace itself, and only
   while one is actually open. */
.workspace:has(.studio-overlay:not([hidden])),
.workspace:has(.studio-modal-wrap:not([hidden])),
.workspace:has(.studio-drawer-wrap:not([hidden])) { z-index:50; }
