:root {
  color-scheme: dark;
  --bg: #080c14;
  --surface: #101722;
  --surface-raised: #172131;
  --surface-hover: #1d2a3d;
  --text: #e6edf7;
  --text-muted: #98a7bd;
  /* The dimmest text tier still has to be *readable* — it labels the stat
     chips, inspector notes and example descriptions at 10–11px. Kept a clear
     step below --text-muted while clearing 4.5:1 on --surface-raised. */
  --text-dim: #8595ac;
  --border: #243247;
  --border-light: #33445f;
  --accent: #6ea8fe;
  --accent-hover: #93bdff;
  --accent-strong: #3478dd;
  --success: #46d7a0;
  --warning: #f8be5d;
  --error: #ff7785;
  --code-bg: #0b111b;
  --code-gutter: #0f1724;
  /* Syntax palette. These values used to be literal hex on the .cm-* rules,
     which caused two separate problems: the tokens could not follow a theme
     (on the four light themes a dark-theme palette is unreadable), and the
     rules were losing outright to CodeMirror's own .cm-s-default palette —
     see the specificity note above the .cm-* block. Themes override these
     tokens instead (see "Syntax palettes per theme" below). */
  --syn-keyword: #c792ea;
  --syn-number: #f7c66a;
  --syn-type: #7dcfff;
  --syn-string: #a7db8d;
  --syn-comment: #71809a;
  --syn-operator: #f29e9e;
  --syn-builtin: #6ee7c0;
  --syn-meta: #f5a3d7;
  --shadow: 0 12px 32px rgba(0, 0, 0, .2);
  --shadow-lg: 0 24px 64px rgba(0, 0, 0, .34);
  --gradient-bg: linear-gradient(112deg, #101a2b, #0b101b 60%, #0a1622);
  --radius: 14px;
  /* Two smaller radii that recur throughout the panel/card and pill/badge
     components (introduced as tokens rather than restating the literal
     value at each of their many call sites). */
  --radius-card: 9px;
  --radius-pill: 999px;
  --mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  /* Single source of truth for the editor's height. Overridden per
     breakpoint (see the media queries below) instead of restating the same
     four-selector list (.editor-container, .CodeMirror, .CodeMirror-scroll,
     #src) at every width. */
  --editor-min-h: clamp(480px, calc(100vh - 170px), 720px);
  /* iOS safe-area insets (notch / home indicator). Zero on every other
     platform; only non-zero here when the viewport meta has viewport-fit=cover. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html { min-height: 100%; background: var(--bg); }

body {
  min-width: 320px;
  margin: 0;
  background:
    radial-gradient(circle at 12% -12%, rgba(65, 130, 255, .2), transparent 28rem),
    radial-gradient(circle at 94% 8%, rgba(70, 215, 160, .09), transparent 24rem),
    var(--bg);
  color: var(--text);
  font: 15px/1.5 Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  /* Padding, not the old 100vh trick: keeps content clear of the iPhone home
     indicator / rounded corners without fighting Safari's dynamic toolbar. */
  padding-left: var(--safe-left);
  padding-right: var(--safe-right);
  padding-bottom: var(--safe-bottom);
}

button, input, select { font: inherit; }

@media (hover: none) and (pointer: coarse) {
  /* Touch devices: a light press-down replaces the (absent) hover state so
     taps still feel responsive, and every tap target clears Apple's 44pt
     minimum. Scoped to coarse pointers so mouse/trackpad users keep the
     existing hover-only feedback untouched. */
  button:not(:disabled):active, .upload-control:active, .header-link:active,
  .example-item:active, .tag-btn:active, .output-tab:active, .examples-toggle-label:active {
    background: var(--surface-hover);
    transform: scale(.97);
  }
  button, select, .upload-control, .header-link, .examples-toggle-label, .control-settings > summary { min-height: 44px; }
}

button, select, .upload-control {
  min-height: 36px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-raised);
  color: var(--text);
  cursor: pointer;
  transition: background .16s ease, border-color .16s ease, transform .16s ease, box-shadow .16s ease;
}

button:hover, select:hover, .upload-control:hover {
  border-color: var(--border-light);
  background: var(--surface-hover);
}

button:focus-visible, input:focus-visible, select:focus-visible, summary:focus-visible, .upload-control:focus-within, .header-link:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--accent) 48%, transparent);
  outline-offset: 2px;
}

button:disabled { cursor: not-allowed; opacity: .45; transform: none; }

.header {
  position: sticky;
  top: 0;
  z-index: 20;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
  background: color-mix(in srgb, var(--bg) 84%, transparent);
  backdrop-filter: blur(18px);
}

.header-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: min(1720px, 100%);
  min-height: 56px;
  margin: 0 auto;
  padding: max(8px, var(--safe-top)) max(clamp(14px, 2.4vw, 30px), calc(var(--safe-right) + 14px)) 8px max(clamp(14px, 2.4vw, 30px), calc(var(--safe-left) + 14px));
  gap: 12px;
}

.brand { display: flex; align-items: center; gap: 10px; min-width: 0; font-weight: 760; letter-spacing: -.02em; font-size: 20px; }
.brand img { width: 30px; height: 30px; filter: drop-shadow(0 4px 10px rgba(110, 168, 254, .22)); }
.brand-subtitle { padding-left: 12px; border-left: 1px solid var(--border); color: var(--text-muted); font-size: 13px; font-weight: 500; letter-spacing: 0; }

.header-actions { position: relative; display: flex; align-items: center; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }
.header-actions > button, .upload-control { padding: 7px 10px; font-size: 13px; }
.upload-control { display: inline-flex; align-items: center; gap: 5px; }
.upload-control input { display: none; }
.header-link { padding: 7px 10px; color: var(--text-muted); font-size: 13px; text-decoration: none; }
.header-link:hover { color: var(--accent-hover); }

/* Hidden below the phone breakpoint (see media query) so header/controls
   collapse to icon-only buttons; kept in the DOM (not display:none on the
   button) so title="" tooltips and screen readers still get the full name. */
.btn-label { white-space: nowrap; }
.shortcut-hint { color: inherit; opacity: .8; font-weight: 500; }

.theme-popup {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 30;
  display: none;
  width: min(330px, calc(100vw - 28px));
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
}
.theme-popup[aria-hidden="false"] { display: block; }
.theme-popup-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px; }
.theme-option { display: flex; align-items: center; min-height: 38px; padding: 6px 8px; text-align: left; }
.theme-option[aria-pressed="true"] { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
/* Brief highlight flash (added, then removed ~400ms later by JS) so a
   reopened popup draws the eye straight to the already-selected theme. */
.theme-option.focused { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 55%, transparent); }
.theme-option .swatch { width: 24px; height: 24px; margin-right: 8px; border-radius: 6px; }
.theme-option .label { font-size: 12px; }

/* Share & Embed popup — reuses .theme-popup's positioning/box but needs a
   column layout instead of the theme grid. */
.embed-popup { display: none; width: min(360px, calc(100vw - 28px)); }
.embed-popup[aria-hidden="false"] { display: block; }
.embed-popup-title { margin: 2px 2px 2px; font-size: 13px; font-weight: 700; }
.embed-popup-sub { margin: 0 2px 10px; color: var(--text-muted); font-size: 11px; line-height: 1.5; }
.embed-options { display: flex; flex-wrap: wrap; gap: 12px; margin: 0 2px 10px; }
.embed-option { display: inline-flex; align-items: center; gap: 6px; color: var(--text-muted); font-size: 12px; cursor: pointer; }
.embed-snippet { width: 100%; margin-bottom: 8px; padding: 8px 9px; border: 1px solid var(--border); border-radius: 8px; resize: vertical; background: var(--code-bg); color: var(--text-muted); font-family: var(--mono); font-size: 11px; line-height: 1.5; }
.embed-popup-actions { display: flex; gap: 8px; margin-bottom: 10px; }
.embed-popup-hint { margin: 0 2px; color: var(--text-dim); font-size: 10.5px; line-height: 1.5; }
.embed-popup-hint code { padding: 1px 4px; border-radius: 4px; background: var(--code-bg); color: var(--accent-hover); font-family: var(--mono); }
.embed-popout-link { display: none; }

