/* Turtle Blocks — friendly, fluid workspace UI for kids.
   Sections: tokens · base · toolbar · file menu · layout · stage ·
   palette · script strip · runbar · blocks · containers · drag & run states ·
   dialogs · toasts · trash + mobile chrome · responsive · accessibility */

/* ============ design tokens ============ */

:root {
  --bg: #f2f5fa;            /* soft paper behind everything */
  --panel: #ffffff;
  --ink: #253044;
  --muted: #5b6b81;         /* >= 4.5:1 on white */
  --line: #dbe3ee;
  --soft-line: #e9eef6;
  --accent: #10b981;
  --accent-dark: #047857;   /* white text on this passes 4.5:1 */
  --danger: #dc2626;

  /* category hues — kids learn color -> category, keep the meanings */
  --turtle: #2563eb;     --turtle-dark: #1d4ed8;     --turtle-tint: #eff6ff;     --turtle-text: #1d4ed8;
  --ai: #4f46e5;         --ai-dark: #3730a3;         --ai-tint: #eef2ff;         --ai-text: #3730a3;
  --sound: #c2410c;      --sound-dark: #9a3412;      --sound-tint: #fff7ed;      --sound-text: #9a3412;
  --math: #059669;       --math-dark: #047857;       --math-tint: #ecfdf5;       --math-text: #065f46;
  --condition: #7c3aed;  --condition-dark: #6d28d9;  --condition-tint: #f5f3ff;  --condition-text: #6d28d9;
  --loops: #f59e0b;      --loops-dark: #d97706;      --loops-tint: #fffbeb;      --loops-text: #92400e;
  --variables: #0ea5e9;  --variables-dark: #0284c7;  --variables-tint: #f0f9ff;  --variables-text: #075985;
  --functions: #db2777;  --functions-dark: #be185d;  --functions-tint: #fdf2f8;  --functions-text: #be185d;

  --radius-lg: 12px;
  --radius: 10px;
  --radius-sm: 8px;

  --strip-bg: #eef2f8;      /* the strip surface — block notches must match it */

  /* Give the program workspace priority: it is where students build and edit. */
  --toolbox-w: 240px;
  --script-w: 560px;
  --resize-handle-w: 10px;

  /* Stacked layouts (phone, tablet) put the stage under the workspace and let
     the divider between them be dragged. JS overrides this with a pixel value
     derived from a stored ratio; the default has to be sane on its own or the
     first paint - before any script runs - collapses the stage to nothing. */
  --stage-h: 38dvh;
  --resize-handle-h: 16px;

  --shadow-soft: 0 1px 4px rgba(37, 48, 68, .05), 0 8px 22px rgba(37, 48, 68, .07);
  --shadow-pop: 0 14px 44px rgba(37, 48, 68, .2);

  --font-base: clamp(14px, 13px + 0.3vw, 15.5px);
}

/* ============ base ============ */

* { box-sizing: border-box; }

[hidden] { display: none !important; }

.sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

.skip-link {
  position: fixed;
  top: 8px;
  left: 12px;
  z-index: 200;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  background: var(--ink);
  color: #fff;
  font-weight: 800;
  text-decoration: none;
  transform: translateY(calc(-100% - 20px));
  transition: transform .15s ease;
}
.skip-link:focus { transform: translateY(0); }

html, body {
  height: 100%;
  width: 100%;
  overflow-x: hidden;
}

body {
  margin: 0;
  font-family: 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', sans-serif;
  font-size: var(--font-base);
  background: var(--bg);
  color: var(--ink);
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

button { font: inherit; cursor: pointer; }

summary { list-style: none; cursor: pointer; }
summary::-webkit-details-marker { display: none; }

/* ============ toolbar ============ */

.toolbar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(8px, 1.5vw, 16px);
  padding: clamp(8px, 1vw, 10px) clamp(10px, 2vw, 20px);
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 2px 10px rgba(37, 48, 68, .05);
  z-index: 30;
}

.toolbar-group { display: flex; align-items: center; gap: clamp(6px, 1vw, 10px); }

