/* Mini4WD Track Editor — mobile fork PoC */
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0; padding: 0;
  height: 100%;
  overscroll-behavior: none;
}

body {
  display: flex; flex-direction: column;
  height: 100vh; height: 100dvh;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: #16181d; color: #e8eaed;
  --accent: #ffd166; --accent-ink: #1a1a1a;
  --panel: #1f2229; --panel-2: #262a33; --line: #333844;
}

/* ---------- top bar ---------- */
#topbar {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; padding-top: calc(8px + env(safe-area-inset-top));
  background: var(--panel); border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}
.brand {
  font: inherit; font-weight: 700; font-size: 15px; white-space: nowrap;
  border: 0; background: transparent; color: inherit; cursor: pointer; padding: 0;
}
.brand span { color: var(--accent); }
.brand:hover { text-decoration: underline; }
.brand:active { opacity: .8; }
.mode-switch { display: flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
/* narrow screens: the segmented control collapses to one cycling button
 * (pure CSS — the app never toggles visibility, so viewport changes
 * can't leave the switcher in a stale state) */
#modeCycle { display: none; }
@media (max-width: 540px) {
  .mode-switch > button:not(#modeCycle) { display: none; }
  #modeCycle { display: block; }
}
.mode-switch button {
  border: 0; background: transparent; color: #aab1bd;
  font: inherit; font-size: 12px; padding: 5px 10px; cursor: pointer;
}
.mode-switch button.active { background: var(--accent); color: var(--accent-ink); font-weight: 700; }
.stats {
  margin-left: auto; font-variant-numeric: tabular-nums;
  font-size: 12px; color: #aab1bd; white-space: nowrap;
  /* the working track's name lives here: it may grow long, but the
   * mode selector and menu are owner-mandated always-visible — on
   * phones the name hides entirely (numbers stay; the popup carries
   * it), on desktop the title ellipsizes instead of pushing them out */
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
/* phones: the numbers stay, the name moves behind the tap popup
 * (same breakpoint as the mode-switch collapse); full line on desktop */
@media (max-width: 540px) {
  .stats-name { display: none; }
}
.icon-btn {
  border: 1px solid var(--line); background: var(--panel-2); color: inherit;
  border-radius: 8px; font-size: 16px; padding: 5px 10px; cursor: pointer;
  display: inline-flex; align-items: center;
}
#zoomControls button { display: flex; align-items: center; justify-content: center; }
.menu-actions button svg, .file-label svg, .tip-cta svg { vertical-align: -3px; margin-right: 2px; }

/* ---------- stage / canvas ---------- */
#stage { position: relative; flex: 1 1 auto; min-height: 0; }
#editor {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: block; touch-action: none; cursor: crosshair;
}
#zoomControls {
  position: absolute; right: 10px; bottom: 10px;
  display: flex; flex-direction: column; gap: 8px;
}
#zoomControls button {
  width: 42px; height: 42px; border-radius: 10px; border: 1px solid var(--line);
  background: rgba(31, 34, 41, .92); color: inherit; font-size: 19px; cursor: pointer;
}
.hint {
  position: absolute; left: 50%; top: 10px; transform: translateX(-50%);
  font-size: 11px; color: #9aa3af; background: rgba(22, 24, 29, .8);
  padding: 4px 10px; border-radius: 999px; pointer-events: none;
  transition: opacity .6s; white-space: nowrap; max-width: 92%; overflow: hidden; text-overflow: ellipsis;
}

/* ---------- toolbar ---------- */
#toolbar {
  flex: 0 0 auto; background: var(--panel);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}
.tool-row { display: flex; gap: 6px; padding: 8px 10px 4px; align-items: center; overflow-x: auto; }
.tool {
  min-width: 44px; height: 44px; padding: 0 10px;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-2); color: inherit; font-size: 19px; cursor: pointer;
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
}
.tool svg { display: block; }        /* rgb dots + MDI icons: baseline off, center it */
.tool.active { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); font-weight: 700; }
.sep { width: 1px; height: 28px; background: var(--line); flex: 0 0 auto; margin: 0 2px; }