/* Embed mode (?embed=1): a compact, iframe-friendly layout — sidebar,
   promo panel, and the advanced inspector go away; only the editor and a
   single output panel remain, stacked in one column so it stays readable
   at typical embed widths (a few hundred px tall in a blog post). */
body.mode-embed .sidebar,
body.mode-embed .sidebar-backdrop,
body.mode-embed .sidebar-toggle-btn,
body.mode-embed .header-link:not(.embed-popout-link),
body.mode-embed #shareBtn,
body.mode-embed #embedBtn,
body.mode-embed #downloadBtn,
body.mode-embed .upload-control,
body.mode-embed #vetBtn,
body.mode-embed #inspectBtn,
body.mode-embed .output-tab[data-output="inspector"],
body.mode-embed .brand-subtitle {
  display: none;
}
body.mode-embed .embed-popout-link { display: inline-flex; }
body.mode-embed .main { grid-template-areas: "editor" "output"; grid-template-columns: 1fr; padding: 12px; gap: 10px; }
body.mode-embed .header-content { min-height: 48px; padding: 8px 12px; }
body.mode-embed { --editor-min-h: 260px; }
body.mode-embed .output-panel.active { min-height: 180px; }
body.mode-embed #log { height: min(40vh, 260px); }
body.mode-embed .canvas-container, body.mode-embed #output { min-height: 180px; }

/* The sidebar is a drawer overlay (below), not a grid column, so .main only
   ever has to lay out two things — editor and output — instead of the old
   three-column-plus-collapsing-sidebar arrangement. */
.main {
  display: grid;
  grid-template-areas: "editor output";
  grid-template-columns: minmax(520px, 1fr) minmax(330px, 440px);
  align-items: start;
  width: min(1720px, 100%);
  margin: 0 auto;
  padding: clamp(10px, 1.5vw, 20px) clamp(12px, 2.2vw, 30px) 28px;
  gap: clamp(12px, 1.4vw, 20px);
}
.editor-section { grid-area: editor; }
.output-section { grid-area: output; }
.editor-section, .output-section { min-width: 0; }

/* Sidebar drawer: fixed overlay below the sticky header, sliding in from the
   left. Deliberately an overlay rather than a grid column that pushes
   content — opening it never reflows the editor/CodeMirror underneath, and
   it works identically at every viewport width instead of needing its own
   responsive column-count logic the way the old always-present sidebar did. */
.sidebar {
  position: fixed;
  top: var(--header-h, 56px);
  left: 0;
  bottom: 0;
  z-index: 25;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(330px, 88vw);
  padding: 12px;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  background: var(--surface);
  border-right: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  transform: translateX(-100%);
  transition: transform .22s ease;
}
.sidebar.open { transform: translateX(0); }
.sidebar-drawer-head { display: flex; justify-content: flex-end; }
.sidebar-toggle-btn { margin-right: 2px; font-size: 15px; }

.sidebar-backdrop {
  position: fixed;
  top: var(--header-h, 56px);
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 24;
  background: rgba(3, 6, 12, .5);
  opacity: 0;
  pointer-events: none;
  transition: opacity .22s ease;
}
.sidebar-backdrop.open { opacity: 1; pointer-events: auto; }

.examples-panel, .output-panel {
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  box-shadow: var(--shadow);
}
/* The examples panel is now the sidebar drawer's only content (the old Demo
   Info and "Why nanoGo" panels are gone) — it grows to use the drawer's
   full height instead of leaving empty space below a short list. */
.examples-panel { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.sidebar .examples-panel { border: 0; border-radius: 0; background: transparent; box-shadow: none; }

.panel-header, .output-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 40px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--surface-raised) 82%, transparent);
  color: var(--text);
  font-size: 13px;
  font-weight: 700;
}

/* Examples panel collapse toggle — a checkbox + label, no JS. The checkbox
   itself is visually hidden (but stays focusable/tabbable via the label's
   `for`); only the phone media query below actually makes it collapse the
   body, so desktop/tablet keep the always-expanded layout untouched. */
.examples-toggle-input { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.examples-toggle-label { width: 100%; cursor: pointer; }
/* The chevron only means something where the collapse behavior is actually
   active (see the max-width:640px query) — hidden otherwise so a wider
   viewport doesn't show an inert "closed" arrow above always-expanded content. */
.examples-chevron { display: none; color: var(--text-dim); font-size: 11px; transition: transform .18s ease; }
.examples-panel-body { display: flex; flex-direction: column; flex: 1; min-height: 0; }

.example-search {
  width: calc(100% - 28px);
  margin: 9px 14px 8px;
  padding: 9px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  outline: none;
  background: var(--code-bg);
  color: var(--text);
}
.example-search::placeholder { color: var(--text-dim); }
.example-search:focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent); }

.tag-filters { display: flex; flex-wrap: wrap; gap: 5px; padding: 0 14px 8px; }
.tag-btn { min-height: 26px; padding: 3px 8px; border-radius: var(--radius-pill); color: var(--text-muted); font-size: 11px; }
.tag-btn.active { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 20%, var(--surface-raised)); color: var(--accent-hover); }

.examples-list { flex: 1; min-height: 0; overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; border-top: 1px solid var(--border); }
/* Category headers shown when browsing the full unfiltered list (see
   showGroups in fillExamples) — sticky so the current category stays
   visible while scrolling a list of 50+ demos. */
.example-group-header { position: sticky; top: 0; z-index: 1; padding: 7px 13px 6px; background: color-mix(in srgb, var(--surface-raised) 96%, transparent); backdrop-filter: blur(6px); color: var(--text-dim); font-size: 10.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; border-bottom: 1px solid color-mix(in srgb, var(--border) 65%, transparent); }
.example-group-header:first-child { border-top: 0; }
.example-item { display: flex; align-items: center; justify-content: space-between; width: 100%; gap: 8px; padding: 11px 13px; border: 0; border-bottom: 1px solid color-mix(in srgb, var(--border) 65%, transparent); border-radius: 0; background: transparent; text-align: left; }
.example-item:hover { background: var(--surface-raised); }
.example-item.active { background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 24%, var(--surface)), var(--surface-raised)); box-shadow: inset 3px 0 var(--accent), inset 0 1px color-mix(in srgb, var(--accent) 14%, transparent); }
.example-info { min-width: 0; }
.example-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 680; }
.example-desc { display: -webkit-box; overflow: hidden; margin-top: 2px; color: var(--text-muted); font-size: 11px; line-height: 1.35; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.example-badge { flex: 0 0 auto; padding: 3px 6px; border: 1px solid var(--border); border-radius: 5px; color: var(--text-muted); font-size: 10px; font-weight: 650; letter-spacing: .02em; }
.example-tags { display: flex; max-width: 124px; flex: 0 1 auto; justify-content: flex-end; gap: 4px; flex-wrap: wrap; }
.copy-btn { min-height: 27px; padding: 3px 7px; font-size: 11px; }

/* Stretched (not align-items:start like its siblings) so its box is always
   at least as tall as the tallest column. position:sticky's containing
   block is this element, not the viewport — if it stayed short, the sticky
   toolbar inside would run out of room to stick to and vanish partway down
   a long page (e.g. a long Examples list making the sidebar the tallest
   column). See setupStickyOffsets() in index.html for the matching --header-h
   var. */
.editor-section { display: grid; align-self: stretch; align-content: start; gap: 8px; }

.status { display: inline-flex; align-items: center; gap: 7px; padding: 6px 9px; border: 1px solid var(--border); border-radius: var(--radius-pill); color: var(--text-muted); font-size: 12px; white-space: nowrap; }
.status-indicator { width: 7px; height: 7px; border-radius: 50%; background: var(--warning); }
.status.loading { color: var(--warning); } .status.loading .status-indicator { background: var(--warning); animation: pulse 1.35s ease-in-out infinite; }
.status.ready { color: var(--success); } .status.ready .status-indicator { background: var(--success); }
.status.error { color: var(--error); } .status.error .status-indicator { background: var(--error); }
@keyframes pulse { 50% { opacity: .4; transform: scale(.8); } }

/* Sticky so Run/Stop/Vet/Test/Inspect and the other controls stay reachable
   no matter how far the page (or a long code sample / output panel) is
   scrolled — see setupStickyOffsets(), which keeps --header-h in sync with
   the actual (variable-height) site header above it. Now the first element
   in .editor-section (the old title/status editor-header row was removed),
   so it also carries that row's top-left accent marker. */
.controls {
  position: sticky;
  top: var(--header-h, 64px);
  z-index: 14;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}
.controls::before { position: absolute; top: 0; left: 0; width: 46px; height: 2px; border-radius: 0 0 3px 0; background: linear-gradient(90deg, var(--success), var(--accent)); content: ""; }
.controls > button { padding: 6px 9px; font-size: 12px; }
.controls .primary { border-color: var(--accent-strong); background: var(--accent-strong); color: white; font-weight: 700; }
.controls .primary:hover { border-color: var(--accent); background: var(--accent); transform: translateY(-1px); box-shadow: 0 7px 16px rgba(52, 120, 221, .25); }
.control-settings { position: relative; }
.control-settings > summary { min-height: 32px; padding: 6px 9px; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--surface-raised); color: var(--text-muted); cursor: pointer; font-size: 12px; list-style: none; }
.control-settings > summary::-webkit-details-marker { display: none; }
.control-settings[open] > summary { border-color: var(--accent); background: var(--surface-hover); color: var(--accent-hover); }
.control-settings-menu { position: absolute; top: calc(100% + 7px); right: 0; z-index: 20; display: grid; gap: 9px; width: min(280px, calc(100vw - 28px)); padding: 10px; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--surface); box-shadow: var(--shadow-lg); }
.input-group { display: grid; gap: 4px; color: var(--text-muted); font-size: 11px; }
.input-group select, .input-group input { min-height: 32px; max-width: 92px; padding: 4px 7px; font-size: 12px; }
.control-settings-menu .input-group select, .control-settings-menu .input-group input { width: 100%; max-width: none; }
.controls .status { margin-left: auto; }