.brand { min-width: 0; }
.brand-turtle {
  --turtle-angle: 0deg;
  --head-x: 0px;
  --head-y: 0px;
  width: 46px;
  height: 42px;
  flex: none;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.brand-turtle-svg {
  width: 40px;
  height: 40px;
  overflow: visible;
  filter: drop-shadow(0 2px 2px rgba(37, 48, 68, .16));
}
.brand-turtle-art {
  transform-box: view-box;
  transform-origin: 26px 26px;
  transform: translate(var(--head-x), var(--head-y)) rotate(var(--turtle-angle));
  transition: transform 90ms ease-out;
}
.mascot-face {
  fill: #7bc747;
  stroke: #37863b;
  stroke-width: 1.8;
}
.mascot-muzzle {
  fill: #a8dc6d;
  opacity: .92;
}
.mascot-scale {
  fill: #5bad3b;
  opacity: .72;
}
.mascot-eye {
  transform-box: fill-box;
  transform-origin: center;
}
.mascot-eye-white { fill: #fff; stroke: #2f6f36; stroke-width: .8; }
.mascot-pupil {
  fill: #172033;
  transform: translate(var(--pupil-x, 0px), var(--pupil-y, 0px));
  transition: transform 70ms ease-out;
}
.mascot-smile {
  fill: none;
  stroke: #2f6f36;
  stroke-width: 1.35;
  stroke-linecap: round;
}
.mascot-nostril { fill: #3b7f38; }
.brand-turtle:hover .mascot-face { fill: #83cf4d; }
.brand-turtle:active .brand-turtle-svg { transform: scale(.96); }
.brand-turtle:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 1px;
  border-radius: 50%;
}
.brand-turtle.is-blinking .mascot-eye { animation: mascot-blink .34s ease-in-out; }

@keyframes mascot-blink {
  0%, 32%, 72%, 100% { scale: 1 1; }
  46%, 58% { scale: 1 .08; }
}

.brand-text { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.brand-text strong {
  font-size: clamp(15px, 1.5vw, 17px);
  letter-spacing: -.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#program-name {
  font-size: 12.5px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 1px solid var(--line);
  background: #fbfcfe;
  color: var(--ink);
  border-radius: 12px;
  min-height: 44px;
  padding: 8px clamp(12px, 1.5vw, 16px);
  font-weight: 700;
  font-size: 14.5px;
  transition: background .15s, transform .05s, box-shadow .15s;
}
.btn:hover { background: var(--bg); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: default; transform: none; }

.btn-run {
  min-width: 100px;
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  box-shadow: 0 3px 10px rgba(16, 185, 129, .35);
}
.btn-run:hover:not(:disabled) { background: #0da975; }

.btn-stop {
  background: #fff1f2;
  border-color: #fecdd3;
  color: var(--danger);
}
.btn-stop:hover:not(:disabled) { background: #ffe4e6; }

.btn-ghost { background: transparent; }
.btn-small { min-height: 36px; padding: 5px 12px; font-size: 13px; border-radius: var(--radius-sm); }

.btn-examples {
  background: var(--loops-tint);
  border-color: #fcd34d;
  color: var(--loops-text);
}
.btn-examples:hover { background: #fef3c7; }

.btn-help {
  width: 44px;
  padding-inline: 0;
  border-radius: 50%;
}
.btn-help > span:first-child {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #e8eef7;
  color: #334155;
  font-weight: 900;
}
.help-label { display: none; }

/* ============ file menu (pure-HTML <details> dropdown) ============ */

.file-menu { position: relative; }

.file-menu-btn { display: inline-flex; align-items: center; gap: 7px; }
.menu-caret { font-size: 11px; color: var(--muted); transition: transform .15s; }
.file-menu[open] .menu-caret { transform: rotate(180deg); }
.file-menu[open] > .file-menu-btn { background: var(--bg); }

.file-menu-list {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  min-width: 200px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
  z-index: 60;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 8px 12px;
  border: none;
  background: transparent;
  border-radius: var(--radius-sm);
  font-weight: 650;
  font-size: 14.5px;
  color: var(--ink);
  text-align: left;
}
.menu-item:hover { background: var(--bg); }
.menu-icon { width: 22px; text-align: center; font-size: 16px; }
.menu-separator { height: 1px; margin: 5px 8px; background: var(--line); }

/* ============ workspace layout ============ */

.workbench {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns:
    clamp(210px, var(--toolbox-w), 380px)
    var(--resize-handle-w)
    clamp(280px, var(--script-w), 760px)
    var(--resize-handle-w)
    minmax(0, 1fr);
  overflow: hidden;
}

.toolbox {
  grid-column: 1;
  min-height: 0;
  background: #f7f9fc;
  overflow-y: auto;
  padding: clamp(8px, 1.1vw, 12px);
}

.resize-handle {
  position: relative;
  min-width: var(--resize-handle-w);
  background: #f7f9fc;
  border-inline: 1px solid transparent;
  cursor: col-resize;
  touch-action: none;
  z-index: 12;
}

.resize-handle::before {
  content: '';
  position: absolute;
  top: 14px;
  bottom: 14px;
  left: 50%;
  width: 2px;
  border-radius: 999px;
  background: #cbd5e1;
  transform: translateX(-50%);
  opacity: .65;
  transition: width .14s, background .14s, opacity .14s;
}

.resize-handle::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 4px;
  height: 34px;
  border-radius: 999px;
  background: linear-gradient(#94a3b8 20%, transparent 20% 40%, #94a3b8 40% 60%, transparent 60% 80%, #94a3b8 80%);
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity .14s;
}

.resize-handle:hover::before,
.resize-handle:focus-visible::before,
.resize-handle.dragging::before {
  width: 4px;
  background: var(--accent);
  opacity: 1;
}

.resize-handle:hover::after,
.resize-handle:focus-visible::after,
.resize-handle.dragging::after {
  opacity: .9;
}

.resize-handle-toolbox { grid-column: 2; }
.resize-handle-script { grid-column: 4; }

body.resizing-panels {
  cursor: col-resize;
  user-select: none;
}

.script-panel {
  grid-column: 3;
  position: relative;
  min-width: 0;
  min-height: 0;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 9px;
  padding: clamp(8px, 1.1vw, 12px);
  background: var(--panel);
  overflow: hidden;
}

.workspace-zoom-controls {
  position: absolute;
  right: 14px;
  bottom: 14px;
  z-index: 8;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.workspace-zoom-btn {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 2px solid #d1d5db;
  border-radius: 50%;
  background: rgba(255, 255, 255, .94);
  color: #718096;
  box-shadow: 0 2px 5px rgba(37, 48, 68, .1);
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.workspace-zoom-btn svg {
  width: 25px;
  height: 25px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.workspace-zoom-btn:hover:not(:disabled) {
  border-color: #aeb8c5;
  background: #fff;
  color: #475569;
  box-shadow: 0 4px 10px rgba(37, 48, 68, .14);
}

.workspace-zoom-btn:disabled {
  opacity: .42;
  cursor: default;
}

/* ============ stage / canvas ============ */

.stage {
  grid-column: 5;
  position: relative;
  min-height: 0;
  display: flex;
  align-items: stretch;
  justify-content: stretch;
  padding: 0;
  overflow: hidden;
  background: #fff;
}

.stage-chrome {
  position: absolute;
  top: 12px;
  left: 12px;
  right: 12px;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  pointer-events: none;
}

.stage-title,
.stage-action {
  min-height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 1px solid rgba(203, 213, 225, .82);
  border-radius: 999px;
  background: rgba(255, 255, 255, .88);
  color: #475569;
  box-shadow: 0 3px 12px rgba(37, 48, 68, .1);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  pointer-events: auto;
}

.stage-title {
  padding: 0 12px;
  font-size: 12px;
  font-weight: 850;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.stage-action {
  width: 38px;
  padding: 0;
  font: inherit;
  font-size: 18px;
  cursor: pointer;
}
.stage-action:hover { background: #fff; color: var(--accent-dark); }

.stage:fullscreen {
  width: 100vw;
  height: 100vh;
  background: #fff;
}
.stage:fullscreen .stage-chrome { top: max(16px, env(safe-area-inset-top)); }
.stage:fullscreen .stage-action {
  border-color: rgba(220, 38, 38, .42);
  background: rgba(239, 68, 68, .14);
  color: #dc2626;
  box-shadow: 0 4px 16px rgba(185, 28, 28, .13);
}
.stage:fullscreen .stage-action:hover {
  border-color: rgba(220, 38, 38, .6);
  background: rgba(239, 68, 68, .23);
  color: #b91c1c;
}

/* Always on the stage, docked or full screen: the view is sticky across runs
   (`world.reset()` deliberately leaves zoom and pan alone), so a learner who
   zooms in needs a way back that does not depend on entering full screen. */
.stage-zoom-controls {
  position: absolute;
  right: max(18px, env(safe-area-inset-right));
  bottom: max(18px, env(safe-area-inset-bottom));
  z-index: 6;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid rgba(148, 163, 184, .48);
  border-radius: 14px;
  background: rgba(255, 255, 255, .78);
  box-shadow: 0 8px 26px rgba(30, 41, 59, .16);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.stage-zoom-btn {
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: #334155;
  font: 800 24px/1 ui-rounded, 'Arial Rounded MT Bold', system-ui, sans-serif;
  cursor: pointer;
}
.stage-zoom-btn + .stage-zoom-btn { border-top: 1px solid rgba(148, 163, 184, .38); }
.stage-zoom-btn:hover:not(:disabled) { background: rgba(226, 232, 240, .72); color: #0f172a; }
.stage-zoom-btn:disabled { color: #a8b2c1; cursor: default; }

.canvas-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  min-width: 0;
  background: #ffffff;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  overflow: hidden;
  /* The drag pans the drawing, so the browser must not read it as a scroll
     or a pinch first - without this a touch drag never reaches pointermove. */
  touch-action: none;
  cursor: grab;
}

.canvas-wrap.is-panning {
  cursor: grabbing;
}

.canvas-wrap canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* ============ palette ============ */

.toolbox-discovery {
  position: sticky;
  top: -4px;
  z-index: 10;
  margin: -4px -4px 10px;
  padding: 4px 4px 9px;
  background: linear-gradient(180deg, rgba(247, 249, 252, .98) 78%, rgba(247, 249, 252, 0));
}

.block-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.block-search {
  width: 100%;
  min-height: 44px;
  padding: 9px 64px 9px 39px;
  border: 1px solid #cbd5e1;
  border-radius: 12px;
  background: rgba(255, 255, 255, .96);
  color: var(--ink);
  font: inherit;
  font-size: 13.5px;
  font-weight: 650;
  box-shadow: 0 2px 8px rgba(37, 48, 68, .06);
  outline: none;
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.block-search::placeholder { color: #718096; font-weight: 550; }
.block-search::-webkit-search-cancel-button { display: none; }
.block-search:focus {
  border-color: #2563eb;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .16), 0 5px 14px rgba(37, 48, 68, .09);
}

.block-search-icon {
  position: absolute;
  left: 13px;
  z-index: 1;
  color: #64748b;
  font-size: 20px;
  font-weight: 800;
  line-height: 1;
  pointer-events: none;
}

.block-search-clear {
  position: absolute;
  right: 37px;
  z-index: 1;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: #e7edf5;
  color: #475569;
  font: inherit;
  font-size: 19px;
  line-height: 1;
}
.block-search-clear:hover { background: #dbe4ef; color: var(--ink); }

.search-shortcut {
  position: absolute;
  right: 10px;
  min-width: 22px;
  min-height: 23px;
  color: #64748b;
  pointer-events: none;
}
.block-search-wrap:focus-within .search-shortcut,
.block-search-wrap:has(.block-search:not(:placeholder-shown)) .search-shortcut { opacity: 0; }

.palette.is-filtering .palette-section,
.palette.is-filtering .palette-group,
.palette.is-filtering .chip {
  animation: search-result-in .16s ease-out;
}

@keyframes search-result-in {
  from { opacity: .35; transform: translateY(2px); }
  to { opacity: 1; transform: translateY(0); }
}

.palette-search-empty {
  min-height: 210px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 24px 16px;
  border: 1px dashed #b8c5d6;
  border-radius: var(--radius);
  background: rgba(255, 255, 255, .7);
  color: var(--muted);
  text-align: center;
}
.palette-search-empty strong { color: var(--ink); font-size: 14.5px; }
.palette-search-empty > span:not(.palette-empty-icon) { max-width: 210px; font-size: 12px; line-height: 1.45; }
.palette-empty-icon { font-size: 30px; filter: grayscale(.2); }
.palette-search-empty .btn { margin-top: 5px; background: #fff; }

.palette {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.palette-section {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(37, 48, 68, .04);
}

.palette-section-title {
  min-height: 42px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 12px;
  color: var(--ink);
  font-size: 14px;
  font-weight: 800;
}

.palette-section-title::after,
.palette-label::after {
  content: '▾';
  font-size: 11px;
  color: var(--muted);
}

.palette-section:not([open]) .palette-section-title::after,
.palette-group:not([open]) .palette-label::after {
  content: '▸';
}

.palette-group {
  display: block;
  border-top: 1px solid var(--soft-line);
}

.palette-label {
  min-height: 34px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 12px;
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .03em;
  color: var(--muted);
}

/* A palette entry that opens a website rather than adding a block. It sits at
   the same level as a group header so it reads as a peer of "Camera", but it
   carries an outbound arrow instead of a disclosure caret, because one click
   leaves the app rather than expanding anything. */
.palette-link {
  min-height: 34px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0 12px;
  border-top: 1px solid var(--soft-line);
  color: #6d28d9;
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .03em;
  text-decoration: none;
  cursor: pointer;
  transition: color .15s ease, background-color .15s ease;
}

.palette-link:hover,
.palette-link:focus-visible {
  background: rgba(109, 40, 217, .1);
  color: #4c1d95;
  text-decoration: none;
}

.palette-link:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: -3px;
  border-radius: 8px;
}

.palette-link-arrow {
  width: 18px;
  text-align: center;
  font-size: 11px;
}

@media (prefers-reduced-motion: reduce) {
  .palette-link { transition: none; }
}

.palette-chips {
  display: grid;
  gap: 5px;
  padding: 2px 7px 8px;
}

.chip {
  --chip-text: var(--ink);
  --chip-edge: rgba(37, 48, 68, .1);
  position: relative;
  min-height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  border-radius: 9px;
  padding: 5px 9px;
  font-family: "Nunito", "Segoe UI", system-ui, sans-serif;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: .005em;
  border: 1px solid var(--chip-edge);
  cursor: grab;
  user-select: none;
  color: var(--chip-text);
  text-shadow: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .65),
    inset 0 -1px 0 rgba(37, 48, 68, .08),
    0 2px 6px rgba(37, 48, 68, .08);
  transition: transform .1s, box-shadow .1s, background .15s, filter .15s;
}
.chip > span:last-child {
  line-height: 1.2;
  text-wrap: pretty;
}
.chip:hover {
  transform: translateY(-1px);
  filter: brightness(1.01);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .72),
    inset 0 -1px 0 rgba(37, 48, 68, .08),
    0 4px 10px rgba(37, 48, 68, .1);
}
.chip:active { cursor: grabbing; }
.chip-icon { width: 20px; font-size: 17px; text-align: center; flex: none; }

/* Default category palette. */
.chip.cat-turtle { --chip-text: #1e40af; --chip-edge: rgba(37, 99, 235, .28); background: linear-gradient(180deg, #eff6ff 0%, #bfdbfe 100%); }
.chip.cat-design { --chip-text: #115e59; --chip-edge: rgba(13, 148, 136, .3); background: linear-gradient(180deg, #f0fdfa 0%, #99f6e4 100%); }
.chip.cat-ai { --chip-text: #3730a3; --chip-edge: rgba(79, 70, 229, .28); background: linear-gradient(180deg, #eef2ff 0%, #c7d2fe 100%); }
.chip.cat-sound { --chip-text: #9a3412; --chip-edge: rgba(194, 65, 12, .3); background: linear-gradient(180deg, #fff7ed 0%, #fed7aa 100%); }
.chip.cat-math { --chip-text: #065f46; --chip-edge: rgba(5, 150, 105, .28); background: linear-gradient(180deg, #ecfdf5 0%, #bbf7d0 100%); }
.chip.cat-condition { --chip-text: #5b21b6; --chip-edge: rgba(124, 58, 237, .26); background: linear-gradient(180deg, #f5f3ff 0%, #ddd6fe 100%); }
.chip.cat-loops { --chip-text: #78350f; --chip-edge: rgba(245, 158, 11, .32); background: linear-gradient(180deg, #fffbeb 0%, #fde68a 100%); }
.chip.cat-variables { --chip-text: #155e75; --chip-edge: rgba(14, 165, 233, .28); background: linear-gradient(180deg, #ecfeff 0%, #a5f3fc 100%); }
.chip.cat-functions { --chip-text: #831843; --chip-edge: rgba(219, 39, 119, .26); background: linear-gradient(180deg, #fdf2f8 0%, #fbcfe8 100%); }

/* ============ script strip ============ */

.strip-row {
  position: relative;
  width: 100%;
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  overflow: hidden;
}

.strip-start {
  flex: none;
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: 7px;
  min-height: 28px;
  padding: 0 12px;
  border: 0;
  border-radius: 999px;
  background: var(--accent-dark);
  color: #fff;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .05em;
  text-transform: uppercase;
  cursor: grab;
  user-select: none;
  box-shadow: 0 1px 3px rgba(37, 48, 68, .16);
}
.strip-start:active { cursor: grabbing; }

.strip {
  flex: 1;
  display: block;
  position: relative;
  min-height: 0;
  min-width: 0;
  width: 100%;
  padding: 0;
  border-radius: var(--radius-sm);
  background:
    linear-gradient(rgba(37, 48, 68, .035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(37, 48, 68, .035) 1px, transparent 1px),
    var(--strip-bg);
  background-size: 28px 28px;
  border: 2px dashed #c6d2e2;
  overflow-x: auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
}

.workspace-surface {
  position: relative;
  min-width: 100%;
  min-height: 100%;
}

.workspace-surface.is-empty::after {
  content: 'Drag blocks here - or tap one in the toolbox';
  position: absolute;
  left: 18px;
  top: 18px;
  color: var(--muted);
  font-size: 14.5px;
  font-weight: 600;
  padding: 8px 6px;
  pointer-events: none;
}

.script-stack {
  position: absolute;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: max-content;
  max-width: min(92%, 420px);
  box-sizing: border-box;
  touch-action: none;
}

.script-stack.stack-dragging {
  z-index: 30;
  filter: drop-shadow(0 12px 24px rgba(37, 48, 68, .22));
}

.start-hat {
  --turtle-color: var(--accent);
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 31px;
  padding: 0 13px 0 11px;
  border-radius: 16px 16px 8px 8px;
  background: linear-gradient(180deg, var(--turtle-color), #047857);
  color: #fff;
  font-size: 12px;
  font-weight: 850;
  letter-spacing: .04em;
  text-transform: uppercase;
  cursor: grab;
  user-select: none;
  box-shadow: 0 1px 4px rgba(37, 48, 68, .18);
}
.start-hat:active { cursor: grabbing; }

.start-remove {
  position: relative;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  margin-left: 2px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .24);
  color: #fff;
  font: inherit;
  font-size: 11px;
  font-weight: 900;
  line-height: 1;
  cursor: pointer;
  opacity: .8;
}

.start-remove:hover,
.start-remove:focus-visible {
  opacity: 1;
  background: rgba(255, 255, 255, .42);
}

.start-play {
  display: grid;
  place-items: center;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .22);
  font-size: 10px;
}

.turtle-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .45);
  opacity: .95;
}

.stack-drag-grip {
  position: relative;
  width: 34px;
  height: 16px;
  margin: 0 0 -1px 12px;
  border: 0;
  border-radius: 8px 8px 3px 3px;
  background: #cbd5e1;
  color: #64748b;
  font-size: 10px;
  font-weight: 900;
  line-height: 1;
  cursor: grab;
}
.stack-drag-grip:active { cursor: grabbing; }

.stack-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 54px;
  min-height: 16px;
}

.script-stack.has-hat .stack-body:empty {
  min-width: 156px;
  min-height: 35px;
  border: 2px dashed rgba(16, 185, 129, .28);
  border-radius: 0 9px 9px 9px;
  background: rgba(255, 255, 255, .34);
}

/* The bar drawn at the seam a drop will land on. Positioned in viewport
   coordinates from getBoundingClientRect, so it sits on <body> rather than
   inside the scrolling, zoomable workspace. */
.insert-mark {
  position: fixed;
  z-index: 1200;
  height: 5px;
  margin-top: -3px;
  border-radius: 999px;
  background: #10b981;
  box-shadow: 0 0 0 2px rgba(16, 185, 129, .22), 0 3px 10px rgba(16, 185, 129, .42);
  pointer-events: none;
  opacity: 0;
  transition: opacity .09s linear, top .09s ease-out, left .09s ease-out;
}

.insert-mark.is-visible { opacity: 1; }

/* A seam can be crossed several times a second while a block is hunting for
   its place, and sliding the bar to each one turns that into a smear. */
@media (prefers-reduced-motion: reduce) {
  .insert-mark { transition: none; }
}

.palette-drag-ghost {
  position: fixed;
  z-index: 1000;
  pointer-events: none;
  opacity: .9;
  transform: rotate(-1deg);
  box-shadow: 0 12px 28px rgba(37, 48, 68, .24);
}

/* ============ runbar ============ */

.runbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  position: sticky;
  bottom: 0;
  z-index: 6;
  padding: 8px;
  background: #fbfcfe;
  border: 1px solid var(--soft-line);
  border-radius: var(--radius);
}

.run-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  margin-left: auto;
}

/* Run and Stop are never both useful - whichever does not apply is a dead,
   greyed-out button holding ~110px, which is what pushed this bar onto a
   second row. Swap them in place; setRunning() still keeps both `disabled`. */
body:not(.running) #stop-btn { display: none; }
body.running #run-btn { display: none; }

.runbar { column-gap: 6px; }
.run-actions .btn { padding: 8px 11px; }
.btn-run { min-width: 0; }

.history-actions {
  flex: none;
  display: inline-flex;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel);
}
.history-btn {
  width: 39px;
  min-height: 42px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-size: 21px;
  line-height: 1;
}
.history-btn + .history-btn { border-left: 1px solid var(--line); }
.history-btn:hover:not(:disabled) { background: var(--bg); color: var(--accent-dark); }
.history-btn:disabled { opacity: .34; cursor: default; }

.run-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 28px;
  max-width: 132px;
  padding: 0 9px;
  border-radius: 999px;
  background: #eef2f7;
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 800;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.run-status::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #94a3b8;
}
body.running .run-status {
  background: #ecfdf5;
  color: var(--accent-dark);
}
body.running .run-status::before {
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(16, 185, 129, .14);
}

/* The slider was the bar's only uncapped grower, so it swallowed every spare
   pixel (266px at the default panel) while refusing to yield below 150. */
.speed-control {
  flex: 1 1 80px;
  min-width: 80px;
  max-width: 200px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  min-height: 44px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
}
.speed-control input[type="range"] { width: 100%; accent-color: var(--accent); cursor: pointer; }
#speed-face { width: 20px; font-size: 17px; text-align: center; }

/* ============ blocks ============ */

.block {
  --block-top: #2563eb;
  --block-mid: #2563eb;
  --block-bottom: #1d4ed8;
  --block-text: #ffffff;
  --block-shadow: rgba(29, 78, 216, .24);
  --block-edge: rgba(29, 78, 216, .55);
  --block-accent: #2563eb;
  --block-ring: rgba(37, 99, 235, .2);
  position: relative;
  flex: none;
  width: fit-content;
  max-width: min(100%, 380px);
  border: 1px solid var(--block-edge);
  border-bottom-width: 2px;
  border-radius: 7px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .06), transparent 36%),
    linear-gradient(180deg, var(--block-top) 0%, var(--block-mid) 58%, var(--block-bottom) 100%);
  color: var(--block-text);
  cursor: grab;
  user-select: none;
  text-shadow: 0 1px 1px rgba(37, 48, 68, .2);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .8),
    inset 0 -2px 0 rgba(37, 48, 68, .07),
    0 2px 0 rgba(37, 48, 68, .05),
    0 4px 10px var(--block-shadow);
  margin-bottom: 0;
  transition: filter .14s, box-shadow .14s, transform .08s;
}

.block:hover {
  filter: brightness(1.015);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .84),
    inset 0 -2px 0 rgba(37, 48, 68, .07),
    0 2px 0 rgba(37, 48, 68, .05),
    0 6px 14px var(--block-shadow);
}

.stack-body > .block.stack-start:not(:first-child),
.container-body.repeat-body > .block.stack-start:not(:first-child) {
  margin-top: 22px;
}

.stack-body > .block:not(:first-child),
.container-body.repeat-body > .block:not(.stack-start),
.drag-stack > .block:not(.stack-start) {
  margin-top: -1px;
}

.block.cat-turtle {
  --block-top: #2563eb;
  --block-mid: #2563eb;
  --block-bottom: #1d4ed8;
  --block-text: #ffffff;
  --block-shadow: rgba(29, 78, 216, .24);
  --block-edge: rgba(29, 78, 216, .55);
  --block-accent: #2563eb;
  --block-ring: rgba(37, 99, 235, .2);
}
.block.cat-design {
  --block-top: #0f766e;
  --block-mid: #0f766e;
  --block-bottom: #115e59;
  --block-text: #ffffff;
  --block-subtle: rgba(240, 253, 250, .92);
  --block-edge: rgba(15, 118, 110, .58);
  --block-accent: #0d9488;
  --block-ring: rgba(13, 148, 136, .2);
}
.block.cat-ai {
  --block-top: #4f46e5;
  --block-mid: #4f46e5;
  --block-bottom: #3730a3;
  --block-text: #ffffff;
  --block-shadow: rgba(55, 48, 163, .24);
  --block-edge: rgba(49, 46, 129, .58);
  --block-accent: #4f46e5;
  --block-ring: rgba(79, 70, 229, .2);
}
.block.cat-sound {
  --block-top: #c2410c;
  --block-mid: #c2410c;
  --block-bottom: #9a3412;
  --block-text: #ffffff;
  --block-shadow: rgba(154, 52, 18, .24);
  --block-edge: rgba(124, 45, 18, .58);
  --block-accent: #c2410c;
  --block-ring: rgba(194, 65, 12, .2);
}
.block.cat-math {
  --block-top: #047857;
  --block-mid: #047857;
  --block-bottom: #065f46;
  --block-text: #ffffff;
  --block-shadow: rgba(4, 120, 87, .22);
  --block-edge: rgba(4, 120, 87, .55);
  --block-accent: #059669;
  --block-ring: rgba(5, 150, 105, .2);
}
.block.cat-condition {
  --block-top: #7c3aed;
  --block-mid: #7c3aed;
  --block-bottom: #6d28d9;
  --block-text: #ffffff;
  --block-shadow: rgba(109, 40, 217, .22);
  --block-edge: rgba(109, 40, 217, .55);
  --block-accent: #7c3aed;
  --block-ring: rgba(124, 58, 237, .2);
}
.block.cat-loops {
  --block-top: #f59e0b;
  --block-mid: #f59e0b;
  --block-bottom: #d97706;
  --block-text: #4a2500;
  --block-label: #4a2500;
  --block-shadow: rgba(217, 119, 6, .22);
  --block-edge: rgba(180, 83, 9, .48);
  --block-accent: #f59e0b;
  --block-ring: rgba(245, 158, 11, .2);
}
.block.cat-variables {
  --block-top: #0284c7;
  --block-mid: #0284c7;
  --block-bottom: #0369a1;
  --block-text: #ffffff;
  --block-shadow: rgba(2, 132, 199, .22);
  --block-edge: rgba(2, 132, 199, .55);
  --block-accent: #0ea5e9;
  --block-ring: rgba(14, 165, 233, .2);
}
.block.cat-functions {
  --block-top: #db2777;
  --block-mid: #db2777;
  --block-bottom: #be185d;
  --block-text: #ffffff;
  --block-shadow: rgba(190, 24, 93, .22);
  --block-edge: rgba(190, 24, 93, .55);
  --block-accent: #db2777;
  --block-ring: rgba(219, 39, 119, .2);
}

/* puzzle notch: the top "cut" matches the strip surface, the bottom tab
   inherits the block color */
.block::before {
  content: '';
  position: absolute;
  left: 22px;
  top: -1px;
  width: 44px;
  height: 9px;
  border-radius: 0 0 7px 7px;
  background: var(--strip-bg);
  box-shadow:
    inset 0 -1px 0 var(--block-edge),
    inset 6px 0 0 -5px var(--block-edge),
    inset -6px 0 0 -5px var(--block-edge);
  pointer-events: none;
}

.block::after {
  content: '';
  position: absolute;
  left: 22px;
  bottom: -9px;
  width: 44px;
  height: 10px;
  border: 1px solid var(--block-edge);
  border-top: 0;
  border-radius: 0 0 7px 7px;
  background: var(--block-bottom);
  box-shadow:
    inset 0 -2px 0 rgba(37, 48, 68, .08),
    0 2px 3px var(--block-shadow);
  pointer-events: none;
}

.repeat-body .block::before { background: rgba(255, 255, 255, .58); }

.block-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  column-gap: 6px;
  row-gap: 4px;
  max-width: 100%;
  min-height: 38px;
  padding: 5px 34px 6px 7px;
  font-family: "Nunito", "Segoe UI", system-ui, sans-serif;
  font-weight: 800;
  font-size: 12.5px;
  line-height: 1.15;
  white-space: normal;
}

/* Short motion commands are intentionally one connected row. Giving them an
   explicit intrinsic width avoids flex-wrap changing after a clone/drop render. */
.block.block-single-line {
  width: max-content;
  max-width: none;
}

.block-single-line .block-head {
  width: max-content;
  max-width: none;
  flex-wrap: nowrap;
}

.block-single-line .block-label,
.block-single-line .param {
  flex: none;
  white-space: nowrap;
}

.block-icon {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 1px solid rgba(255, 255, 255, .78);
  border-radius: 6px;
  background: rgba(255, 255, 255, .58);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .8),
    0 1px 2px rgba(37, 48, 68, .08);
  font-size: 13px;
  line-height: 1;
  flex: none;
}
.block-label {
  margin-inline: 1px 2px;
  font-size: 12.75px;
  font-weight: 850;
  line-height: 1.15;
  letter-spacing: .005em;
  text-wrap: pretty;
}

.block-remove {
  position: absolute;
  top: 5px;
  right: 5px;
  border: 1px solid rgba(255, 255, 255, .58);
  background: rgba(255, 255, 255, .42);
  color: var(--block-text);
  width: 24px;
  height: 24px;
  flex: none;
  border-radius: 50%;
  font-size: 16px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: .82;
  margin-left: 0;
  transition: opacity .15s, background .15s;
}
.block-remove:hover { opacity: 1; background: rgba(255, 255, 255, .76); }

.block.selected-block {
  outline: 2px solid var(--block-accent);
  outline-offset: 3px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .72),
    inset 0 -2px 0 rgba(37, 48, 68, .08),
    0 0 0 6px var(--block-ring),
    0 6px 14px var(--block-shadow);
}

.selection-marquee {
  position: fixed;
  z-index: 1000;
  border: 1.5px solid rgba(37, 99, 235, .55);
  border-radius: 4px;
  background: rgba(37, 99, 235, .1);
  pointer-events: none;
}

body.marquee-selecting {
  cursor: crosshair;
  user-select: none;
  -webkit-user-select: none;
}

.param {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  min-height: 28px;
  padding-left: 5px;
  border: 1px solid rgba(255, 255, 255, .36);
  border-radius: 999px;
  background: rgba(255, 255, 255, .14);
}
.param-name,
.param-unit {
  font-family: "Segoe UI", system-ui, sans-serif;
  font-size: 10.5px;
  font-weight: 800;
  line-height: 1;
  opacity: .96;
  white-space: nowrap;
}
.param-unit { margin-right: 5px; }

.block input[type="number"],
.block input[type="text"],
.block select {
  border: 1px solid var(--block-edge);
  border-radius: 999px;
  min-height: 28px;
  padding: 3px 8px;
  font: inherit;
  font-size: 12px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-shadow: none;
  background: rgba(255, 255, 255, .92);
  box-shadow:
    inset 0 1px 2px rgba(37, 48, 68, .09),
    0 1px 0 rgba(255, 255, 255, .38);
}

.block input[type="number"]:hover,
.block input[type="text"]:hover,
.block select:hover {
  background: #fff;
}

.block input:focus-visible,
.block select:focus-visible {
  outline: 2px solid var(--block-accent);
  outline-offset: 2px;
  background: #fff;
  box-shadow: 0 0 0 4px var(--block-ring);
}

.block input[type="number"] {
  width: 54px;
  text-align: center;
}

.block input[type="text"] {
  width: 78px;
}

.block input.param-url { width: min(210px, 56vw); }
.block input.param-wide { width: min(180px, 50vw); }
.block input.param-training { width: min(160px, 46vw); }

.block input.param-number {
  width: 56px;
  text-align: center;
}

.block input.param-variable {
  width: 84px;
  text-align: left;
}

.block select.param-mode {
  width: 48px;
  min-width: 48px;
  max-width: 48px;
  padding-left: 7px;
  padding-right: 3px;
}

.block select {
  min-width: 82px;
  max-width: 132px;
  cursor: pointer;
}

.block input[type="color"] {
  width: 34px;
  height: 28px;
  border: 1px solid rgba(255, 255, 255, .6);
  border-radius: 999px;
  padding: 3px;
  background: rgba(255, 255, 255, .95);
  box-shadow: inset 0 1px 2px rgba(37, 48, 68, .12);
  cursor: pointer;
}

/* ============ live AI feedback ============ */

.ai-live-panel {
  position: absolute;
  left: 16px;
  bottom: 16px;
  z-index: 8;
  width: min(210px, calc(100% - 32px));
  display: grid;
  gap: 7px;
  padding: 10px;
  border: 1px solid rgba(79, 70, 229, .28);
  border-radius: 14px;
  background: rgba(255, 255, 255, .92);
  color: #312e81;
  box-shadow: 0 12px 30px rgba(49, 46, 129, .2);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  text-shadow: none;
}

.ai-live-title {
  font-size: 12px;
  font-weight: 900;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.ai-live-media {
  overflow: hidden;
  aspect-ratio: 1;
  border-radius: 10px;
  background: #111827;
}

.ai-live-media canvas,
.ai-live-media video {
  position: static;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ai-live-video-flipped {
  transform: scaleX(-1);
}

.ai-live-status {
  min-height: 1.3em;
  font-size: 12px;
  font-weight: 750;
  line-height: 1.35;
}

/* ============ containers (repeat / if / function bodies) ============ */

.container-wrap {
  margin: 0 7px 9px 13px;
}

.container-label {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 0 8px;
  border-radius: 999px;
  border: 1px solid var(--block-edge);
  background: rgba(255, 255, 255, .9);
  /* The pill is near-white, so white block text vanished on it (1.3:1).
     The category's deep shade reads at 5.5:1 or better on every block. */
  color: var(--block-label, var(--block-bottom));
  text-shadow: none;
  font-size: 10.5px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .05em;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .25);
}

.container-body.repeat-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  min-width: 214px;
  min-height: 66px;
  margin: 4px 0 0;
  padding: 10px 7px 8px;
  border: 1px solid var(--block-edge);
  border-left: 4px solid var(--block-accent);
  border-radius: 6px;
  background:
    repeating-linear-gradient(0deg, rgba(37, 48, 68, .02) 0 1px, transparent 1px 5px),
    repeating-linear-gradient(90deg, rgba(37, 48, 68, .016) 0 1px, transparent 1px 5px),
    rgba(255, 255, 255, .72);
  background-size: 5px 5px, 5px 5px, 100% 100%;
  box-shadow:
    inset 0 1px 3px rgba(37, 48, 68, .1),
    0 1px 0 rgba(255, 255, 255, .22);
  overflow-x: auto;
}

.block .repeat-body { border-color: var(--block-edge); border-left-color: var(--block-accent); }

.repeat-body:empty::after {
  content: 'drop blocks inside';
  color: rgba(37, 48, 68, .74);
  font-size: 12.5px;
  font-weight: 800;
  margin: auto;
}

.loop-badge {
  background: rgba(255, 255, 255, .92);
  color: var(--loops-text);
  border-radius: 999px;
  font-size: 11px;
  font-weight: 800;
  padding: 3px 8px;
  text-shadow: none;
  box-shadow: inset 0 1px 2px rgba(37, 48, 68, .12);
}
.loop-badge:empty { display: none; }

.design-angle-badge {
  padding: 3px 7px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .92);
  color: #115e59;
  font-size: 11px;
  font-weight: 800;
  white-space: nowrap;
  text-shadow: none;
  box-shadow: inset 0 1px 2px rgba(15, 118, 110, .14);
}

.design-layout-badge {
  padding: 3px 7px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .92);
  color: #115e59;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .02em;
  white-space: nowrap;
  text-shadow: none;
  box-shadow: inset 0 1px 2px rgba(15, 118, 110, .14);
}

.function-summary {
  margin: 0 7px 8px 13px;
  padding: 7px 9px;
  border-radius: 10px;
  background: rgba(255, 255, 255, .86);
  color: rgba(37, 48, 68, .75);
  font-size: 11.5px;
  font-weight: 800;
  text-shadow: none;
  box-shadow: inset 0 1px 2px rgba(37, 48, 68, .1);
}

/* collapsed function definitions look like a small stack of cards */
.function-collapsed {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .72),
    inset 0 -2px 0 rgba(37, 48, 68, .08),
    0 5px 0 -3px rgba(37, 48, 68, .12),
    0 6px 14px var(--block-shadow);
}

/* ============ drag & run states ============ */

.drag-ghost { opacity: .35; }
.block.drag-chosen {
  cursor: grabbing;
  filter: brightness(1.015);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .76),
    inset 0 -2px 0 rgba(37, 48, 68, .08),
    0 8px 18px var(--block-shadow);
}

.drag-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  margin-top: -1px;
  pointer-events: none;
}

.drag-stack > .block {
  margin-bottom: 0;
}

body.running .palette,
body.running .strip-row {
  pointer-events: none;
}
body.running .palette { opacity: .5; }

.running-block {
  position: relative;
  box-shadow: 0 0 0 3px #fff, 0 0 0 6px var(--accent);
}

/* The pulse animates only opacity on an overlay, so it runs on the
   compositor: box-shadow/filter keyframes would repaint the whole block
   subtree every frame for the entire run. The static glow above also keeps
   the highlight visible under prefers-reduced-motion. */
.running-block::after {
  content: '';
  position: absolute;
  inset: -9px;
  border-radius: 12px;
  border: 3px solid rgba(16, 185, 129, .35);
  pointer-events: none;
  animation: block-pulse 0.9s ease-in-out infinite;
}

@keyframes block-pulse {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}

/* ============ dialogs ============ */

.dialog {
  border: none;
  border-radius: var(--radius-lg);
  padding: clamp(18px, 3vw, 26px);
  width: min(440px, 92vw);
  box-shadow: 0 24px 70px rgba(37, 48, 68, .35);
  color: var(--ink);
}
.dialog::backdrop { background: rgba(37, 48, 68, .45); }
.dialog h2 { margin: 0 0 6px; font-size: clamp(18px, 2.2vw, 21px); }
.dialog-wide { width: min(640px, 94vw); }
.dialog-hint { margin: 0 0 16px; color: var(--muted); font-size: 14px; line-height: 1.45; }
.dialog-empty { color: var(--muted); font-size: 14.5px; text-align: center; padding: 20px 0; }

.dialog input[type="text"] {
  width: 100%;
  border: 2px solid var(--line);
  border-radius: 12px;
  min-height: 46px;
  padding: 10px 14px;
  font: inherit;
}
.dialog input[type="text"]:focus-visible { outline: none; border-color: var(--accent); }

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 18px;
}

.dialog-title-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
}
.dialog-title-row h2 { margin-top: 3px; }
.eyebrow {
  color: var(--accent-dark);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.icon-btn {
  flex: none;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: #f8fafc;
  color: var(--muted);
  font-size: 24px;
  line-height: 1;
}
.icon-btn:hover { background: #eef2f7; color: var(--ink); }

.dialog-help { width: min(560px, 94vw); }

/* ============ private sharing ============ */

.dialog-share { width: min(620px, 94vw); }
.share-panel { display: grid; gap: 14px; }
.share-panel[hidden] { display: none; }
.share-privacy-card,
.share-guidance {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 13px 14px;
  border: 1px solid #bdebd9;
  border-radius: 12px;
  background: #f0fdf8;
  color: #155e4a;
}
.share-privacy-card strong,
.share-privacy-card span,
.share-guidance strong,
.share-guidance span { display: block; }
.share-privacy-card span,
.share-guidance span { margin-top: 3px; font-size: 13px; line-height: 1.45; color: var(--muted); }
.share-privacy-icon { flex: 0 0 auto; font-size: 20px; line-height: 1.2; }
.share-project-summary { margin: 0; font-weight: 700; color: var(--ink); }
.share-field-label { font-size: 13px; font-weight: 700; color: var(--ink); }
.share-link-output {
  box-sizing: border-box;
  width: 100%;
  min-height: 76px;
  resize: vertical;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg);
  color: var(--ink);
  font: 12px/1.45 ui-monospace, SFMono-Regular, Consolas, monospace;
  overflow-wrap: anywhere;
}
.share-link-output:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 1px; }
.share-size-guidance { min-height: 20px; margin: 0; color: var(--muted); font-size: 13px; line-height: 1.45; }
.share-guidance { border-color: #fde68a; background: #fffbeb; color: #854d0e; }
.share-guidance-file code { font-size: .92em; }
.share-actions { flex-wrap: wrap; }
.share-incoming-hero { display: flex; align-items: center; gap: 12px; }
.share-incoming-hero > span { font-size: 34px; }
.share-incoming-hero h3 { margin: 2px 0 0; font-size: 18px; }
.share-preview-list { display: grid; gap: 0; margin: 0; border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.share-preview-list > div { display: grid; grid-template-columns: minmax(90px, .6fr) 1.4fr; gap: 12px; padding: 11px 13px; background: var(--surface); }
.share-preview-list > div + div { border-top: 1px solid var(--border); }
.share-preview-list dt { color: var(--muted); font-size: 13px; }
.share-preview-list dd { margin: 0; color: var(--ink); font-weight: 700; overflow-wrap: anywhere; }

@media (max-width: 520px) {
  .dialog-share { width: 96vw; padding: 18px 15px; }
  .share-actions { display: grid; grid-template-columns: 1fr 1fr; }
  .share-actions .btn { justify-content: center; }
  #share-create-btn, #share-open-btn { grid-column: 1 / -1; }
  .share-preview-list > div { grid-template-columns: 1fr; gap: 3px; }
}
.help-steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin: 20px 0 16px;
  padding: 0;
  list-style: none;
}
.help-steps li {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  min-width: 0;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #fbfcfe;
}
.step-icon {
  flex: none;
  width: 25px;
  height: 25px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--accent-dark);
  color: #fff;
  font-size: 12px;
  font-weight: 900;
}
.help-steps li div { display: grid; gap: 4px; }
.help-steps strong { font-size: 13px; }
.help-steps li div span { color: var(--muted); font-size: 12px; line-height: 1.4; }

.shortcut-card {
  padding: 14px;
  border-radius: var(--radius);
  background: #f1f5f9;
}
.shortcut-card h3 { margin: 0 0 10px; font-size: 13px; }
.shortcut-list { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 18px; margin: 0; }
.shortcut-list > div { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.shortcut-list dt { white-space: nowrap; }
.shortcut-list dd { margin: 0; color: var(--muted); font-size: 12px; text-align: right; }
kbd {
  min-width: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 23px;
  padding: 0 6px;
  border: 1px solid #cbd5e1;
  border-bottom-width: 2px;
  border-radius: 5px;
  background: #fff;
  color: #334155;
  font-family: inherit;
  font-size: 10.5px;
  font-weight: 800;
}

.saves-list { display: flex; flex-direction: column; gap: 8px; max-height: 320px; overflow-y: auto; }

.save-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 10px 14px;
}
.save-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.save-meta strong { font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.save-meta span { font-size: 12.5px; color: var(--muted); }
.save-actions { display: flex; gap: 6px; flex: none; }

.examples-grid:focus-visible { outline: none; }

.examples-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(155px, 1fr));
  gap: 10px;
}

.example-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  text-align: left;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  padding: 14px;
  background: #fff;
  color: var(--ink);
  transition: transform .12s, box-shadow .12s, border-color .12s;
}
.example-card:hover {
  transform: translateY(-2px);
  border-color: var(--accent);
  box-shadow: 0 6px 18px rgba(37, 48, 68, .12);
}
.example-emoji { font-size: 30px; }
.example-card strong { font-size: 14.5px; }
.example-desc { font-size: 12.5px; color: var(--muted); line-height: 1.4; }

/* ============ toasts ============ */

.toasts {
  position: fixed;
  top: 122px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  z-index: 90;
  pointer-events: none;
}

.toast {
  background: var(--ink);
  color: #fff;
  border-radius: 12px;
  padding: 11px 18px;
  font-size: 14px;
  font-weight: 600;
  box-shadow: 0 10px 28px rgba(37, 48, 68, .3);
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity .25s, transform .25s;
  max-width: min(480px, 90vw);
}
.toast.show { opacity: 1; transform: translateY(0); }
.toast-info { background: var(--ink); }
.toast-warn { background: #b45309; }
.toast-ok { background: var(--accent-dark); }

/* ============ trash target + mobile chrome ============ */

.trash-target {
  position: fixed;
  left: 50%;
  bottom: 18px;
  transform: translate(-50%, 20px);
  min-height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0 22px;
  border-radius: 999px;
  background: #991b1b;
  color: #fff;
  font-size: 14px;
  font-weight: 800;
  box-shadow: 0 12px 34px rgba(37, 48, 68, .3);
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s, transform .18s;
  z-index: 80;
}
.trash-icon { font-size: 18px; }

body.dragging-code-block .trash-target {
  opacity: 1;
  pointer-events: auto;
  transform: translate(-50%, 0);
}

/* ============ responsive: tablet (2 columns) ============ */

/* ============ stacked layouts: the workspace/stage divider ============ */

/* Below 1100px the stage sits under the workspace instead of beside it, so the
   same handle that splits two columns on a desktop splits two rows here. It is
   the one panel divider that survives onto a phone, because how much room the
   drawing deserves changes constantly - a long script wants the workspace, a
   finished drawing wants the stage. installPanelResizing drives it from a
   stored *ratio*, so the split means the same thing after a rotation. */

@media (max-width: 1099px) {
  .resize-handle-script {
    display: block;
    min-width: 0;
    height: var(--resize-handle-h);
    cursor: row-resize;
    background: var(--bg);
    border-inline: 0;
    border-block: 1px solid var(--soft-line);
  }

  /* Every offset in the base rule assumes a vertical bar, so all of them flip. */
  .resize-handle-script::before {
    top: 50%;
    bottom: auto;
    left: 18px;
    right: 18px;
    width: auto;
    height: 3px;
    transform: translateY(-50%);
    transition: height .14s, background .14s, opacity .14s;
  }

  .resize-handle-script::after {
    width: 38px;
    height: 4px;
    background: linear-gradient(90deg, #94a3b8 20%, transparent 20% 40%, #94a3b8 40% 60%, transparent 60% 80%, #94a3b8 80%);
  }

  .resize-handle-script:hover::before,
  .resize-handle-script:focus-visible::before,
  .resize-handle-script.dragging::before {
    width: auto;
    height: 5px;
  }

  body.resizing-rows {
    cursor: row-resize;
  }
}

/* Workspace over stage here too, matching the phone. A modern phone turned
   sideways is 800-950px wide and lands in this range, so the two panels would
   otherwise trade places the moment the device rotates. */

@media (min-width: 720px) and (max-width: 1099px) {
  .workbench {
    grid-template-columns: clamp(210px, var(--toolbox-w), 300px) var(--resize-handle-w) minmax(0, 1fr);
    grid-template-rows: minmax(150px, 1fr) var(--resize-handle-h) clamp(160px, var(--stage-h), 72dvh);
  }

  .toolbox {
    grid-column: 1;
    grid-row: 1 / 4;
  }

  .resize-handle-toolbox {
    display: block;
    grid-column: 2;
    grid-row: 1 / 4;
  }

  .script-panel {
    grid-column: 3;
    grid-row: 1;
    border-right: none;
  }

  .resize-handle-script {
    grid-column: 3;
    grid-row: 2;
  }

  .stage {
    grid-column: 3;
    grid-row: 3;
  }

  .canvas-wrap {
    width: 100%;
    height: 100%;
  }
}

/* ============ responsive: phone (compact studio) ============ */

/* A phone shows the same three regions as a desktop rather than one panel at
   a time: the toolbox is a rail down the left, and the right side stacks the
   program workspace over the stage. Nothing below may depend on
   `body[data-mobile-panel]` - every panel is on screen at once now, so the
   bottom tab bar keeps the `display: none` it has at every other width. */

@media (max-width: 719px) {
  .toolbar {
    gap: 8px;
    padding: 8px 10px;
  }

  .brand { flex: 1; min-width: 0; }
  .brand-turtle { width: 42px; height: 38px; }
  .brand-turtle-svg { width: 36px; height: 36px; }

  .btn { min-height: 44px; }
  .btn-examples { padding: 8px 12px; font-size: 13.5px; }
  .file-menu-btn { padding: 8px 12px; font-size: 13.5px; }

  /* The stage row is a clamped track, never a bare `1fr`: `.canvas-wrap` is
     `height: 100%`, which resolves against an indefinite track to zero. The
     clamp bounds also mirror the ones installPanelResizing enforces, so the
     pre-script paint already lands somewhere sensible. */
  .workbench {
    grid-template-columns: clamp(104px, 28vw, 160px) minmax(0, 1fr);
    grid-template-rows: minmax(120px, 1fr) var(--resize-handle-h) clamp(120px, var(--stage-h), 72dvh);
  }

  .toolbox {
    grid-column: 1;
    grid-row: 1 / 4;
    padding: 7px 6px;
  }

  .script-panel {
    grid-column: 2;
    grid-row: 1;
    padding: 6px;
  }

  .resize-handle-script {
    grid-column: 2;
    grid-row: 2;
  }

  .stage {
    grid-column: 2;
    grid-row: 3;
    padding: 0;
  }

  .canvas-wrap {
    width: 100%;
    height: 100%;
    min-width: 0;
  }

  /* The rail is a fixed width here; only the workspace/stage split is dragged. */
  .resize-handle-toolbox {
    display: none;
  }

  /* ---- toolbox: a ~120px rail, so its type scales down with it ---- */

  .toolbox-discovery {
    margin: -3px -3px 7px;
    padding: 3px 3px 6px;
  }

  .block-search {
    min-height: 40px;
    padding: 7px 8px 7px 25px;
    border-radius: 10px;
    font-size: 11.5px;
  }
  .block-search-icon { left: 7px; font-size: 15px; }
  .block-search-clear { right: 6px; width: 26px; height: 26px; font-size: 16px; }

  .palette { gap: 5px; }

  /* Section names are single words ("Programming", "Mathematics") so they
     cannot wrap out of trouble - the type has to shrink with the rail. */
  .palette-section-title {
    min-height: 34px;
    gap: 4px;
    padding: 0 7px;
    font-size: clamp(9.5px, 2.6vw, 11.5px);
    line-height: 1.15;
  }

  .palette-label,
  .palette-link {
    min-height: 30px;
    gap: 4px;
    padding: 5px 7px;
    font-size: clamp(9.5px, 2.7vw, 11.5px);
    line-height: 1.2;
  }

  .palette-chips { gap: 5px; padding: 2px 5px 6px; }

  /* The label has to stay inside the rail at its narrowest, and the rail no
     longer widens as fast as the viewport, so the type tops out sooner. */
  .chip {
    width: 100%;
    gap: clamp(3px, 1vw, 6px);
    padding: 5px 6px;
    font-size: clamp(10px, 2.6vw, 11.5px);
  }

  /* The icon column has to shrink with the rail or it eats the label: at a
     104px rail a fixed 18px icon leaves ~44px of text, and "Backward" needs
     47px, so it broke mid-word. Wide enough at each size that multi-codepoint
     emoji still paint inside their column. */
  .chip-icon {
    width: clamp(14px, 4.2vw, 20px);
    font-size: clamp(12px, 3.6vw, 17px);
  }

  /* A safety net only - break-word breaks a word solely when it cannot fit a
     line of its own, unlike `anywhere`, which will split one eagerly. */
  .chip > span:last-child { overflow-wrap: break-word; }

  .custom-empty { font-size: 10.5px; line-height: 1.35; }

  /* Sized for the full-width panel this used to be; in a rail it has to lose
     its 210px floor and its generous padding or it fills the whole column. */
  .palette-search-empty {
    min-height: 0;
    gap: 5px;
    padding: 14px 8px;
    border-radius: var(--radius-sm);
  }
  .palette-search-empty strong { font-size: 11.5px; }
  .palette-search-empty > span:not(.palette-empty-icon) {
    max-width: none;
    font-size: 10px;
    line-height: 1.35;
  }
  .palette-empty-icon { font-size: 21px; }
  .palette-search-empty .btn {
    min-height: 36px;
    padding: 6px 8px;
    font-size: 10.5px;
  }

  /* ---- workspace ---- */

  .strip {
    min-height: 0;
    padding: 0;
  }

  /* New Start stays in the flow, just shorter. Floating it into the workspace
     corner reclaimed 32px but put an opaque 90px chip on top of whatever block
     had scrolled under it - and a chip with `pointer-events` still live, so a
     tap meant for that block's number field opened a new Start stack instead.
     Translucency changes how it looks, not what gets hit. */
  .strip-row { gap: 4px; }

  .strip-start {
    min-height: 24px;
    padding: 0 9px;
    font-size: 9.5px;
  }

  /* ---- blocks: same shape, ~20% less of it ----
     A phone workspace column is ~280px, so every millimetre of block chrome
     costs a row. Only the visible box shrinks; the number fields keep a real
     touch height and the delete button gets an invisible hit area back below,
     so a smaller silhouette does not mean smaller targets. The base values are
     untouched, which is what keeps the desktop block metrics contract honest. */
  .block-head {
    min-height: 30px;
    column-gap: 5px;
    row-gap: 3px;
    padding: 3px 26px 4px 6px;
    font-size: 11.5px;
  }

  .block-label {
    margin-inline: 1px;
    font-size: 11.5px;
  }

  /* 23px is short for a touch target on its own, but these sit inside a 30px
     block row that is itself draggable - the row is the target you aim at, and
     tapping anywhere on the field focuses it and raises the keyboard. */
  .block input[type="number"],
  .block input[type="text"],
  .block select {
    min-height: 23px;
    padding: 1px 5px;
    font-size: 11px;
  }

  .block-remove {
    top: 4px;
    right: 4px;
    width: 21px;
    height: 21px;
    font-size: 14px;
  }

  .start-hat {
    min-height: 26px;
    gap: 5px;
    padding: 0 10px 0 8px;
    font-size: 10.5px;
  }

  .start-remove {
    width: 17px;
    height: 17px;
    font-size: 10px;
  }

  .container-body.repeat-body {
    min-width: 180px;
    min-height: 54px;
    padding: 7px 6px 6px;
  }

  /* Blocks keep their natural width and the workspace scrolls to them, as on
     a desktop. Squeezing them to the column would crush their number inputs.

     Which means these buttons permanently float over block content - a 265px
     column has no clear corner to put them in. So they rest translucent and
     firm up on touch, and an invisible inset keeps the target at 44px even
     though the visible circle is 32px. */
  .workspace-zoom-controls { right: 8px; bottom: 8px; gap: 5px; }

  .workspace-zoom-btn {
    position: relative;
    width: 32px;
    height: 32px;
    border-width: 1px;
    opacity: .55;
  }
  .workspace-zoom-btn svg { width: 18px; height: 18px; }
  .workspace-zoom-btn::after {
    content: '';
    position: absolute;
    inset: -6px;
  }
  .workspace-zoom-btn:active,
  .workspace-zoom-btn:focus-visible { opacity: 1; }

  /* ---- run bar ----
     One row (~54px) wherever it fits, which is roughly 375px and up. Three
     things buy that over the two rows this used to take: the status pill goes
     visually hidden, Reset drops to its glyph, and Run keeps its label because
     it is the one control a child actually looks for.

     Undo/redo and pause/step take the same slot rather than both claiming
     one, because they are never useful at the same time: `body.running`
     already puts `pointer-events: none` on the palette and the workspace, so
     there is nothing to undo mid-run, and the debugger buttons are disabled
     until one starts. Same swap-in-place trade Run and Stop make. */
  .runbar {
    gap: 4px;
    padding: 5px;
  }

  /* Still announced - it is the `aria-live` region that reports run state -
     but the word costs a third of the row and Run/Stop already shows it. */
  .run-status {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  /* Glyph only. `font-size: 0` hides the text node without touching the
     accessible name, which is still "Reset". */
  #reset-btn {
    flex: none;
    width: 36px;
    min-width: 36px;
    padding: 0;
    font-size: 0;
  }
  #reset-btn::before {
    content: '↺';
    font-size: 20px;
    line-height: 1;
  }

  .history-actions,
  .debug-actions {
    order: 1;
    flex: none;
    margin-left: 0;
  }

  body.running .history-actions,
  body:not(.running) .debug-actions {
    display: none;
  }

  /* Two icons plus the slider plus the status pill is the whole budget, so
     the icons scale with the viewport instead of holding a fixed 39px. The
     `.runbar` prefix is load-bearing: `@media (pointer: coarse)` pins
     `.debug-btn` to 44px further down the file and would otherwise win.
     Only the width gives; the 42-44px touch height stays. */
  .runbar .history-btn,
  .runbar .debug-btn {
    width: clamp(32px, 8vw, 40px);
  }

  /* A zero basis, so the slider never votes on whether the row wraps - it just
     absorbs whatever the fixed controls leave (58px at 390, 38px at 360). Flex
     breaks lines on hypothetical size, so a 44px basis was pushing Run onto a
     second row over two pixels. */
  /* Everything the pill spends on chrome comes straight off the draggable
     track, and the track is the control - so the padding, the gap and the
     turtle face all shrink to leave the slider the width it needs. */
  .speed-control {
    order: 2;
    flex: 1 1 0;
    width: auto;
    min-width: 34px;
    max-width: none;
    min-height: 40px;
    gap: 2px;
    padding: 3px 5px;
  }
  #speed-face { width: 14px; font-size: 14px; }

  /* No forced line break any more. Below ~375px the group wraps on its own,
     and because the slider grows the row above stays filled rather than
     leaving a ragged gap. */
  /* `flex: 0 0 auto`, not `1 1 auto`: the slider is the only control that
     should absorb spare width. Letting this group grow too split the surplus
     between them and left the speed track ten pixels wide. */
  .run-actions {
    order: 5;
    flex: 0 0 auto;
    gap: 5px;
    margin-left: auto;
    justify-content: flex-end;
  }

  .run-actions .btn {
    min-width: 0;
    min-height: 42px;
    gap: 5px;
    padding: 7px 8px;
    font-size: 13.5px;
  }

  #run-btn,
  #stop-btn {
    flex: 1 1 auto;
    min-width: 0;
  }

  /* ---- stage ---- */

  .stage-chrome { top: 8px; left: 8px; right: 8px; gap: 6px; }
  .stage-title { min-height: 28px; padding: 0 9px; font-size: 10px; }
  .stage-action { width: 32px; min-height: 28px; font-size: 15px; }

  /* The stage is at its smallest here, so the cluster shrinks and takes the
     same translucent-until-touched treatment as the workspace one, or three
     46px buttons would claim a third of a 280px-wide stage. */
  .stage-zoom-controls {
    right: max(8px, env(safe-area-inset-right));
    bottom: max(8px, env(safe-area-inset-bottom));
    border-radius: 11px;
    opacity: .62;
  }
  .stage-zoom-controls:focus-within,
  .stage-zoom-controls:active { opacity: 1; }

  .stage-zoom-btn {
    width: 34px;
    height: 34px;
    font-size: 19px;
  }

  /* No bottom tab bar to clear any more. */
  .trash-target {
    bottom: max(14px, env(safe-area-inset-bottom));
  }

  .toasts {
    top: 68px;
  }
}

/* compact phones: keep the toolbar on one line, no page overflow */
@media (max-width: 560px) {
  .toolbar-actions { gap: 6px; }
  .btn-examples {
    width: 44px;
    min-width: 44px;
    padding: 0;
    font-size: 0;
  }
  .btn-examples span { font-size: 15px; }
  .btn-help { width: 40px; min-width: 40px; }
}

/* On the narrowest phones that still hold a one-row bar, the speed emoji is
   the first thing to go: it is decoration, and the 16px it occupies is a
   third of the track it sits next to. The slider keeps its aria-valuetext. */
@media (max-width: 389px) {
  #speed-face { display: none; }
}

/* Below ~360px the bar cannot hold one row, so rather than let it wrap into a
   ragged half-empty line, it splits deliberately: transport above, Reset and
   Run filling the width below. */
@media (max-width: 359px) {
  .runbar .run-actions {
    flex: 1 0 100%;
    margin-left: 0;
  }
  .runbar .run-actions #run-btn,
  .runbar .run-actions #stop-btn {
    flex: 1 1 auto;
  }
}

/* extra-small phones: keep labels compact */
@media (max-width: 419px) {
  .brand-text strong { font-size: 14px; }
  .file-menu-btn { padding: 8px 10px; font-size: 13px; }
  .file-menu-list { min-width: 180px; }
}

@media (max-width: 560px) {
  .help-steps { grid-template-columns: 1fr; }
  .shortcut-list { grid-template-columns: 1fr; }
  .dialog-help { max-height: calc(100dvh - 24px); overflow-y: auto; }
}

/* A phone held sideways has height, not width, as its scarce axis: the stage
   band and the run bar both give room back to the workspace between them. */
@media (max-width: 719px) and (max-height: 560px) {
  .workbench {
    grid-template-rows: minmax(96px, 1fr) var(--resize-handle-h) clamp(96px, var(--stage-h), 62dvh);
  }

  .toolbar { padding-block: 5px; }
  .btn { min-height: 38px; }
  .runbar { gap: 4px; padding: 4px; }
  .speed-control { min-height: 38px; }
  .runbar .history-btn,
  .runbar .debug-btn { min-height: 38px; }
  .run-actions .btn { min-height: 40px; }
}

/* Landscape phones and short laptop windows keep the primary controls usable. */
@media (max-height: 560px) and (min-width: 720px) {
  .toolbar { padding-block: 5px; }
  .brand-turtle { height: 36px; }
  .btn { min-height: 38px; padding-block: 5px; }
  .palette-section-title { min-height: 36px; }
  .runbar { padding: 5px; }
  .speed-control { min-height: 38px; }
}

/* Tablet row minimums must never add up to more than the remaining viewport.
   Stage last, matching the row order above. */
@media (max-height: 700px) and (min-width: 720px) and (max-width: 1099px) {
  .workbench {
    grid-template-rows: minmax(120px, 1fr) var(--resize-handle-h) clamp(120px, var(--stage-h), 62dvh);
  }
}

/* ============ touch ergonomics ============ */

@media (pointer: coarse) {
  /* A finger needs more of the divider to grab than a cursor does. */
  .workbench { --resize-handle-w: 18px; --resize-handle-h: 20px; }

  .chip {
    min-height: 44px;
  }

  .start-remove::after,
  .stack-drag-grip::after {
    content: '';
    position: absolute;
    inset: -12px;
  }

  /* The delete button is 21px across on a phone. This keeps the silhouette
     that small while giving a finger a ~35px target, the same trade the Start
     controls above already make. Kept narrower horizontally than vertically so
     it does not reach into the number field beside it. */
  .block-remove::after {
    content: '';
    position: absolute;
    inset: -7px -5px;
  }

  .stack-drag-grip::after {
    inset: -14px -5px;
  }

  /* Keep the connected stack silhouette compact on touch and hybrid devices.
     Its controls already meet the 24px target-size minimum; only the small
     Start and drag handles need the invisible hit-area expansion above. */
}

/* ============ guided learning journey ============ */

.btn-learn {
  color: #064e3b;
  background: linear-gradient(135deg, #d1fae5, #a7f3d0);
  border-color: #6ee7b7;
  box-shadow: 0 3px 9px rgba(5, 150, 105, .13);
}

.btn-learn:hover { background: linear-gradient(135deg, #a7f3d0, #6ee7b7); }

.dialog-learning {
  width: min(780px, 95vw);
  max-height: min(90dvh, 840px);
  padding: 0;
  overflow: hidden;
}

.dialog-learning[open] { display: flex; flex-direction: column; }

.dialog-learning .learning-title-row {
  padding: 24px 26px 14px;
  background:
    radial-gradient(circle at 88% 10%, rgba(110, 231, 183, .35), transparent 30%),
    linear-gradient(145deg, #f0fdf4, #ffffff 72%);
  border-bottom: 1px solid #d1fae5;
}

.dialog-learning .learning-title-row > div { min-width: 0; }
.dialog-learning .dialog-hint { max-width: 600px; margin: 7px 0 0; }

.learning-overview {
  margin: 18px 26px 6px;
  padding: 15px 17px;
  border: 1px solid #dbe7e2;
  border-radius: 15px;
  background: #fbfefc;
}

.learning-progress-copy {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 10px;
}

.learning-progress-copy strong { font-size: 14px; color: #14532d; }
.learning-progress-copy span { font-size: 12px; color: var(--muted); text-align: right; }

.learning-progress-track {
  height: 9px;
  overflow: hidden;
  border-radius: 999px;
  background: #e5e7eb;
  box-shadow: inset 0 1px 2px rgba(37, 48, 68, .1);
}

.learning-progress-track > span {
  display: block;
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, #10b981, #22c55e, #84cc16);
  transition: width .45s cubic-bezier(.2, .8, .2, 1);
}

.learning-path {
  flex: 1 1 auto;
  min-height: 180px;
  max-height: none;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 10px 26px 22px;
  scrollbar-gutter: stable;
}

.learning-chapter {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 15px 0 9px;
}

.learning-chapter:first-child { margin-top: 1px; }
.learning-chapter h3 { margin: 0; font-size: 13px; letter-spacing: .025em; color: #475569; }

.learning-chapter-number {
  display: grid;
  place-items: center;
  width: 23px;
  height: 23px;
  flex: none;
  border-radius: 8px;
  color: #047857;
  background: #d1fae5;
  font-size: 11px;
  font-weight: 900;
}

.mission-card {
  position: relative;
  margin: 0 0 10px 11px;
  padding: 15px 16px;
  border: 1px solid #dce5e1;
  border-radius: 15px;
  background: #fff;
  box-shadow: 0 4px 14px rgba(37, 48, 68, .05);
}

.mission-card::before {
  content: '';
  position: absolute;
  left: -12px;
  top: -11px;
  bottom: -11px;
  width: 2px;
  background: #dbe7e2;
}

.mission-card.is-active {
  border-color: #6ee7b7;
  box-shadow: 0 7px 24px rgba(5, 150, 105, .12), inset 3px 0 #10b981;
}

.mission-card.is-complete { background: linear-gradient(145deg, #f0fdf4, #fff 70%); }
.mission-card.is-locked { background: #f8fafc; box-shadow: none; opacity: .76; }

.mission-head { display: flex; align-items: flex-start; gap: 13px; }

.mission-icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  flex: none;
  border: 1px solid #dbe7e2;
  border-radius: 12px;
  color: #047857;
  background: #ecfdf5;
  font-size: 18px;
  font-weight: 900;
}

.mission-card.is-complete .mission-icon { color: #fff; background: #10b981; border-color: #10b981; }
.mission-card.is-locked .mission-icon { filter: grayscale(1); background: #f1f5f9; }
.mission-title { min-width: 0; }
.mission-title h4 { margin: 2px 0 3px; color: #1e293b; font-size: 16px; }
.mission-title p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.45; }

.mission-kicker {
  display: block;
  color: #047857;
  font-size: 10.5px;
  line-height: 1.2;
  font-weight: 850;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.learning-objectives {
  display: grid;
  gap: 6px;
  margin: 13px 0 0 51px;
  padding: 0;
  list-style: none;
}

.learning-objective {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 10px;
  color: #475569;
  background: #f8fafc;
  font-size: 12.5px;
  line-height: 1.35;
}

.learning-objective.is-passed { color: #166534; background: #f0fdf4; }
.learning-check { width: 16px; flex: none; color: #64748b; font-size: 15px; font-weight: 900; line-height: 1.1; }
.learning-objective.is-passed .learning-check { color: #16a34a; }
.learning-objective-copy { display: grid; gap: 2px; }
.learning-objective-copy strong { font-weight: 700; }
.learning-objective-copy small { color: #64748b; font-size: 11.5px; }

.mission-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin: 13px 0 0 51px;
}

.learning-awards-section { padding: 3px 26px 19px; border-top: 1px solid #edf2f0; background: #fbfefc; }

.learning-achievements {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.achievement {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  padding: 10px;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  color: #94a3b8;
  background: #f8fafc;
  filter: grayscale(.8);
}

.achievement.is-earned { color: #334155; background: #fff; border-color: #bae6d2; filter: none; }
.achievement-icon { display: grid; place-items: center; width: 29px; height: 29px; flex: none; border-radius: 9px; background: #e2e8f0; font-size: 17px; }
.achievement.is-earned .achievement-icon { background: #ecfdf5; }
.achievement-copy { display: grid; min-width: 0; }
.achievement-copy strong { font-size: 12px; }
.achievement-copy small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 10.5px; color: #64748b; }

.dialog-learning > .dialog-actions { margin: 0; padding: 12px 26px 16px; border-top: 1px solid #e5e7eb; background: #fff; }
.learning-privacy { margin-right: auto; color: #64748b; font-size: 11.5px; }

@media (max-width: 719px) {
  .btn-learn { width: 44px; min-width: 44px; padding: 0; font-size: 0; }
  .btn-learn span { font-size: 15px; }
  .dialog-learning { width: calc(100vw - 18px); max-height: calc(100dvh - 18px); }
  .dialog-learning .learning-title-row { padding: 19px 18px 12px; }
  .learning-overview { margin: 13px 18px 4px; }
  .learning-progress-copy { align-items: flex-start; flex-direction: column; gap: 3px; }
  .learning-progress-copy span { text-align: left; }
  .learning-path { min-height: 120px; padding-inline: 18px; }
  .learning-awards-section { padding-inline: 18px; }
  .learning-achievements { grid-template-columns: 1fr; }
  .learning-objectives, .mission-actions { margin-left: 0; }
  .mission-actions { justify-content: stretch; }
  .mission-actions .btn { flex: 1; }
  .achievement:nth-child(n+3) { display: none; }
  .dialog-learning > .dialog-actions { padding-inline: 18px; }
}

@media (max-width: 420px) {
  .learning-privacy { display: none; }
  .dialog-learning > .dialog-actions { justify-content: flex-end; }
}

/* ============ accessibility ============ */

:focus-visible {
  outline: 3px solid #2563eb;
  outline-offset: 2px;
}

/* inside colored blocks a white ring reads better than blue */
.block input:focus-visible,
.block select:focus-visible,
.block-remove:focus-visible {
  outline: 3px solid rgba(37, 99, 235, .45);
  outline-offset: 1px;
}

.block.selected-block:focus-visible {
  outline-color: var(--block-accent);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }

  .running-block {
    animation: none;
    box-shadow: 0 0 0 3px #fff, 0 0 0 6px var(--accent);
  }

  .chip:hover,
  .example-card:hover,
  .btn:active {
    transform: none;
  }
}

/* ============ block-boundary execution debugger ============ */

.debug-actions {
  display: inline-flex;
  flex: none;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel);
  transition: border-color .18s ease, box-shadow .18s ease;
}

.debug-btn {
  display: grid;
  place-items: center;
  width: 39px;
  min-height: 42px;
  padding: 0;
  border: 0;
  background: transparent;
  color: #334155;
  font-size: 17px;
  line-height: 1;
}

.debug-btn + .debug-btn { border-left: 1px solid var(--line); }
.debug-btn:hover:not(:disabled) { color: #075985; background: #f0f9ff; }
.debug-btn:disabled { opacity: .34; cursor: default; }
.debug-btn:focus-visible { position: relative; z-index: 1; outline-offset: -3px; }

/* Paused reads clearly from the amber status pill and the resume glyph, so the
   group itself only tints its border - no ring, no extra box around the pair. */
body.paused .debug-actions {
  border-color: #fcd34d;
}

body.paused #pause-btn { color: #92400e; background: #fffbeb; }

/* Stepping is only meaningful while paused, so that is the only time the
   button spells out what it does. Everywhere else it stays a compact glyph. */
.debug-label { display: none; }
body.paused .debug-actions .debug-label { display: inline; }
body.paused #step-btn {
  width: auto;
  grid-auto-flow: column;
  gap: 5px;
  padding: 0 9px;
  font-size: 14.5px;
  font-weight: 700;
}

body.paused .run-status {
  color: #92400e;
  background: #fffbeb;
  border-color: rgba(245, 158, 11, .28);
}

body.paused .run-status::before {
  background: #f59e0b;
  box-shadow: 0 0 0 4px rgba(245, 158, 11, .14);
  animation: none;
}

/* The phone run bar swaps this group in for undo/redo while a program runs -
   see the `.history-actions` / `.debug-actions` pair in the phone breakpoint.
   These two rules have to live here rather than up there: they restate
   `body.paused` selectors that appear above and would otherwise win on order. */
@media (max-width: 719px) {
  /* Spelling out "Next" costs the status pill more than the word explains -
     the amber pill and the ↦ glyph already say what stepping does, and the
     pill is where "Paused · 2" lives. */
  body.paused .debug-actions .debug-label { display: none; }

  body.paused #step-btn {
    width: clamp(34px, 9.5vw, 44px);
    padding: 0;
    font-size: 17px;
  }
}

@media (pointer: coarse) {
  .debug-btn { width: 44px; min-height: 44px; }
}

/* ============ interactivity polish (added) ============ */

/* level headings inside the examples grid — span all card columns */
.examples-group-title {
  grid-column: 1 / -1;
  margin: 12px 0 0;
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: .03em;
  color: var(--muted);
}
.examples-group-title:first-child { margin-top: 0; }

/* brief pop-in for a block just added from the toolbox */
.block-just-added {
  animation: block-pop-in .45s cubic-bezier(.2, .9, .3, 1.2);
}

@keyframes block-pop-in {
  0% {
    transform: scale(.9);
    box-shadow: 0 0 0 3px #fff, 0 0 0 7px rgba(16, 185, 129, .5), 0 2px 6px rgba(37, 48, 68, .18);
  }
  100% {
    transform: scale(1);
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0), 0 0 0 7px rgba(16, 185, 129, 0), 0 2px 6px rgba(37, 48, 68, .18);
  }
}

@media (prefers-reduced-motion: reduce) {
  .block-just-added { animation: none; }
}

/* keep the grouped examples dialog inside the viewport on short screens */
.examples-grid {
  max-height: min(62vh, 540px);
  overflow-y: auto;
  padding-right: 4px;
}

/* ============ My Blocks (saved custom function blocks) ============ */

.custom-chip {
  position: relative;
  padding-right: 38px;
  cursor: grab;
}

.custom-chip .chip-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chip-delete {
  position: absolute;
  right: 7px;
  top: 50%;
  transform: translateY(-50%);
  width: 26px;
  height: 26px;
  border: none;
  border-radius: 50%;
  background: rgba(37, 48, 68, .08);
  color: currentColor;
  font-size: 11px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: .65;
}
.chip-delete:hover { opacity: 1; background: rgba(37, 48, 68, .13); }

.custom-empty {
  margin: 0;
  padding: 2px 4px 6px;
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.5;
}

/* the ★ save button on Define function blocks, styled like .block-remove */
.block-save-fn {
  border: 1px solid rgba(255, 255, 255, .58);
  background: rgba(255, 255, 255, .42);
  color: var(--block-text);
  width: 24px;
  height: 24px;
  flex: none;
  border-radius: 50%;
  font-size: 13px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: .75;
}
.block-save-fn:hover { opacity: 1; background: rgba(255, 255, 255, .76); color: var(--block-text); }
.block-save-fn:focus-visible { outline: 3px solid rgba(37, 99, 235, .45); outline-offset: 1px; }

@media (pointer: coarse) {
  .chip-delete {
    width: 32px;
    height: 32px;
  }
}

/* ============ final product-detail pass ============ */

:root {
  color-scheme: light;
  --focus-ring: #2563eb;
  --focus-halo: rgba(37, 99, 235, .18);
  --panel-highlight: rgba(255, 255, 255, .78);
}

html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

button,
summary,
input,
select {
  -webkit-tap-highlight-color: transparent;
}

button,
summary {
  touch-action: manipulation;
}

button:disabled {
  pointer-events: none;
}

/* Calm, consistent scrolling across dense panels. */
.toolbox,
.strip,
.examples-grid,
.saves-list,
.container-body.repeat-body,
.dialog-help {
  scrollbar-width: thin;
  scrollbar-color: #aebdce transparent;
}

.toolbox::-webkit-scrollbar,
.strip::-webkit-scrollbar,
.examples-grid::-webkit-scrollbar,
.saves-list::-webkit-scrollbar,
.container-body.repeat-body::-webkit-scrollbar,
.dialog-help::-webkit-scrollbar {
  width: 9px;
  height: 9px;
}

.toolbox::-webkit-scrollbar-thumb,
.strip::-webkit-scrollbar-thumb,
.examples-grid::-webkit-scrollbar-thumb,
.saves-list::-webkit-scrollbar-thumb,
.container-body.repeat-body::-webkit-scrollbar-thumb,
.dialog-help::-webkit-scrollbar-thumb {
  border: 2px solid transparent;
  border-radius: 999px;
  background: #aebdce;
  background-clip: padding-box;
}

.toolbox,
.strip,
.examples-grid,
.saves-list {
  overscroll-behavior: contain;
}

.btn,
.history-btn,
.stage-action,
.icon-btn,
.menu-item,
.chip,
.block-search-clear {
  transition-property: color, background-color, border-color, box-shadow, opacity, transform, filter;
  transition-duration: .16s;
  transition-timing-function: ease;
}

.btn:focus-visible,
.history-btn:focus-visible,
.stage-action:focus-visible,
.icon-btn:focus-visible,
.menu-item:focus-visible,
.block-search-clear:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-halo);
}

.btn-run:focus-visible {
  outline-color: #065f46;
  box-shadow: 0 0 0 5px rgba(16, 185, 129, .24), 0 5px 16px rgba(16, 185, 129, .32);
}

.btn-run:not(:disabled):active,
.example-card:active,
.chip:active {
  transform: translateY(1px) scale(.99);
}

.toolbar {
  padding-top: max(clamp(8px, 1vw, 10px), env(safe-area-inset-top));
  background: rgba(255, 255, 255, .96);
  -webkit-backdrop-filter: saturate(1.2) blur(14px);
  backdrop-filter: saturate(1.2) blur(14px);
}

.file-menu-list {
  transform-origin: top right;
}

.file-menu[open] .file-menu-list {
  animation: menu-reveal .16s cubic-bezier(.2, .8, .2, 1);
}

@keyframes menu-reveal {
  from { opacity: 0; transform: translateY(-5px) scale(.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

.menu-item:focus-visible {
  outline-offset: -2px;
}

.toolbox {
  border-right: 1px solid var(--soft-line);
}

.palette-section,
.runbar,
.block-search {
  box-shadow: 0 1px 2px rgba(37, 48, 68, .04), 0 6px 18px rgba(37, 48, 68, .035);
}

.palette-section-title,
.palette-label {
  transition: color .15s ease, background-color .15s ease;
}

.palette-section-title:focus-visible,
.palette-label:focus-visible {
  position: relative;
  outline: 3px solid var(--focus-ring);
  outline-offset: -3px;
  border-radius: 8px;
}

.palette-section[open] > .palette-section-title {
  color: #172033;
}

.palette-section-title::after,
.palette-label::after {
  width: 18px;
  text-align: center;
  transition: transform .15s ease;
}

.palette-section[open] > .palette-section-title::after,
.palette-group[open] > .palette-label::after {
  transform: rotate(0deg);
}

.chip {
  isolation: isolate;
  text-align: left;
}

.custom-chip-use {
  flex: 1;
  min-width: 0;
  min-height: 28px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-weight: inherit;
  text-align: left;
  cursor: inherit;
}

.custom-chip:has(.custom-chip-use:focus-visible) {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-halo), 0 5px 14px rgba(37, 48, 68, .14);
}

.custom-chip-use:focus-visible {
  outline: none;
}

.chip:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-halo), 0 5px 14px rgba(37, 48, 68, .14);
}

.chip-icon {
  display: grid;
  place-items: center;
  min-height: 24px;
  border-radius: 6px;
  background: rgba(255, 255, 255, .38);
}

.block-search-wrap:focus-within .block-search-icon {
  color: var(--focus-ring);
}

.block-search:focus-visible {
  outline: none;
}

.palette-search-empty {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9);
}

.strip-start {
  transition: box-shadow .15s ease, transform .12s ease, background-color .15s ease;
}

.strip-start:hover {
  background: #056b50;
  box-shadow: 0 4px 12px rgba(4, 120, 87, .22);
  transform: translateY(-1px);
}

.strip {
  background-color: #f1f4f9;
  box-shadow: inset 0 1px 3px rgba(37, 48, 68, .05);
}

.workspace-surface.is-empty::before {
  content: '+';
  position: absolute;
  left: 24px;
  top: 24px;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 2px dashed #94a3b8;
  border-radius: 10px;
  color: #64748b;
  font-size: 23px;
  font-weight: 500;
  pointer-events: none;
}

.workspace-surface.is-empty::after {
  content: 'Choose a block to begin';
  left: 70px;
  top: 24px;
  padding: 3px 6px 20px;
  background: linear-gradient(transparent calc(100% - 18px), transparent);
  color: #53657c;
  font-size: 14px;
  line-height: 1.35;
}

.script-stack.has-hat .stack-body:empty::after {
  content: 'Drop a block here';
  align-self: center;
  margin: auto 14px;
  color: #537568;
  font-size: 11px;
  font-weight: 750;
  letter-spacing: .01em;
  pointer-events: none;
}

.script-stack:focus-within {
  z-index: 8;
}

.block:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 2px;
  box-shadow: 0 0 0 7px var(--block-accent), 0 8px 18px var(--block-shadow);
}

.start-hat:focus-visible,
.stack-drag-grip:focus-visible,
.start-remove:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}

.runbar {
  border-color: var(--line);
  box-shadow: 0 -2px 18px rgba(37, 48, 68, .06);
}

.speed-control:focus-within {
  border-color: #93c5fd;
  box-shadow: 0 0 0 3px var(--focus-halo);
}

.speed-control input[type="range"] {
  min-height: 30px;
}

.speed-control input[type="range"]:focus-visible {
  outline: none;
}

.run-status {
  border: 1px solid rgba(148, 163, 184, .24);
}

body.running .run-status::before {
  animation: status-breathe 1.4s ease-in-out infinite;
}

@keyframes status-breathe {
  50% { box-shadow: 0 0 0 7px rgba(16, 185, 129, .05); }
}

.stage {
  border-left: 1px solid var(--soft-line);
}

.stage-title,
.stage-action {
  border-color: rgba(148, 163, 184, .4);
  background: rgba(255, 255, 255, .92);
}

.stage-action:active {
  transform: scale(.94);
}

.dialog {
  max-height: min(88dvh, 760px);
  overflow: auto;
  border: 1px solid rgba(255, 255, 255, .7);
  background: linear-gradient(180deg, #fff 0%, #fbfcfe 100%);
}

.dialog[open] {
  animation: dialog-reveal .2s cubic-bezier(.2, .8, .2, 1);
}

.dialog[open]::backdrop {
  animation: backdrop-reveal .2s ease-out;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

@keyframes dialog-reveal {
  from { opacity: 0; transform: translateY(8px) scale(.985); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes backdrop-reveal {
  from { opacity: 0; }
  to { opacity: 1; }
}

.dialog input[type="text"] {
  transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}

.dialog input[type="text"]:focus-visible {
  background: #fff;
  box-shadow: 0 0 0 4px rgba(16, 185, 129, .14);
}

.dialog-empty {
  margin: 4px 0;
  border: 1px dashed #c5d0de;
  border-radius: 12px;
  background: #f8fafc;
}

.save-row {
  background: #fff;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

.example-card:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-color: var(--focus-ring);
  box-shadow: 0 0 0 5px var(--focus-halo), 0 8px 22px rgba(37, 48, 68, .12);
}

.toast {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  padding-inline: 14px 18px;
  line-height: 1.35;
  overflow-wrap: anywhere;
}

.toast::before {
  content: 'i';
  flex: none;
  display: grid;
  place-items: center;
  width: 21px;
  height: 21px;
  border: 1px solid rgba(255, 255, 255, .55);
  border-radius: 50%;
  font-size: 12px;
  font-weight: 900;
}

.toast-ok::before { content: '\2713'; }
.toast-warn::before { content: '!'; }

@media (hover: hover) and (pointer: fine) {
  .btn:hover:not(:disabled) {
    border-color: #c5d0de;
    box-shadow: 0 3px 10px rgba(37, 48, 68, .08);
  }

  .palette-section-title:hover,
  .palette-label:hover,
  .menu-item:hover {
    background: #f2f6fa;
  }

  .save-row:hover {
    border-color: #b9c7d8;
    box-shadow: 0 5px 16px rgba(37, 48, 68, .07);
    transform: translateY(-1px);
  }
}

/* A mouse or trackpad does not need 44-46px targets. On a laptop the stage
   and workspace zoom clusters were the largest controls on screen, so on
   fine pointers (and only at desktop widths - the phone rules below 720px
   already size these) they drop to the 34px that Figma, Miro and Blockly
   use for the same job, with hover states carrying the affordance. */
@media (hover: hover) and (pointer: fine) and (min-width: 720px) {
  .stage-zoom-controls {
    right: max(14px, env(safe-area-inset-right));
    bottom: max(14px, env(safe-area-inset-bottom));
    border-radius: 11px;
    box-shadow: 0 6px 18px rgba(30, 41, 59, .14);
  }
  .stage-zoom-btn {
    width: 34px;
    height: 34px;
    font-size: 18px;
  }
  .workspace-zoom-controls { right: 12px; bottom: 12px; gap: 6px; }
  .workspace-zoom-btn {
    position: relative;
    width: 34px;
    height: 34px;
    border-width: 1.5px;
  }
  .workspace-zoom-btn svg { width: 19px; height: 19px; }
  /* Invisible inset keeps the click target at 44px while the circle is 34px. */
  .workspace-zoom-btn::after,
  .stage-zoom-btn::after {
    content: '';
    position: absolute;
    inset: -5px;
  }
  .stage-zoom-btn { position: relative; }
}

@media (max-width: 719px) {
  .toolbar {
    padding-top: max(8px, env(safe-area-inset-top));
  }

  /* The toolbox is a rail beside the workspace on a phone now, not a panel
     that owns the whole screen, so it keeps its divider. */

  .script-panel {
    gap: 5px;
  }

  .runbar {
    box-shadow: 0 -4px 16px rgba(37, 48, 68, .08);
  }

  .run-status {
    min-height: 32px;
  }

  .dialog {
    width: min(94vw, 560px);
    max-height: calc(100dvh - 24px);
    padding: 18px;
  }

  .dialog-actions {
    position: sticky;
    bottom: -18px;
    margin: 18px -18px -18px;
    padding: 12px 18px max(14px, env(safe-area-inset-bottom));
    border-top: 1px solid var(--soft-line);
    background: rgba(255, 255, 255, .96);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
  }

  .save-row {
    align-items: flex-start;
  }

  .toasts {
    left: 10px;
    right: 10px;
    transform: none;
  }

  .toast {
    width: fit-content;
    max-width: 100%;
    text-align: left;
  }
}

@media (max-width: 419px) {
  .brand-turtle {
    width: 36px;
  }

  .brand-turtle-svg {
    width: 32px;
    height: 32px;
  }

  #program-name {
    max-width: 96px;
  }

  .toolbar-actions {
    gap: 4px;
  }

  .save-row {
    flex-direction: column;
  }

  .save-actions {
    width: 100%;
  }

  .save-actions .btn:first-child {
    flex: 1;
  }

  .dialog-actions .btn {
    flex: 1;
  }
}

@media (pointer: coarse) {
  .stage-action,
  .icon-btn,
  .block-search-clear {
    min-width: 44px;
    min-height: 44px;
  }

  .block-search-clear {
    right: 31px;
  }

  .search-shortcut {
    display: none;
  }

  .block-search {
    padding-right: 51px;
  }

}

@media (prefers-contrast: more) {
  :root {
    --line: #94a3b8;
    --soft-line: #cbd5e1;
    --muted: #415269;
  }

  .btn,
  .palette-section,
  .runbar,
  .speed-control,
  .block-search {
    border-width: 2px;
  }
}

@media (forced-colors: active) {
  .block,
  .chip,
  .start-hat,
  .btn-run {
    forced-color-adjust: auto;
  }

  .workspace-surface.is-empty::before,
  .script-stack.has-hat .stack-body:empty {
    border-color: CanvasText;
  }

  .run-status::before {
    background: Highlight;
  }
}

@media (prefers-reduced-motion: reduce) {
  body.running .run-status::before,
  .dialog[open],
  .dialog[open]::backdrop,
  .file-menu[open] .file-menu-list {
    animation: none;
  }
}

/* Keep the paused state authoritative over later general running polish. */
body.running.paused .run-status {
  color: #92400e;
  background: #fffbeb;
  border-color: rgba(245, 158, 11, .28);
}

body.running.paused .run-status::before {
  background: #f59e0b;
  box-shadow: 0 0 0 4px rgba(245, 158, 11, .14);
  animation: none;
}

/* ============ project insights + Python bridge ============ */

.menu-icon-code {
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 10px;
  font-weight: 900;
  letter-spacing: -.08em;
}

.dialog-insights {
  width: min(940px, 94vw);
  max-height: min(92dvh, 900px);
}

.dialog-python {
  width: min(920px, 94vw);
  max-height: min(92dvh, 860px);
}

.dialog-insights,
.dialog-python,
.python-preview {
  scrollbar-width: thin;
  scrollbar-color: #94a3b8 transparent;
}

.insights-section-title {
  margin: 22px 0 10px;
  color: #334155;
  font-size: 13px;
  font-weight: 900;
  letter-spacing: .075em;
  text-transform: uppercase;
}

.insights-partial {
  margin: 4px 0 16px;
  padding: 11px 13px;
  border: 1px solid #fbbf24;
  border-radius: 10px;
  background: #fffbeb;
  color: #78350f;
  font-size: 13px;
  font-weight: 650;
  line-height: 1.45;
}

.insights-summary {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
}

.insight-metric {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 13px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 4px 14px rgba(37, 48, 68, .055);
}

.insight-metric-icon {
  flex: none;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: #ecfdf5;
  color: var(--accent-dark);
  font-size: 17px;
  font-weight: 900;
}

.insight-metric-copy {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.insight-metric-copy strong {
  overflow: hidden;
  color: #172033;
  font-size: 19px;
  line-height: 1.1;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.insight-metric-copy span {
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 700;
}

.insights-complexity-card {
  margin-top: 14px;
  padding: clamp(14px, 2.2vw, 20px);
  border: 1px solid #c7d2fe;
  border-radius: 14px;
  background:
    radial-gradient(circle at 100% 0, rgba(99, 102, 241, .12), transparent 38%),
    linear-gradient(145deg, #f8fafc, #eef2ff);
}

.insights-complexity-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.insights-kicker {
  color: #6366f1;
  font-size: 10.5px;
  font-weight: 900;
  letter-spacing: .09em;
  text-transform: uppercase;
}

.insights-complexity-heading h3 {
  margin: 3px 0 0;
  font-size: 17px;
}

.insights-complexity-rating {
  flex: none;
  padding: 6px 10px;
  border: 1px solid #c7d2fe;
  border-radius: 999px;
  background: rgba(255, 255, 255, .76);
  color: #4338ca;
  font-size: 12px;
}

.insights-complexity-meter {
  height: 9px;
  margin: 15px 0 10px;
  overflow: hidden;
  border-radius: 999px;
  background: rgba(99, 102, 241, .14);
  box-shadow: inset 0 1px 2px rgba(37, 48, 68, .08);
}

.insights-complexity-meter span {
  display: block;
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, #10b981, #6366f1);
  transition: width .35s cubic-bezier(.2, .8, .2, 1);
}

.insights-complexity-copy {
  margin: 0;
  color: #475569;
  font-size: 12.5px;
  line-height: 1.5;
}

.insights-inline-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 14px 0 0;
}

.insights-inline-stats > div {
  min-width: 0;
  padding: 9px 10px;
  border: 1px solid rgba(165, 180, 252, .62);
  border-radius: 9px;
  background: rgba(255, 255, 255, .64);
}

.insights-inline-stats dt {
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 750;
}

.insights-inline-stats dd {
  margin: 2px 0 0;
  overflow-wrap: anywhere;
  color: #312e81;
  font-size: 12px;
  font-weight: 850;
}

.insights-concepts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.insight-concept {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  padding: 7px 10px;
  border: 1px solid #d8e0eb;
  border-radius: 10px;
  background: #fff;
}

.insight-concept::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #94a3b8;
  box-shadow: 0 0 0 3px rgba(148, 163, 184, .15);
}

.insight-concept-explored::before { background: #0ea5e9; box-shadow: 0 0 0 3px rgba(14, 165, 233, .14); }
.insight-concept-practiced::before { background: var(--accent); box-shadow: 0 0 0 3px rgba(16, 185, 129, .15); }
.insight-concept strong { font-size: 12.5px; }
.insight-concept span { color: var(--muted); font-size: 10.5px; font-weight: 700; text-transform: capitalize; }

.insights-details {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
}

.insight-detail {
  position: relative;
  min-width: 0;
  padding: 13px 13px 12px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #fff;
}

.insight-detail::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: #94a3b8;
}

.insight-detail-good::before { background: var(--accent); }
.insight-detail-team::before { background: #6366f1; }
.insight-detail-attention::before { background: #f59e0b; }
.insight-detail-label { display: block; color: var(--muted); font-size: 10.5px; font-weight: 800; text-transform: uppercase; }
.insight-detail strong { display: block; margin-top: 4px; font-size: 14px; }
.insight-detail p { margin: 5px 0 0; color: var(--muted); font-size: 11.5px; line-height: 1.4; }

.insights-recommendations {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.insight-recommendation {
  min-width: 0;
  padding: 13px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #fff;
}

.insight-recommendation-heading {
  display: flex;
  align-items: center;
  gap: 8px;
}

.insight-priority {
  flex: none;
  padding: 3px 7px;
  border-radius: 999px;
  background: #eef2f7;
  color: #475569;
  font-size: 9.5px;
  font-weight: 900;
  letter-spacing: .035em;
  text-transform: uppercase;
}

.insight-recommendation-fix .insight-priority { background: #fef2f2; color: #b91c1c; }
.insight-recommendation-next .insight-priority { background: #eff6ff; color: #1d4ed8; }
.insight-recommendation-improve .insight-priority { background: #fffbeb; color: #92400e; }
.insight-recommendation-celebrate .insight-priority { background: #ecfdf5; color: #047857; }
.insight-recommendation-heading strong { font-size: 13.5px; }
.insight-recommendation p { margin: 8px 0 7px; color: var(--muted); font-size: 12px; line-height: 1.45; }
.insight-action { display: block; color: #334155; font-size: 11.5px; font-weight: 800; line-height: 1.4; }

.insights-empty {
  grid-column: 1 / -1;
  margin: 0;
  padding: 14px;
  border: 1px dashed #c5d0de;
  border-radius: 10px;
  background: #f8fafc;
  color: var(--muted);
  font-size: 12.5px;
  text-align: center;
}

.insights-actions,
.python-actions {
  align-items: center;
}

.insights-privacy {
  margin-right: auto;
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 700;
}

.python-preview-meta {
  min-height: 38px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 12px;
  border: 1px solid #1e293b;
  border-bottom: 0;
  border-radius: 12px 12px 0 0;
  background: #172033;
  color: #dbeafe;
  font-size: 11px;
  font-weight: 700;
}

.python-preview-meta > span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.python-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #34d399;
  box-shadow: 0 0 0 3px rgba(52, 211, 153, .16);
}

.python-preview {
  width: 100%;
  height: clamp(300px, 52dvh, 520px);
  display: block;
  resize: vertical;
  border: 1px solid #1e293b;
  border-radius: 0 0 12px 12px;
  padding: 16px 18px;
  outline: 0;
  background: #0f172a;
  color: #dbeafe;
  caret-color: #34d399;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  font-size: 12.5px;
  line-height: 1.6;
  tab-size: 4;
  white-space: pre;
}

.python-preview:focus-visible {
  border-color: #60a5fa;
  box-shadow: 0 0 0 4px rgba(37, 99, 235, .2);
}

.python-note {
  display: flex;
  align-items: flex-start;
  gap: 7px;
  margin: 10px 2px 0;
  color: var(--muted);
  font-size: 11.5px;
  line-height: 1.45;
}

@media (max-width: 820px) {
  .insights-summary,
  .insights-details {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 600px) {
  .dialog-insights,
  .dialog-python {
    width: calc(100vw - 18px);
    max-height: calc(100dvh - 18px);
  }

  .insights-summary,
  .insights-inline-stats,
  .insights-details,
  .insights-recommendations {
    grid-template-columns: 1fr;
  }

  .insights-section-title { margin-top: 18px; }
  .insight-metric { padding: 10px 11px; }
  .insight-metric-icon { width: 32px; height: 32px; }
  .insight-metric-copy strong { font-size: 17px; }
  .insights-complexity-heading { align-items: center; }

  .insight-concept {
    width: 100%;
    justify-content: flex-start;
  }

  .insight-concept span { margin-left: auto; }

  .insights-privacy {
    width: 100%;
    margin: 0 0 4px;
    text-align: center;
  }

  .python-preview-meta {
    align-items: flex-start;
    flex-direction: column;
    gap: 3px;
    padding-block: 8px;
  }

  .python-preview {
    height: min(46dvh, 430px);
    min-height: 250px;
    padding: 13px;
    font-size: 11.5px;
  }

  .python-actions {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .python-actions .btn:first-child {
    grid-column: 1 / -1;
    order: 3;
  }
}

@media (prefers-reduced-motion: reduce) {
  .insights-complexity-meter span { transition: none; }
}

@media (forced-colors: active) {
  .insight-detail::before,
  .insight-concept::before,
  .python-status-dot,
  .insights-complexity-meter span {
    background: Highlight;
  }
}

/* ---------- picture block + picture dialog ---------- */

/* The Picture param is a thumbnail plus a button, not a text box: the stored
   outline is thousands of characters and there is nothing useful to type. It
   has to sit inside the same 28px pill every other param uses, so the
   thumbnail is sized to the pill rather than to the dialog. */
.param-sketch {
  gap: 5px;
  padding-left: 3px;
  padding-right: 3px;
}

.param-sketch-thumb {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: #fff;
  border: 1px solid rgba(255, 255, 255, .6);
  flex: 0 0 auto;
}

.block .param-sketch-btn {
  font: inherit;
  font-size: 11px;
  font-weight: 800;
  line-height: 1;
  min-height: 22px;
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px solid var(--block-edge);
  background: rgba(255, 255, 255, .92);
  color: var(--ink);
  text-shadow: none;
  cursor: pointer;
  white-space: nowrap;
}

.block .param-sketch-btn:hover { background: #fff; }

.block .param-sketch-btn:focus-visible {
  outline: 2px solid var(--block-accent);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--block-ring);
}

.sketch-body {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) minmax(240px, 1.2fr);
  gap: 18px;
  align-items: start;
  margin: 4px 0 14px;
}

.sketch-left {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sketch-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 20px 14px;
  border: 2px dashed var(--line);
  border-radius: 14px;
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
  text-align: center;
}

.sketch-drop:hover,
.sketch-drop.is-over {
  border-color: var(--accent);
  background: var(--math-tint);
}

.sketch-drop-icon { font-size: 1.6rem; }

.sketch-drop-hint {
  font-size: 0.78rem;
  color: var(--muted);
}

.sketch-control {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.85rem;
}

.sketch-control-name {
  flex: 0 0 74px;
  color: var(--muted);
}

.sketch-control select,
.sketch-control input[type="range"] {
  flex: 1 1 auto;
  min-width: 0;
}

.sketch-right {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
}

.sketch-preview {
  width: 100%;
  max-width: 320px;
  aspect-ratio: 1 / 1;
  height: auto;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}

.sketch-status {
  margin: 0;
  font-size: 0.8rem;
  color: var(--muted);
  text-align: center;
  min-height: 1.2em;
}

.sketch-status-warn { color: var(--danger); }

/* ---------- style cards ---------- */

.sketch-styles {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin: 0;
  padding: 0;
  border: 0;
}

.sketch-style-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 8px 4px 7px;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  cursor: pointer;
  text-align: center;
  transition: border-color .12s, box-shadow .12s, transform .06s;
}

.sketch-style-card:hover { border-color: var(--accent); }
.sketch-style-card:active { transform: translateY(1px); }

/* the real radio is visually hidden but keeps keyboard + reader semantics */
.sketch-style-card input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  clip-path: inset(50%);
  overflow: hidden;
}

/* selection is a JS-toggled class rather than :has(), so the cards work on
   every browser the rest of the app supports */
.sketch-style-card.is-selected {
  border-color: var(--accent-dark);
  background: var(--math-tint);
  box-shadow: 0 0 0 2px rgba(4, 120, 87, .18);
}

.sketch-style-card:focus-within {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.sketch-style-art {
  position: relative;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
}

.sketch-style-thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: var(--radius-sm);
  background: #fff;
  border: 1px solid var(--soft-line);
  opacity: 0;
  transition: opacity .18s;
}

.sketch-style-card.has-thumb .sketch-style-thumb { opacity: 1; }

.sketch-style-emoji { font-size: 1.35rem; }
.sketch-style-card.has-thumb .sketch-style-emoji { visibility: hidden; }

.sketch-style-name {
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--ink);
}

/* ---------- drop zone with picture ---------- */

.sketch-drop-thumb {
  width: 120px;
  max-width: 70%;
  height: auto;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: #fff;
  box-shadow: var(--shadow-soft);
}

.sketch-drop.has-picture {
  padding: 12px 14px 10px;
  border-style: solid;
}

@media (max-width: 620px) {
  .sketch-body { grid-template-columns: 1fr; }
  /* Stacked, a full-width square preview pushes Use this picture off screen,
     so cap its height and let the square shrink to match. */
  .sketch-preview {
    width: auto;
    max-width: 100%;
    max-height: 26vh;
  }
  .sketch-drop { padding: 10px 12px 8px; }
  .sketch-styles { grid-template-columns: repeat(2, 1fr); }
  /* Phones: everything shrinks a notch so Cancel / Use this picture stay
     above the mobile tab bar instead of scrolling out of reach. */
  .sketch-drop-thumb { width: 64px; }
  .sketch-drop-hint { display: none; }
  /* the intro sentence is a luxury a phone screen cannot afford */
  .dialog-sketch .dialog-hint { display: none; }
  .sketch-style-card { padding: 6px 4px 5px; }
  .sketch-style-art { width: 36px; height: 36px; }
  .sketch-style-emoji { font-size: 1.15rem; }
  .sketch-preview { max-height: 19vh; }
}

.sketch-check-body {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.82rem;
  color: var(--muted);
}

.sketch-check-body input { margin: 0; }