.palette {
  display: flex; gap: 8px; padding: 6px 10px 10px;
  overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: thin;
}
.chip {
  flex: 0 0 auto; width: 76px;
  border: 1px solid var(--line); border-radius: 12px;
  background: var(--panel-2); color: #c8cdd6;
  padding: 6px 4px 5px; cursor: pointer; text-align: center;
}
.chip canvas { width: 64px; height: 44px; display: block; margin: 0 auto; border-radius: 6px; background: #14161a; }
.chip .chip-label { display: block; font-size: 10px; margin-top: 4px; line-height: 1.15; }
.chip.active { border-color: var(--accent); background: #2e3140; color: #fff; box-shadow: 0 0 0 1px var(--accent); }

/* ---------- dialogs ---------- */
dialog {
  margin: auto; max-width: 420px; width: calc(100vw - 32px);
  background: var(--panel); color: inherit; border: 1px solid var(--line);
  border-radius: 14px; padding: 18px;
}
dialog::backdrop { background: rgba(0, 0, 0, .55); }
dialog h2 { margin: 0 0 12px; font-size: 17px; }
dialog h3 { margin: 14px 0 6px; font-size: 14px; color: #aab1bd; }
.menu-actions { display: flex; flex-direction: column; gap: 8px; }
.menu-actions button, .file-label {
  font: inherit; font-size: 14px; text-align: left; padding: 11px 12px;
  border-radius: 10px; border: 1px solid var(--line);
  background: var(--panel-2); color: inherit; cursor: pointer; display: block;
}
.file-label input { display: none; }
button.primary { background: var(--accent); color: var(--accent-ink); font-weight: 700; border-color: var(--accent); }
button.secondary { background: transparent; }
.dialog-actions { display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
.dialog-actions button { flex: 1 1 auto; font: inherit; padding: 10px; border-radius: 10px; border: 1px solid var(--line); background: var(--panel-2); color: inherit; cursor: pointer; }
.credits { font-size: 11px; color: #9aa3af; line-height: 1.5; margin: 14px 0 0; }
.credits a { color: var(--accent); }
.io-hint { font-size: 12px; color: #aab1bd; line-height: 1.5; }
#ioText {
  width: 100%; margin-top: 10px; resize: vertical;
  background: #14161a; color: #dfe3ea; border: 1px solid var(--line);
  border-radius: 10px; padding: 10px; font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
}
.help-list { margin: 0 0 8px; padding-left: 18px; font-size: 13px; line-height: 1.7; }
kbd {
  background: #14161a; border: 1px solid var(--line); border-bottom-width: 2px;
  border-radius: 5px; padding: 0 5px; font-size: 11px;
}

/* ---------- toast ---------- */
#toast {
  position: fixed; left: 50%; top: calc(52px + env(safe-area-inset-top));
  transform: translateX(-50%) translateY(-8px);
  background: #2e3140; border: 1px solid var(--line); color: #fff;
  padding: 9px 16px; border-radius: 999px; font-size: 13px;
  opacity: 0; pointer-events: none; transition: opacity .25s, transform .25s;
  max-width: 88vw; text-align: center; z-index: 50;
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); pointer-events: auto; }
#toast button {
  margin-left: 10px; border: 1px solid #7dd3fc; background: transparent;
  color: #7dd3fc; border-radius: 999px; padding: 4px 10px; font-size: 12px;
}

@media (min-width: 900px) {
  /* desktop: toolbar becomes a left sidebar-ish wide palette, but flex works fine as-is */
  .palette { flex-wrap: wrap; }
  .hint { display: none; }
}

/* ---------- dialog heads (✕ close) ---------- */
.dialog-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 6px;
}
.dialog-head h2 { margin: 0; }

/* ---------- dialog/menu button feedback (hover + press) ----------
 * The global -webkit-tap-highlight-color makes :active the only touch
 * feedback channel — every clickable gets both states. Hover rules are
 * :not(:disabled)-guarded and locked controls dim. */
.dialog-actions button:not(:disabled):hover, .menu-actions button:hover, .file-label:hover,
button.primary:not(:disabled):hover, button.secondary:not(:disabled):hover,
.icon-btn:hover, .lib-row:hover, .gal-main:hover, .gal-more:hover,
.gal-star:not(:disabled):hover, .gal-toggle:hover, .gal-filterbtn:hover {
  background: #2e3140;
  border-color: #4a5160;
}
button.primary:not(:disabled):hover { background: var(--accent); border-color: #ffd97a; }
button.secondary:not(:disabled):hover { background: rgba(255, 255, 255, .06); }
.dialog-actions button:not(:disabled):active, .menu-actions button:active, .file-label:active,
button.primary:not(:disabled):active, button.secondary:not(:disabled):active,
.icon-btn:active, .lib-row:active, .gal-main:active, .gal-more:active,
.gal-star:not(:disabled):active, .gal-toggle:active, .gal-filterbtn:active {
  transform: translateY(1px);
  background: #262a33;
}
button.primary:not(:disabled):active { background: #e6b84f; }
.dialog-actions button:disabled, button.primary:disabled { opacity: .55; cursor: default; }
#pubName:disabled { opacity: .55; }

/* the Complete-suggestion CTA in the publish dialog */
.tip-cta {
  width: 100%; margin-top: 8px; font: inherit; font-size: 13px; text-align: left;
  padding: 9px 12px; border-radius: 10px; border: 1px solid var(--line);
  background: transparent; color: #7dd3fc; cursor: pointer;
}
.tip-cta:hover { background: rgba(125, 211, 252, .08); border-color: #7dd3fc; }
.tip-cta:active { transform: translateY(1px); background: rgba(125, 211, 252, .14); }

/* ---------- gallery (all published tracks on the server) ---------- */
/* full-screen (owner round): the gallery is a browse surface, not a
 * popover — it takes the whole viewport on every device. display is
 * [open]-guarded: an unguarded flex would override the UA's
 * dialog:not([open]) display:none and render a closed dialog as an
 * invisible click shield over the whole app. overflow hidden CLIPS the
 * filter panel so a hidden panel can never leak a horizontal scrollbar */
dialog.gallery-full {
  max-width: none; width: 100vw; height: 100dvh; height: 100svh;
  margin: 0; border: 0; border-radius: 0; overflow: hidden;
}
dialog.gallery-full[open] { display: flex; flex-direction: column; }
.gallery-full .dialog-head { flex: 0 0 auto; }
.gallery-full .io-hint { flex: 0 0 auto; }
/* toolbar wraps instead of scrolling — the pill row's horizontal
 * scrollbar on desktop was the complaint that spawned the panel */
.gal-toolbar-wrap { position: relative; flex: 0 0 auto; }
.gal-toolbar {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 8px; margin-top: 10px;
}
.gal-sortwrap {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: #aab1bd;
}
.gal-sortwrap select {
  font: inherit; font-size: 13px; color: #e8eaed;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 10px;
  padding: 7px 8px; cursor: pointer;
}
.gal-toggle {
  font: inherit; font-size: 12px; text-align: left;
  padding: 7px 11px; border-radius: 10px; border: 1px solid var(--line);
  background: var(--panel-2); color: #aab1bd; cursor: pointer;
}
.gal-toggle[aria-pressed="true"] { background: #2e3140; color: #4ade80; border-color: #4ade80; }
.gal-filterbtn {
  position: relative; font: inherit; font-size: 13px; padding: 7px 12px;
  border-radius: 10px; border: 1px solid var(--line);
  background: var(--panel-2); color: inherit; cursor: pointer;
}
.gal-filtercount {
  margin-left: 6px; padding: 1px 7px; border-radius: 999px;
  background: var(--accent); color: var(--accent-ink); font-size: 11px; font-weight: 700;
}
.gal-meta { flex: 0 0 auto; margin-top: 8px; font-size: 11px; color: #9aa3af; font-variant-numeric: tabular-nums; }

/* card grid (owner round 2): larger thumbnails, columns when there is
 * room, one column on phones */
.gal-list {
  flex: 1 1 auto; min-height: 0; margin-top: 8px; overflow-y: auto;
  display: grid; gap: 10px; align-items: stretch;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  padding-bottom: 10px;
}

/* the filter panel — drops DOWN from the toolbar (anchored to the
 * Filters button, not a right-side slide-in). Hiding is visibility-
 * based: a transform-only hide still occupies scroll width and leaks
 * the horizontal scrollbar the owner could scroll to see */
.gal-panel {
  position: absolute; top: calc(100% + 6px); left: 10px; right: 10px; z-index: 5;
  max-height: min(70vh, 520px); overflow-y: auto;
  display: flex; flex-direction: column; gap: 14px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 12px;
  padding: 14px; box-shadow: 0 10px 28px rgba(0, 0, 0, .45);
  transform: translateY(-6px); opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .15s ease, transform .15s ease, visibility .15s;
}
.gal-panel.open {
  transform: translateY(0); opacity: 1; visibility: visible; pointer-events: auto;
}
.gal-panel-row {
  display: flex; flex-direction: column; gap: 6px;
  font-size: 13px; color: #c8cdd6; border: 0; padding: 0; margin: 0;
}
.gal-panel-row legend { color: #c8cdd6; padding: 0; }
/* label text + (?) stay on ONE line — the icon wrapping under the
 * title looked broken on every width (owner report); titles get their
 * own row, controls sit BELOW (owner round 3) */
.gal-field-title {
  display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
}
.gal-panel-row input[type="range"] { accent-color: var(--accent); width: 100%; }
/* two-ended length slider: two native ranges overlaid — tracks are
 * click-through, only the thumbs catch the pointer */
.gal-range { position: relative; height: 36px; }
.gal-range input[type="range"] {
  position: absolute; inset: 0; width: 100%; margin: 0;
  background: transparent; pointer-events: none; appearance: none; -webkit-appearance: none;
}
.gal-range input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; pointer-events: auto;
  width: 28px; height: 28px; border-radius: 50%;   /* touch-first target */
  background: var(--accent); border: 2px solid #1a1a1a; cursor: grab;
}
.gal-range input[type="range"]::-moz-range-thumb {
  pointer-events: auto;
  width: 28px; height: 28px; border-radius: 50%;   /* matches -webkit travel + the 14px track inset */
  background: var(--accent); border: 2px solid #1a1a1a; cursor: grab;
}
.gal-range-track {
  position: absolute; left: 14px; right: 14px; top: 16px; height: 4px;
  border-radius: 999px; background: var(--line);
}
.gal-range-fill {
  position: absolute; top: 0; height: 100%; border-radius: 999px;
  background: var(--accent);
}
.gal-units {
  flex-direction: row; align-items: center; gap: 8px;
  padding-bottom: 10px; border-bottom: 1px solid var(--line);
  font-size: 12px; color: #9aa3af;
}
.gal-seg {
  font: inherit; font-size: 12px; padding: 5px 10px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--panel-2); color: #aab1bd; cursor: pointer;
}
.gal-seg[aria-pressed="true"] {
  background: var(--accent); color: var(--accent-ink); border-color: var(--accent); font-weight: 700;
}
.gal-dims {
  display: grid; gap: 8px 12px;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
}
/* each cell: label text ABOVE its box, grid-aligned so every input
 * lines up (owner: the At Most boxes were staggered) */
.gal-dims label {
  display: flex; flex-direction: column; align-items: stretch; gap: 4px;
  font-size: 12px; color: #9aa3af; white-space: nowrap;
}
.gal-dims input[type="number"] {
  width: 100%; font: inherit; font-size: 13px; color: #e8eaed;
  background: #14161a; border: 1px solid var(--line); border-radius: 8px; padding: 6px 7px;
}
.gal-dim-input { display: inline-flex; align-items: center; gap: 5px; }
.gal-dim-input input[type="number"] { flex: 1 1 auto; }
.gal-dim-unit { font-size: 12px; color: #9aa3af; }
.gal-lane {
  display: inline-flex; align-items: center; gap: 6px; margin-right: 12px;
  font-size: 13px; cursor: pointer;
}
.gal-lane input { accent-color: var(--accent); width: 17px; height: 17px; }

/* cards: the whole card (minus the star) loads the track; the star
 * lives INSIDE the card, over the thumbnail's top-right corner */
.gal-row { display: block; position: relative; }
.gal-main {
  position: relative; display: flex; flex-direction: column; gap: 5px;
  width: 100%; text-align: left; padding: 8px;
  border-radius: 12px; border: 1px solid var(--line);
  background: var(--panel-2); color: inherit; cursor: pointer;
}
.gal-thumb {
  width: 100%; aspect-ratio: 4 / 3; height: auto; display: block;
  border-radius: 8px; background: #14161a; margin-bottom: 2px;
}
.gal-top { display: flex; align-items: baseline; gap: 8px; min-width: 0; padding-right: 40px; }
.gal-name {
  font-size: 14px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gal-badge { flex: 0 0 auto; font-size: 11px; font-variant-numeric: tabular-nums; }
.gal-badge.ok { color: #4ade80; }
.gal-badge.wip { color: #d9a441; }
.gal-facets { font-size: 12px; color: #aab1bd; font-variant-numeric: tabular-nums; }
.gal-sub { font-size: 11px; color: #9aa3af; font-variant-numeric: tabular-nums; }
.gal-based { font-size: 11px; color: #8a93a3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gal-chain { font-size: 11px; color: #7d8698; }
/* kebab (⋮) beside the star; its menu drops below it */
.gal-kebab {
  position: absolute; top: 14px; right: 60px; z-index: 2;
  width: 38px; height: 38px; border-radius: 50%;
  border: 1px solid var(--line); background: rgba(22, 24, 29, .82);
  color: #9aa3af; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.gal-kebab:hover { color: inherit; }
.gal-kebab[aria-expanded="true"] { color: var(--accent); border-color: var(--accent); }
.gal-menu {
  position: absolute; top: 58px; right: 14px; z-index: 4;
  display: flex; flex-direction: column; min-width: 172px;
  padding: 4px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--panel); box-shadow: 0 8px 24px rgba(0, 0, 0, .45);
}
.gal-menu[hidden] { display: none; }
.gal-menu button {
  font: inherit; font-size: 13px; text-align: left; padding: 10px 12px;
  border: 0; border-radius: 8px; background: transparent; color: inherit;
  cursor: pointer;
}
.gal-menu button:hover { background: #2a2d38; }
.gal-menu button:disabled { opacity: .55; cursor: default; }
.gal-star {
  position: absolute; top: 14px; right: 14px; z-index: 2;
  width: 38px; height: 38px; border-radius: 50%;
  border: 1px solid var(--line); background: rgba(22, 24, 29, .82);
  color: #9aa3af; font-size: 17px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.gal-star.starred { color: var(--accent); border-color: var(--accent); }
.gal-star:disabled { opacity: .55; cursor: default; }
/* history dialog rows */
.his-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-2); font-size: 13px;
}
.his-row button {
  font: inherit; font-size: 12px; padding: 6px 12px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--panel-2); color: inherit; cursor: pointer;
}
/* shared-track note over the canvas (worklog 0017) */
.shared-note {
  position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px; padding: 7px 12px;
  border: 1px solid var(--line); border-radius: 12px;
  background: var(--panel); color: #c3cad6; font-size: 12.5px;
  box-shadow: 0 4px 14px rgba(0,0,0,.35); white-space: nowrap; z-index: 5;
}
.shared-note[hidden] { display: none; }
.shared-note button {
  font: inherit; font-size: 12px; padding: 5px 10px; border-radius: 8px;
  border: 1px solid var(--accent); color: var(--accent); background: transparent; cursor: pointer;
}
@media (max-width: 560px) {
  .shared-note { max-width: calc(100% - 24px); white-space: normal; flex-wrap: wrap; justify-content: center; }
}
.gal-more {
  font: inherit; font-size: 13px; padding: 10px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--panel-2); color: inherit; cursor: pointer;
  grid-column: 1 / -1;
}
.gal-empty { font-size: 13px; color: #9aa3af; padding: 4px 2px; }

/* library rows: load / rename / delete */
.lib-row-wrap { display: flex; gap: 6px; align-items: stretch; }
.lib-row-wrap .lib-row { flex: 1 1 auto; min-width: 0; }
.lib-act {
  flex: 0 0 auto; width: 40px; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-2); color: #aab1bd; cursor: pointer;
}
.lib-act:hover { background: #2e3140; border-color: #4a5160; color: inherit; }
.lib-act:active { transform: translateY(1px); }

/* ---------- track metadata popup (stats-bar tap) ---------- */
.stats-rows { display: flex; flex-direction: column; margin-top: 10px; }
.stat-row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  font-size: 13px; padding: 7px 2px; border-bottom: 1px solid var(--line);
}
.stat-row:last-child { border-bottom: 0; }
.stat-row .stat-label { color: #9aa3af; flex: 0 0 auto; }
.stat-row .stat-value {
  font-variant-numeric: tabular-nums; text-align: right; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.stat-value.ok { color: #4ade80; }
.stat-value.wip { color: #d9a441; }
.stat-note { font-size: 12px; color: #9aa3af; padding: 8px 2px 0; }

/* ---------- reusable (?) tooltips (src/tooltip.js) ---------- */
/* 22px tap target, reads as a quiet affordance next to a label */
.tip-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin-left: 4px; padding: 0;
  border: 1px solid var(--line); border-radius: 50%;
  background: transparent; color: #9aa3af; cursor: pointer;
  vertical-align: middle;
}
.tip-btn:hover { background: #2e3140; border-color: #4a5160; }
.tip-btn:active { transform: translateY(1px); background: #262a33; }
.tip-bubble {
  position: fixed; z-index: 80;
  max-width: 240px; padding: 9px 11px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 10px;
  color: #e8eaed; font-size: 12px; line-height: 1.5;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .4);
}

/* mobile: no double-tap browser zoom anywhere — the canvas keeps its own
 * gesture handling (iOS ignores user-scalable=no; touch-action is what
 * actually sticks). The canvas keeps touch-action: none (#editor, above)
 * — ID specificity beats this universal selector. */
* { touch-action: manipulation; }

/* publish dialog: tripcode explainer (collapsed by default) */
.trip-help { margin-top: 10px; font-size: 12.5px; color: #9aa3af; }
.trip-help summary { cursor: pointer; color: #aab1bd; user-select: none; }
.trip-help summary:hover { color: #c3cad6; }   /* lighter, not dimmer */
.trip-help p { margin: 8px 0 0; line-height: 1.55; }
.trip-help code {
  background: #14161a; border: 1px solid var(--line); border-radius: 4px;
  padding: 1px 5px; font-size: 11.5px;
}

/* publish/save toolbar badge: live validity ring around the button */
#btnPublishBar.pub-ok { box-shadow: 0 0 0 2px #4ade80 inset; }
#btnPublishBar.pub-bad { box-shadow: 0 0 0 2px #e05263 inset; }
/* the stats bar is a real button (keyboard focusable) — tapping it
 * opens the track metadata popup */
#stats { cursor: default; border: 0; background: transparent; color: inherit; font: inherit; padding: 0; }