.editor-container { min-height: var(--editor-min-h); overflow: hidden; border: 1px solid var(--border); border-radius: var(--radius); background: var(--code-bg); box-shadow: var(--shadow-lg), 0 0 0 1px color-mix(in srgb, var(--accent) 5%, transparent); }
#src { width: 100%; min-height: var(--editor-min-h); padding: 16px; resize: vertical; border: 0; outline: 0; background: var(--code-bg); color: var(--text); font-family: var(--mono); line-height: 1.6; }

/* Compact IDE workspace strip. It adds project context without stealing the
   editor's vertical budget: tabs scroll horizontally and actions stay on the
   right on wide screens, then wrap only on narrow phones. */
.workspace-bar { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 7px; min-width: 0; padding: 4px 6px; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--surface); box-shadow: var(--shadow); }
.workspace-project { display: inline-flex; align-items: center; gap: 6px; min-width: 0; color: var(--text); font-size: 11px; font-weight: 750; white-space: nowrap; }
.workspace-project-icon { font-size: 14px; }
.workspace-status { max-width: 210px; overflow: hidden; color: var(--text-dim); font-family: var(--mono); font-size: 10px; font-weight: 500; text-overflow: ellipsis; }
.workspace-tabs { display: flex; gap: 3px; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.workspace-tabs::-webkit-scrollbar { display: none; }
.workspace-tab { flex: 0 0 auto; min-height: 27px; max-width: 180px; padding: 3px 8px; overflow: hidden; border: 1px solid transparent; border-radius: 6px; background: transparent; color: var(--text-muted); font-family: var(--mono); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
.workspace-tab:hover { background: var(--surface-hover); color: var(--text); }
.workspace-tab.active { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); background: color-mix(in srgb, var(--accent) 13%, var(--surface-raised)); color: var(--accent-hover); }
.workspace-actions { display: inline-flex; align-items: center; gap: 4px; }
.workspace-actions .mini-btn { min-height: 27px; padding: 3px 7px; font-size: 11px; }
.workspace-run-btn.active { border-color: color-mix(in srgb, var(--success) 55%, var(--border)); color: var(--success); }

/* CodeMirror: Go mode supplies the token classes; these rules make syntax
   highlighting and the numbered gutter visible in every playground theme. */
.CodeMirror { height: var(--editor-min-h); background: var(--code-bg); color: var(--text); font-family: var(--mono); line-height: 1.6; }
.CodeMirror-scroll { min-height: var(--editor-min-h); }
.CodeMirror-gutters { border-right: 1px solid var(--border); background: var(--code-gutter); }
.CodeMirror-linenumber { min-width: 34px; padding: 0 8px 0 6px; color: var(--text-dim); font-family: var(--mono); font-size: .9em; }
.CodeMirror-cursor { border-left-color: var(--accent-hover); }
.CodeMirror-selected { background: color-mix(in srgb, var(--accent) 24%, transparent) !important; }
.CodeMirror-activeline-background { background: color-mix(in srgb, var(--surface-raised) 55%, transparent); }
.cm-symbol-highlight {
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 78%, transparent);
  border-radius: 3px;
  background: color-mix(in srgb, var(--accent) 13%, transparent);
}
.cm-symbol-selected {
  border-bottom: 2px solid var(--warning);
  border-radius: 3px;
  background: color-mix(in srgb, var(--warning) 24%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--warning) 10%, transparent);
}
/* Ambient marker for the line a run's error was reported at (see
   highlightErrorLine) — a left-edge accent bar plus a faint tint, distinct
   enough from CodeMirror-activeline-background to read clearly even when
   the cursor happens to already be on the same line. Cleared on the next
   run or the next edit (see clearErrorHighlight). */
.cm-error-line { position: relative; background: color-mix(in srgb, var(--error) 12%, transparent) !important; }
.cm-error-line::before { position: absolute; top: 0; bottom: 0; left: 0; width: 3px; background: var(--error); content: ""; }

/* Line-execution heatmap (see applyHeatmap in index.html). Log-scaled
   buckets 1 (barely executed) through 10 (hottest) — warm color, growing
   from a faint tint to solid, drifting from --warning into --error at the
   very top so the single hottest lines read as unmistakably "hot". Uses
   the same 'wrap' line-class mechanism as .cm-error-line (see its comment):
   the 'background' line class measures zero height with lineWrapping on. */
.cm-heat-1  { background: color-mix(in srgb, var(--warning) 7%,  transparent) !important; }
.cm-heat-2  { background: color-mix(in srgb, var(--warning) 14%, transparent) !important; }
.cm-heat-3  { background: color-mix(in srgb, var(--warning) 22%, transparent) !important; }
.cm-heat-4  { background: color-mix(in srgb, var(--warning) 31%, transparent) !important; }
.cm-heat-5  { background: color-mix(in srgb, var(--warning) 41%, transparent) !important; }
.cm-heat-6  { background: color-mix(in srgb, var(--warning) 52%, transparent) !important; }
.cm-heat-7  { background: color-mix(in srgb, var(--warning) 64%, transparent) !important; }
.cm-heat-8  { background: color-mix(in srgb, var(--error) 25%, color-mix(in srgb, var(--warning) 70%, transparent)) !important; }
.cm-heat-9  { background: color-mix(in srgb, var(--error) 55%, transparent) !important; }
.cm-heat-10 { background: color-mix(in srgb, var(--error) 80%, transparent) !important; }

.heatmap-list { padding: 4px 12px 12px; max-height: 320px; overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.heatmap-loc { font-weight: 700; }
.heat-bar { display: inline-block; width: 56px; height: 9px; border-radius: 3px; background: var(--border); }
.heat-bar-1  { width: 12%; background: color-mix(in srgb, var(--warning) 35%, var(--border)); }
.heat-bar-2  { width: 20%; background: color-mix(in srgb, var(--warning) 45%, var(--border)); }
.heat-bar-3  { width: 30%; background: color-mix(in srgb, var(--warning) 55%, var(--border)); }
.heat-bar-4  { width: 40%; background: color-mix(in srgb, var(--warning) 65%, var(--border)); }
.heat-bar-5  { width: 52%; background: var(--warning); }
.heat-bar-6  { width: 64%; background: var(--warning); }
.heat-bar-7  { width: 76%; background: color-mix(in srgb, var(--error) 35%, var(--warning)); }
.heat-bar-8  { width: 86%; background: color-mix(in srgb, var(--error) 60%, var(--warning)); }
.heat-bar-9  { width: 94%; background: color-mix(in srgb, var(--error) 85%, var(--warning)); }
.heat-bar-10 { width: 100%; background: var(--error); }
/* These must be scoped through .cm-s-default, not written as bare `.cm-x`.
   CodeMirror's own stylesheet declares its palette as `.cm-s-default .cm-atom`
   — two classes — which outranks a single-class `.cm-atom` no matter which
   stylesheet loads last. The bare rules that used to live here therefore lost
   to it for every token CodeMirror itself defines (keyword, atom, number, def,
   variable-2, type, comment, string, string-2, builtin, tag, meta), so the
   editor silently rendered CodeMirror's *light* default theme — #221199 atoms
   and #a11 strings — against our dark --code-bg, at ~1.2–2.7:1. Only
   .cm-operator and .cm-variable, which CodeMirror leaves unstyled, ever
   picked up the intended colors. Adding .CodeMirror keeps these ahead of it
   without resorting to !important. */
.CodeMirror.cm-s-default .cm-keyword,
.CodeMirror.cm-s-default .cm-qualifier { color: var(--syn-keyword); font-weight: 650; }
.CodeMirror.cm-s-default .cm-atom,
.CodeMirror.cm-s-default .cm-number { color: var(--syn-number); }
.CodeMirror.cm-s-default .cm-def,
.CodeMirror.cm-s-default .cm-variable-2,
.CodeMirror.cm-s-default .cm-variable-3,
.CodeMirror.cm-s-default .cm-type { color: var(--syn-type); }
.CodeMirror.cm-s-default .cm-variable,
.CodeMirror.cm-s-default .cm-property { color: var(--text); }
.CodeMirror.cm-s-default .cm-string,
.CodeMirror.cm-s-default .cm-string-2 { color: var(--syn-string); }
.CodeMirror.cm-s-default .cm-comment { color: var(--syn-comment); font-style: italic; }
.CodeMirror.cm-s-default .cm-operator { color: var(--syn-operator); }
.CodeMirror.cm-s-default .cm-builtin,
.CodeMirror.cm-s-default .cm-tag { color: var(--syn-builtin); }
.CodeMirror.cm-s-default .cm-meta { color: var(--syn-meta); }
.CodeMirror.cm-s-default .cm-bracket { color: var(--text-muted); }

.output-section { display: grid; align-self: stretch; align-content: start; gap: 8px; }
.output-panel { display: none; min-height: 240px; }
.output-panel.active { display: flex; flex-direction: column; }
.output-header { font-size: 12px; }
.output-actions { display: flex; align-items: center; gap: 7px; }
#execTime { min-width: 32px; color: var(--text-dim); font-family: var(--mono); font-size: 11px; text-align: right; }
.output-content { flex: 1; min-height: 0; padding: 9px; }
.canvas-container { display: grid; min-height: 220px; place-items: center; overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; border: 1px solid var(--border); border-radius: var(--radius-card); background: #080d13; }
#life { max-width: 100%; image-rendering: pixelated; }
#log { height: min(54vh, 560px); overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: 2px 1px; border: 1px solid transparent; border-radius: 8px; color: var(--text); font-family: var(--mono); font-size: 12px; line-height: 1.65; white-space: pre-wrap; }
/* While the console has keyboard focus, log-line fading is paused (see the
   focus/blur handlers) — this border makes that "reading mode" state visible. */
#log.focused { border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.log-line { padding: 2px 5px; border-radius: 4px; word-break: break-word; transition: opacity .3s ease; }
.log-line.log-error { color: var(--error); background: color-mix(in srgb, var(--error) 8%, transparent); }
.log-line.log-warn { color: var(--warning); }
.log-line.log-system { color: var(--text-dim); }
.log-line.fading { opacity: .58; } .log-line.old { opacity: .3; }
/* data-line, not a class: see the comment where it's set in flushLogQueue —
   the fading logic reassigns className wholesale and would drop a class. */
.log-line[data-line] { cursor: pointer; text-decoration: underline dotted color-mix(in srgb, var(--error) 55%, transparent); text-underline-offset: 2px; }
.log-line[data-line]:hover { background: color-mix(in srgb, var(--error) 16%, transparent); }
#output { min-height: 260px; overflow: auto; padding: 14px; border: 1px solid var(--border); border-radius: var(--radius-card); background: #fff; color: #172033; }
#output :first-child { margin-top: 0; }

/* On the two-column desktop layout the editor defines the working height.
   Let the active basic output use that same column instead of ending early
   and leaving a dead strip beside a long source file. Inspector/Lab/AI keep
   their own scroll and sizing rules. */
@media (min-width: 1001px) {
  #consolePanel, #canvasPanel, #domPanel, #symbolPanel { min-height: var(--editor-min-h); }
  #consolePanel > .output-content,
  #canvasPanel > .output-content,
  #domPanel > .output-content { display: flex; flex-direction: column; }
  #consolePanel #log,
  #canvasPanel .canvas-container,
  #domPanel #output { flex: 1; min-height: 0; height: auto; }
}

/* Contextual symbol inspector. It deliberately lives beside the editor in
   the existing output column, so inspecting code never covers or resizes the
   text being read. */
.symbol-content { display: grid; align-content: start; gap: 14px; overflow: auto; max-height: min(78vh, 820px); padding: 14px; }
.symbol-empty { display: grid; justify-items: center; min-height: 250px; padding: 42px 22px; text-align: center; place-content: center; }
.symbol-empty-icon { display: grid; width: 48px; height: 48px; margin-bottom: 12px; place-items: center; border: 1px solid color-mix(in srgb, var(--accent) 42%, var(--border)); border-radius: 14px; background: color-mix(in srgb, var(--accent) 10%, var(--surface-raised)); color: var(--accent-hover); font: 28px/1 var(--mono); }
.symbol-empty strong { font-size: 15px; }
.symbol-empty p { max-width: 330px; margin: 7px 0 0; color: var(--text-muted); font-size: 12px; line-height: 1.6; }
.symbol-loading { display: flex; align-items: center; gap: 12px; min-height: 160px; padding: 18px; border: 1px dashed var(--border-light); border-radius: var(--radius-card); background: var(--code-bg); }
.symbol-loading .status-indicator { flex: 0 0 auto; }
.symbol-loading p { margin: 3px 0 0; color: var(--text-muted); font-size: 11px; }
.symbol-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.symbol-heading h2 { margin: 3px 0 0; overflow-wrap: anywhere; color: var(--text); font: 750 19px/1.3 var(--mono); letter-spacing: -.02em; }
.symbol-kind { display: inline-flex; padding: 2px 7px; border: 1px solid color-mix(in srgb, var(--accent) 42%, var(--border)); border-radius: var(--radius-pill); background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--accent-hover); font-size: 9px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.symbol-kind.variable { border-color: color-mix(in srgb, var(--success) 45%, var(--border)); background: color-mix(in srgb, var(--success) 9%, transparent); color: var(--success); }
.symbol-location { color: var(--text-dim); font: 10px/1.5 var(--mono); white-space: nowrap; }
.symbol-link { min-height: 26px; max-width: 100%; padding: 3px 8px; overflow: hidden; border-color: var(--border); border-radius: 7px; background: var(--code-bg); color: var(--text-muted); font: 10.5px/1.4 var(--mono); text-align: left; text-overflow: ellipsis; white-space: nowrap; }
.symbol-link:hover { color: var(--accent-hover); }
.symbol-link.resolved { border-color: color-mix(in srgb, var(--success) 38%, var(--border)); color: var(--success); }
.symbol-link.external { border-style: dashed; color: var(--text-dim); }
.symbol-link.definition { flex: 0 0 auto; border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); color: var(--accent-hover); }
.symbol-metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.symbol-metrics span { display: grid; gap: 1px; padding: 8px 5px; border: 1px solid var(--border); border-radius: 7px; background: var(--code-bg); color: var(--text-dim); font-size: 9px; text-align: center; text-transform: uppercase; }
.symbol-metrics strong { color: var(--text); font: 750 13px var(--mono); }
.symbol-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.symbol-section { min-width: 0; padding: 10px; border: 1px solid var(--border); border-radius: var(--radius-card); background: color-mix(in srgb, var(--surface-raised) 58%, transparent); }
.symbol-section h3 { margin: 0 0 8px; color: var(--text-muted); font-size: 10px; letter-spacing: .06em; text-transform: uppercase; }
.symbol-section ul { display: grid; gap: 5px; margin: 0; padding: 0; list-style: none; }
.symbol-muted { color: var(--text-dim); font-size: 10.5px; font-style: italic; }
.symbol-value-card { overflow: hidden; border: 1px solid color-mix(in srgb, var(--success) 45%, var(--border)); border-radius: 11px; background: color-mix(in srgb, var(--success) 7%, var(--code-bg)); }
.symbol-value-card.stale { border-color: color-mix(in srgb, var(--warning) 55%, var(--border)); background: color-mix(in srgb, var(--warning) 7%, var(--code-bg)); }
.symbol-value-label { padding: 8px 11px 0; color: var(--success); font-size: 10px; font-weight: 750; letter-spacing: .04em; text-transform: uppercase; }
.symbol-value-card.stale .symbol-value-label { color: var(--warning); }
.symbol-value-card pre { max-height: 260px; margin: 0; padding: 10px 11px 12px; overflow: auto; color: var(--text); font: 700 16px/1.5 var(--mono); white-space: pre-wrap; overflow-wrap: anywhere; }
.symbol-value-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; padding: 8px 10px; border-top: 1px solid var(--border); background: color-mix(in srgb, var(--surface-raised) 72%, transparent); }
.symbol-value-meta > span { padding: 2px 6px; border: 1px solid var(--border); border-radius: var(--radius-pill); color: var(--text-muted); font: 9.5px var(--mono); }
.symbol-no-value { padding: 14px; border: 1px dashed var(--border-light); border-radius: var(--radius-card); background: var(--code-bg); }
.symbol-no-value p { margin: 4px 0 11px; color: var(--text-muted); font-size: 11px; }
.symbol-scopes { padding: 10px 12px; }
.symbol-scopes li { display: flex; align-items: center; justify-content: space-between; gap: 10px; color: var(--text-muted); font-size: 10px; }
.symbol-scopes code { max-width: 50%; overflow: hidden; color: var(--text); font: 10px var(--mono); text-overflow: ellipsis; white-space: nowrap; }
.symbol-footnote { margin: 0; color: var(--text-dim); font-size: 10px; line-height: 1.55; }

/* Output panel tabs. Always a single scrollable row rather than wrapping:
   on a phone four wrapped pill buttons would eat two lines of height for
   little benefit, while a horizontally-scrollable "segmented control" row
   is a familiar iOS pattern and costs one line regardless of width. */
.output-tabs {
  position: sticky;
  top: var(--header-h, 68px);
  z-index: 14;
  display: flex; flex-wrap: nowrap; gap: 6px; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
  padding: 4px;
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}
.output-tabs::-webkit-scrollbar { display: none; }
.output-tab { flex: 0 0 auto; min-height: 32px; padding: 5px 11px; border-radius: var(--radius-pill); color: var(--text-muted); font-size: 12px; font-weight: 650; white-space: nowrap; }
.output-tab.active { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, var(--surface-raised)); color: var(--accent-hover); }

/* Execution inspector */
.inspector-content { display: grid; gap: 12px; align-content: start; overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; max-height: min(72vh, 760px); }
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 8px; }
.stat-chip { display: grid; gap: 2px; padding: 9px 11px; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--code-bg); }
.stat-chip .stat-value { color: var(--accent-hover); font-family: var(--mono); font-size: 14px; font-weight: 700; }
.stat-chip .stat-label { color: var(--text-dim); font-size: 10px; letter-spacing: .04em; text-transform: uppercase; }

.inspector-section { border: 1px solid var(--border); border-radius: var(--radius-card); background: color-mix(in srgb, var(--surface-raised) 55%, transparent); }
.inspector-section > summary { padding: 9px 12px; cursor: pointer; user-select: none; font-size: 13px; font-weight: 700; }
.inspector-section > summary::marker { color: var(--text-dim); }
.inspector-section[open] > summary { border-bottom: 1px solid var(--border); }
.inspector-hint { margin-left: 8px; color: var(--text-dim); font-size: 11px; font-weight: 500; }
.inspector-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 10px 12px 4px; }
.workspace-inspector-actions { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; padding: 9px 12px 4px; }
.workspace-diagnostics { padding: 4px 12px 11px; color: var(--text-muted); font-size: 11px; }
.workspace-summary { display: flex; flex-wrap: wrap; gap: 7px 14px; color: var(--text-muted); font-family: var(--mono); font-size: 11px; }
.workspace-summary strong { color: var(--accent-hover); }
.workspace-package-list { display: grid; gap: 4px; margin: 8px 0 0; padding-left: 17px; }
.workspace-package-list li { min-width: 0; overflow-wrap: anywhere; }
.workspace-package-path { color: var(--text-dim); font-family: var(--mono); }
.inspector-field { display: inline-flex; align-items: center; gap: 6px; color: var(--text-muted); font-size: 12px; }
.inspector-field input[type="number"] { width: 64px; min-height: 30px; padding: 3px 7px; border: 1px solid var(--border); border-radius: 7px; background: var(--code-bg); color: var(--text); }
.inspector-note { color: var(--text-dim); font-size: 11px; }
.inspector-error { margin: 10px 12px; padding: 8px 10px; border: 1px solid color-mix(in srgb, var(--error) 45%, var(--border)); border-radius: 7px; color: var(--error); font-family: var(--mono); font-size: 12px; white-space: pre-wrap; }
.mini-btn { min-height: 30px; padding: 4px 10px; font-size: 12px; }

/* AST tree */
.ast-tree { max-height: 380px; overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: 8px 12px 12px; font-family: var(--mono); font-size: 12px; line-height: 1.7; }
.ast-node > summary { cursor: pointer; user-select: none; list-style-position: outside; }
.ast-node > summary::marker { color: var(--text-dim); font-size: 10px; }
.ast-children { margin-left: 14px; padding-left: 10px; border-left: 1px solid color-mix(in srgb, var(--border) 75%, transparent); }
.ast-leaf { padding-left: 13px; }
.ast-label { display: inline-flex; align-items: baseline; gap: 6px; }
.ast-type { color: var(--accent-hover); font-weight: 650; }
.ast-name { color: var(--warning); }
.ast-pos { color: var(--text-dim); font-size: 10px; cursor: pointer; }
.ast-pos:hover { color: var(--accent); text-decoration: underline; }
.ast-count { margin-left: 7px; padding: 0 5px; border: 1px solid var(--border); border-radius: var(--radius-pill); color: var(--text-dim); font-size: 10px; }

/* Inspector tables (trace, benchmark) */
.trace-table, .bench-results { padding: 4px 12px 12px; }
.inspector-table { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 11px; }
.inspector-table th { position: sticky; top: 0; padding: 5px 7px; border-bottom: 1px solid var(--border-light); background: var(--surface-raised); color: var(--text-muted); font-weight: 700; text-align: left; }
.inspector-table td { padding: 3.5px 7px; border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent); color: var(--text); vertical-align: top; word-break: break-word; }
.trace-table { max-height: 340px; overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.trace-kind { padding: 1px 6px; border: 1px solid var(--border); border-radius: var(--radius-pill); color: var(--text-muted); font-size: 10px; white-space: nowrap; }
.trace-call_start .trace-kind, .trace-call_end .trace-kind { border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); color: var(--accent-hover); }
.trace-goroutine_start .trace-kind, .trace-goroutine_end .trace-kind { border-color: color-mix(in srgb, var(--success) 45%, var(--border)); color: var(--success); }
.trace-run_start .trace-kind, .trace-run_end .trace-kind { border-color: var(--border-light); color: var(--text); }
.trace-capability_denied .trace-kind, .trace-test_error .trace-kind, .trace-test_fatal .trace-kind { border-color: color-mix(in srgb, var(--error) 55%, var(--border)); color: var(--error); }
.trace-debug_q .trace-kind, .trace-debug_mark .trace-kind { border-color: color-mix(in srgb, var(--warning) 50%, var(--border)); color: var(--warning); }
.trace-breakpoint .trace-kind { border-color: color-mix(in srgb, var(--warning) 65%, var(--border)); color: var(--warning); font-weight: 700; }
.trace-loc { min-height: 0; padding: 0 5px; border: 0; background: transparent; color: var(--accent); font-family: var(--mono); font-size: 11px; text-decoration: underline; cursor: pointer; }
.bench-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 8px; margin-bottom: 10px; }

/* Call graph (Functions section) */
.callgraph-list { display: grid; gap: 6px; padding: 4px 12px 12px; max-height: 380px; overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.callgraph-func { border: 1px solid var(--border); border-radius: 8px; background: var(--code-bg); }
.callgraph-func > summary { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 7px 10px; cursor: pointer; list-style: none; }
.callgraph-func > summary::-webkit-details-marker { display: none; }
.callgraph-name { min-height: 0; padding: 2px 7px; border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border)); border-radius: 6px; background: color-mix(in srgb, var(--accent) 10%, var(--surface-raised)); color: var(--accent-hover); font-family: var(--mono); font-size: 12px; font-weight: 700; }
.callgraph-counts { color: var(--text-dim); font-size: 10.5px; white-space: nowrap; }
.callgraph-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 2px 12px 10px; border-top: 1px solid color-mix(in srgb, var(--border) 60%, transparent); }
.callgraph-col { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; min-width: 0; }
.callgraph-col-title { margin: 6px 0 1px; color: var(--text-dim); font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
.callgraph-edge { min-height: 0; max-width: 100%; padding: 2px 7px; overflow: hidden; border: 1px solid var(--border); border-radius: var(--radius-pill); color: var(--text-muted); font-family: var(--mono); font-size: 11px; text-align: left; text-overflow: ellipsis; white-space: nowrap; }
.callgraph-edge.callgraph-resolved { border-color: color-mix(in srgb, var(--success) 40%, var(--border)); color: var(--success); }
.callgraph-none { color: var(--text-dim); font-size: 11px; font-style: italic; }

/* List/Diagram view switch (Functions section) */
.view-switch { display: inline-flex; gap: 2px; padding: 2px; border: 1px solid var(--border); border-radius: 8px; background: var(--code-bg); }
.view-switch-btn { min-height: 26px; padding: 3px 9px; border: 0; border-radius: 6px; background: transparent; color: var(--text-muted); font-size: 11px; font-weight: 650; }
.view-switch-btn.active { background: color-mix(in srgb, var(--accent) 20%, var(--surface-raised)); color: var(--accent-hover); }

/* [hidden] must win over .callgraph-list's own `display: grid` (a plain
   class selector otherwise beats the UA stylesheet's [hidden] rule since
   both apply to the same element with the same specificity tier). */
.callgraph-list[hidden], .callgraph-diagram[hidden] { display: none; }

/* Call graph diagram (node/arrow view) */
.callgraph-diagram { padding: 4px 12px 14px; }
.callgraph-svg-wrap { max-height: 420px; overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--code-bg); }
.callgraph-svg { display: block; }
.callgraph-node rect { stroke-width: 1.5; fill: color-mix(in srgb, var(--accent) 10%, var(--surface-raised)); stroke: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.callgraph-node text { fill: var(--text); font-family: var(--mono); font-size: 11px; text-anchor: middle; dominant-baseline: middle; pointer-events: none; }
.callgraph-node-entry rect { stroke: var(--success); stroke-width: 2; fill: color-mix(in srgb, var(--success) 14%, var(--surface-raised)); }
.callgraph-node-external rect { stroke: var(--border-light); stroke-dasharray: 4 3; fill: var(--surface); }
.callgraph-node-external text { fill: var(--text-dim); }
.callgraph-node:hover rect { stroke-width: 2.5; }
.callgraph-edge-path { fill: none; stroke: var(--accent); stroke-width: 1.5; opacity: .75; }
.callgraph-edge-path.muted { stroke: var(--text-dim); stroke-dasharray: 3 3; opacity: .6; }
.callgraph-edge-path.callgraph-selfloop { stroke: var(--warning); }
.callgraph-legend { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 9px; color: var(--text-muted); font-size: 11px; }
.callgraph-legend span { display: inline-flex; align-items: center; gap: 5px; }
.cg-swatch { display: inline-block; width: 12px; height: 12px; border-radius: 3px; border: 1.5px solid color-mix(in srgb, var(--accent) 45%, var(--border)); background: color-mix(in srgb, var(--accent) 10%, var(--surface-raised)); }
.cg-swatch-entry { border-color: var(--success); border-width: 2px; background: color-mix(in srgb, var(--success) 14%, var(--surface-raised)); }
.cg-swatch-func { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.cg-swatch-external { border-style: dashed; border-color: var(--border-light); background: var(--surface); }

/* Execution Lab: AST-backed Mermaid graph, linked back into the editor. */
.nanogo-breakpoints { width: 16px; }
.nanogo-breakpoint-marker { display: block; width: 10px; height: 10px; margin: 4px auto 0; border: 1px solid color-mix(in srgb, var(--error) 78%, #fff); border-radius: 50%; background: var(--error); box-shadow: 0 0 0 2px color-mix(in srgb, var(--error) 16%, transparent); }
.nanogo-breakpoint-marker.hit { border-color: color-mix(in srgb, var(--warning) 85%, #fff); background: var(--warning); box-shadow: 0 0 0 2px color-mix(in srgb, var(--warning) 18%, transparent); }
.lab-content, .ai-content { display: grid; gap: 12px; }
.lab-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.lab-debug-btn { border-color: color-mix(in srgb, var(--warning) 45%, var(--border)); color: var(--warning); }
.lab-replay-bar { display: flex; align-items: center; gap: 7px; padding: 7px 10px; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--surface-raised); }
.lab-replay-bar .inspector-note { margin: 0; }
.lab-graph { min-height: 230px; overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: 12px; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--code-bg); }
.lab-graph svg { display: block; min-width: max-content; max-width: none; margin: 0 auto; }
.lab-graph .node { cursor: pointer; outline: none; }
.lab-graph .node:hover rect, .lab-graph .node:focus rect { stroke-width: 3px; }
.lab-graph .node.lab-node-active rect, .lab-graph .node.lab-node-active polygon { stroke: var(--warning) !important; stroke-width: 4px !important; filter: drop-shadow(0 0 6px color-mix(in srgb, var(--warning) 70%, transparent)); }
.lab-details { padding: 10px 12px; border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border)); border-radius: var(--radius-card); background: color-mix(in srgb, var(--accent) 7%, var(--surface-raised)); }
.lab-live-debug { display: grid; gap: 8px; padding: 10px; border: 1px solid color-mix(in srgb, var(--error) 35%, var(--border)); border-radius: var(--radius-card); background: color-mix(in srgb, var(--error) 5%, var(--surface-raised)); }
.lab-live-debug .lab-toolbar { justify-content: flex-start; }
#liveDebugStartBtn { border-color: color-mix(in srgb, var(--error) 45%, var(--border)); color: var(--error); }
#liveDebugStatus { margin: 0; }
.lab-live-debug-info { display: grid; grid-template-columns: minmax(140px, 1fr) minmax(200px, 2fr); gap: 12px; }
.lab-live-debug-stack, .lab-live-debug-vars { min-width: 0; }
.lab-live-debug-stack strong, .lab-live-debug-vars strong { display: block; margin-bottom: 4px; font-size: 11px; text-transform: uppercase; letter-spacing: .03em; color: var(--text-muted); }
.lab-live-debug-stack pre { margin: 0; padding: 8px; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--code-bg); font-family: var(--mono); font-size: 12px; max-height: 160px; overflow: auto; white-space: pre-wrap; }
#liveDebugVarsTable { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 12px; display: block; max-height: 160px; overflow: auto; }
#liveDebugVarsTable th, #liveDebugVarsTable td { padding: 3px 6px; border-bottom: 1px solid var(--border); text-align: left; }
#liveDebugVarsTable thead, #liveDebugVarsTable tbody { display: table; width: 100%; table-layout: fixed; }
#liveDebugVarsTable td:last-child { display: flex; align-items: center; gap: 4px; }
.live-debug-var-input { flex: 1; min-width: 0; padding: 2px 5px; border: 1px solid var(--border); border-radius: 4px; background: var(--surface); color: var(--text); font-family: var(--mono); font-size: 12px; }
.live-debug-var-msg { flex-shrink: 0; font-size: 11px; color: var(--success, var(--accent)); }
.live-debug-var-msg.live-debug-var-error { color: var(--error); }
@media (max-width: 640px) {
  .lab-live-debug-info { grid-template-columns: 1fr; }
}
.lab-detail-title { color: var(--text); font-family: var(--mono); font-size: 13px; font-weight: 750; }
.lab-detail-meta { margin-top: 3px; color: var(--text-muted); font-size: 11px; }
.lab-detail-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 9px; }

/* The assistant is deliberately a small local client: a readable transcript,
   an explicit connection disclosure, and no automatic editor mutation. */
.ai-settings { padding: 9px 11px; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--code-bg); }
.ai-settings > summary { cursor: pointer; color: var(--text-muted); font-size: 12px; font-weight: 700; }
.ai-settings-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 10px; }
.ai-settings label { display: grid; gap: 4px; color: var(--text-muted); font-size: 11px; }
.ai-settings input, .ai-composer textarea { min-width: 0; border: 1px solid var(--border); border-radius: 7px; background: var(--surface); color: var(--text); font: inherit; }
.ai-settings input { min-height: 31px; padding: 5px 7px; }
.ai-context-toggle { display: flex !important; grid-template-columns: auto 1fr; align-items: center; gap: 7px !important; margin-top: 10px; }
.ai-context-toggle input { min-height: 0; }
.ai-messages { display: grid; gap: 9px; min-height: 180px; max-height: 420px; overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: 2px; }
.ai-message { padding: 10px 11px; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--code-bg); }
.ai-message-user { border-color: color-mix(in srgb, var(--accent) 42%, var(--border)); background: color-mix(in srgb, var(--accent) 8%, var(--surface-raised)); }
.ai-message-label { margin-bottom: 5px; color: var(--text-dim); font-size: 10px; font-weight: 750; letter-spacing: .05em; text-transform: uppercase; }
.ai-message-body { color: var(--text); font-size: 13px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; }
.ai-message pre { margin: 8px 0 0; padding: 9px; overflow: auto; border-radius: 7px; background: var(--code-bg); color: var(--text); font-family: var(--mono); font-size: 11px; line-height: 1.45; white-space: pre; }
.ai-message-actions { display: flex; gap: 8px; margin-top: 9px; }
.ai-composer { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 9px; align-items: end; }
.ai-composer textarea { min-height: 72px; padding: 9px 10px; resize: vertical; line-height: 1.45; }

/* Command palette: a single, low-chrome layer for IDE actions. */
.command-palette { position: fixed; inset: 0; z-index: 60; display: grid; place-items: start center; padding: min(15vh, 130px) 14px 20px; background: color-mix(in srgb, #000 48%, transparent); }
.command-palette[hidden] { display: none; }
.command-palette-card { width: min(560px, 100%); overflow: hidden; border: 1px solid var(--border-light); border-radius: var(--radius-card); background: var(--surface); box-shadow: var(--shadow-lg); }
.command-palette-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 13px 8px; color: var(--text); }
.command-palette-input { width: calc(100% - 20px); min-height: 38px; margin: 0 10px 8px; padding: 7px 10px; border: 1px solid var(--border); border-radius: 7px; outline: 0; background: var(--code-bg); color: var(--text); font: 13px var(--mono); }
.command-palette-input:focus { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 18%, transparent); }
.command-palette-list { display: grid; max-height: min(50vh, 390px); overflow: auto; padding: 2px 7px 8px; }
.command-item { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 36px; padding: 7px 9px; border: 0; border-radius: 6px; background: transparent; color: var(--text); font-size: 12px; text-align: left; }
.command-item small { color: var(--text-dim); font-family: var(--mono); font-size: 10px; }
.command-item:hover, .command-item.active { background: color-mix(in srgb, var(--accent) 16%, var(--surface-raised)); color: var(--accent-hover); }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { border: 3px solid transparent; border-radius: var(--radius-card); background: var(--border-light); background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--text-dim); background-clip: padding-box; }

/* Theme variables stay lightweight: the existing picker only needs to switch
   these tokens; the full layout above remains identical and accessible. */
.theme-light { color-scheme: light; --bg:#f4f7fb; --surface:#fff; --surface-raised:#f5f8fc; --surface-hover:#eaf0f8; --text:#172033; --text-muted:#485565; --text-dim:#626f85; --border:#d9e2ef; --border-light:#bccbe0; --accent:#2463c5; --accent-hover:#174c9d; --accent-strong:#2463c5; --success:#13865b; --warning:#8f5a00; --error:#c23a4a; --code-bg:#f8fbff; --code-gutter:#eef4fa; --gradient-bg:linear-gradient(112deg,#f2f7ff,#fff); }
.theme-solar, .theme-sepia { color-scheme: light; --bg:#f5efdf; --surface:#fff9ea; --surface-raised:#f3ead6; --surface-hover:#ecdfc4; --text:#4a4031; --text-muted:#5d5342; --text-dim:#71654f; --border:#ded2ba; --border-light:#cdbd9f; --accent:#9a6519; --accent-hover:#74490f; --accent-strong:#9a6519; --success:#31745d; --warning:#9a6519; --error:#b34b48; --code-bg:#fff9eb; --code-gutter:#f3ead7; }
.theme-dracula { --bg:#282a36; --surface:#343746; --surface-raised:#414557; --surface-hover:#4d5265; --text:#f8f8f2; --text-muted:#d5d5cc; --text-dim:#b0b6cb; --border:#505466; --border-light:#696d81; --accent:#ff79c6; --accent-hover:#ff9bd6; --accent-strong:#c95f9f; --success:#50fa7b; --warning:#f1fa8c; --error:#ff8585; --code-bg:#20212b; --code-gutter:#292b36; }
.theme-monokai { --bg:#272822; --surface:#30312a; --surface-raised:#3a3b34; --surface-hover:#46473f; --text:#f8f8f2; --text-muted:#cccbbf; --text-dim:#aca997; --border:#515248; --border-light:#6d6e61; --accent:#a6e22e; --accent-hover:#c1f26a; --accent-strong:#76ae1a; --success:#a6e22e; --warning:#e6db74; --error:#ff709f; --code-bg:#1f201c; --code-gutter:#292a25; }
.theme-ocean { --bg:#062d47; --surface:#0a3a55; --surface-raised:#104b67; --surface-hover:#155b79; --text:#e6f4f8; --text-muted:#b3d3df; --text-dim:#9bbbca; --border:#1d6079; --border-light:#2d7590; --accent:#35d0c8; --accent-hover:#79efe7; --accent-strong:#159f9b; --success:#62d69b; --warning:#f3c56a; --error:#fb7d86; --code-bg:#062536; --code-gutter:#082f43; }
.theme-forest { --bg:#082312; --surface:#10341e; --surface-raised:#174629; --surface-hover:#205635; --text:#e8f7ea; --text-muted:#b5d6ba; --text-dim:#99bda1; --border:#2c6640; --border-light:#448158; --accent:#43c984; --accent-hover:#85efb5; --accent-strong:#249e60; --success:#4cda8f; --warning:#f1c46c; --error:#f47f86; --code-bg:#091b10; --code-gutter:#0d2918; }
.theme-midnight { --bg:#0b1020; --surface:#121a30; --surface-raised:#192440; --surface-hover:#223054; --text:#e9efff; --text-muted:#b5c4e5; --text-dim:#8e9fc4; --border:#2a3a61; --border-light:#40527c; --accent:#7ea8ff; --accent-hover:#aac5ff; --accent-strong:#547ed1; --success:#62d7bb; --warning:#f3c66e; --error:#ff8391; --code-bg:#090e1a; --code-gutter:#10172a; }
.theme-pastel { color-scheme: light; --bg:#fff7f3; --surface:#fff; --surface-raised:#fff0f4; --surface-hover:#ffe4ec; --text:#342b34; --text-muted:#594b54; --text-dim:#6f6270; --border:#f0d6e0; --border-light:#dfb8c8; --accent:#d35f91; --accent-hover:#a53c6b; --accent-strong:#be4e7e; --success:#237a5b; --warning:#8b5c10; --error:#c74d5d; --code-bg:#fffafd; --code-gutter:#fff0f5; }
.theme-high-contrast { --bg:#000; --surface:#000; --surface-raised:#111; --surface-hover:#222; --text:#fff; --text-muted:#eee; --text-dim:#c4c4c4; --border:#fff; --border-light:#ff0; --accent:#ff0; --accent-hover:#fff; --accent-strong:#d3d300; --success:#7fff00; --warning:#ff0; --error:#ff5c5c; --code-bg:#000; --code-gutter:#111; }

/* Syntax palettes per theme. Only the tokens change here — the .cm-* rules
   above read these variables, so a theme never has to restate a selector.
   Every value clears 4.5:1 against that theme's own --code-bg, which is what
   the shared dark palette could not do on a light background.

   The light themes get hue-matched dark tokens (cool for Light, warm for
   Solarized/Sepia, mauve for Pastel). Dracula and Monokai use their canonical
   upstream palettes — that is the reason to pick those themes at all — except
   for the comment color, which both projects define far too dim to read
   (#6272a4 and #75715e sit near 3:1); each is lifted just far enough. */
.theme-light {
  --syn-keyword:#8250df; --syn-number:#8f4b00; --syn-type:#0550ae; --syn-string:#0f6a48;
  --syn-comment:#5b6875; --syn-operator:#a52f28; --syn-builtin:#0d6f61; --syn-meta:#96297b;
}
.theme-solar, .theme-sepia {
  --syn-keyword:#5a51b0; --syn-number:#855d00; --syn-type:#155f8d; --syn-string:#586a00;
  --syn-comment:#75674f; --syn-operator:#ad231e; --syn-builtin:#1c6f65; --syn-meta:#9f2963;
}
.theme-pastel {
  --syn-keyword:#8a3ea6; --syn-number:#8f4f09; --syn-type:#1a5da3; --syn-string:#14684a;
  --syn-comment:#71606c; --syn-operator:#ab2c3c; --syn-builtin:#0d7062; --syn-meta:#9c2b73;
}
.theme-dracula {
  --syn-keyword:#ff79c6; --syn-number:#bd93f9; --syn-type:#8be9fd; --syn-string:#f1fa8c;
  --syn-comment:#8290c4; --syn-operator:#ff79c6; --syn-builtin:#50fa7b; --syn-meta:#ffb86c;
}
.theme-monokai {
  --syn-keyword:#fd4a8b; --syn-number:#ae81ff; --syn-type:#66d9ef; --syn-string:#e6db74;
  --syn-comment:#9f9b87; --syn-operator:#fd4a8b; --syn-builtin:#a6e22e; --syn-meta:#fd971f;
}
/* Ocean and Forest keep the shared dark tokens (they read well against their
   deep backgrounds) but tint the comment toward the theme's own hue, which
   also lifts it over 4.5:1. */
.theme-ocean { --syn-comment:#7f9db0; }
.theme-forest { --syn-comment:#7f9d89; }
.theme-high-contrast {
  --syn-keyword:#ff0; --syn-number:#0ff; --syn-type:#fff; --syn-string:#7fff00;
  --syn-comment:#c4c4c4; --syn-operator:#ff0; --syn-builtin:#0ff; --syn-meta:#ff8cff;
}

/* One breakpoint where editor/output stack instead of the old three-stage
   dance (a column-count change at 1280px, full stacking at 900px, plus the
   sidebar's own extra transitional column layout in between) — now that the
   sidebar is a drawer overlay instead of a grid column, there's only ever
   this one arrangement to switch between. */
@media (max-width: 1000px) {
  :root { --editor-min-h: 480px; }
  .brand-subtitle { display: none; }
  .header-actions { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .header-actions::-webkit-scrollbar { display: none; }
  .main { grid-template-areas: "editor" "output"; grid-template-columns: 1fr; }
  .output-panel.active { min-height: 270px; }
  #log { height: 280px; }
}

/* Phone breakpoint (iPhone in portrait or landscape, plus small Android).
   Below this width the two-column sidebar from the 900px tier no longer
   has room, so everything goes single-column and several desktop-oriented
   affordances (long button labels, an always-open example list, a keyboard
   shortcut hint) get replaced with touch/small-screen equivalents. */
@media (max-width: 640px) {
  .brand-subtitle { display: none; }
  .header-actions { justify-content: flex-start; }
  .main { padding: 10px; gap: 10px; }
  .editor-section { gap: 8px; }
  .controls { gap: 6px; }
  .input-group { margin-left: 0; }
  .workspace-bar { grid-template-columns: minmax(0, 1fr) auto; gap: 4px; }
  .workspace-project { grid-column: 1 / -1; }
  .workspace-tabs { grid-column: 1 / -1; order: 3; }
  .workspace-actions { justify-self: end; }
  .workspace-actions .mini-btn { min-height: 44px; }

  /* Icon-only buttons: the emoji stays, the trailing label collapses. The
     Run button keeps its own label (it's the primary action) but sheds the
     "(Ctrl/⌘+Enter)" hint, which is meaningless without a hardware keyboard. */
  .btn-label, .shortcut-hint { display: none; }
  .header-actions > button, .upload-control, .header-link,
  .controls > button:not(.primary) { min-width: 44px; padding-left: 8px; padding-right: 8px; }

  /* Comfortable tap targets everywhere (Apple HIG: 44pt minimum), and 16px
     form-control text so Safari never zooms the page in on focus. */
  button, select, .upload-control, .header-link { min-height: 44px; }
  input, select, textarea { font-size: 16px; }
  .example-search, .tag-btn, .copy-btn, .mini-btn, .inspector-field input,
  .input-group select, .input-group input { min-height: 44px; }
  .input-group select, .input-group input { max-width: 130px; font-size: 14px; }
  .callgraph-edge { min-height: 30px; padding: 5px 9px; }

  /* Examples list starts collapsed (see the checkbox toggle in the HTML)
     so a first-time visitor isn't forced to scroll past dozens of demos
     before reaching the editor; tapping the header re-expands it in place. */
  .examples-chevron { display: inline; }
  .examples-panel-body { display: none; }
  .examples-toggle-input:checked ~ .examples-panel-body { display: flex; }
  .examples-toggle-input:checked ~ .examples-toggle-label .examples-chevron { transform: rotate(180deg); }

  /* Shorter panels so the page doesn't turn into an endless scroll: only
     one output panel is ever visible at a time (the tabs hide the rest),
     so this is the actual per-screen cost, not a sum across all of them. */
  :root { --editor-min-h: 340px; }
  .output-panel { min-height: 240px; }
  .canvas-container, #output { min-height: 220px; }
  #log { height: min(42vh, 420px); }
  .inspector-content { max-height: min(60vh, 560px); }
  .ai-settings-grid { grid-template-columns: 1fr; }
  .ai-composer { grid-template-columns: 1fr; }
  .ai-composer .primary { width: 100%; }
  .lab-graph { min-height: 190px; }
  .symbol-content { max-height: min(68vh, 620px); padding: 11px; }
  .symbol-grid { grid-template-columns: 1fr; }
  .symbol-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .symbol-heading { align-items: flex-start; }
  .symbol-link { min-height: 38px; padding: 7px 9px; }
}

/* Smallest phones (iPhone SE / mini and narrower): trim padding further. */
@media (max-width: 380px) {
  .main { padding: 10px; }
  .controls > button, .header-actions > button, .upload-control, .header-link { min-width: 44px; padding-left: 6px; padding-right: 6px; }
  .stats-grid, .bench-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* iPhone in landscape: viewport height is short (~375–430px), so tall fixed
   panels would otherwise force scrolling for even a single line of output. */
@media (max-height: 480px) and (orientation: landscape) {
  :root { --editor-min-h: 220px; }
  .output-panel { min-height: 180px; }
  #log { height: min(38vh, 260px); }
  .inspector-content { max-height: 46vh; }
}
