/* Isopix. The canvas fills the screen; controls float over it.
   Phone first: tools along the bottom, the grid-level slider on the right
   edge. From 768 px wide (and tall enough), the slider is a bar along the top. */

:root {
  --bg: #f7f5f0;
  --panel: rgba(255, 255, 255, 0.92);
  --ink: #1d1e22;
  --muted: #5d606b;
  --line: #2b2d3a;
  --accent: #d9480f;
  --accent-ink: #ffffff;
  --border: rgba(0, 0, 0, 0.14);
  --pressed: #ffe3d3;
  --shadow: 0 2px 10px rgba(0, 0, 0, 0.14);
  --btn: 48px;
  color-scheme: light dark;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1b1d22;
    --panel: rgba(38, 41, 48, 0.94);
    --ink: #eceef2;
    --muted: #a9adb8;
    --line: #dfe3ee;
    --accent: #ff8a4c;
    --accent-ink: #1b1d22;
    --border: rgba(255, 255, 255, 0.16);
    --pressed: #5a3423;
    --shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; overflow: hidden; background: var(--bg); color: var(--ink);
  font: 16px/1.35 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
body { overscroll-behavior: none; -webkit-user-select: none; user-select: none; }

#stage { position: fixed; inset: 0; width: 100%; height: 100%; touch-action: none; display: block; outline: none; }
#stage:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; }
body.gray #stage { filter: grayscale(1); }
#stage.pan-ready { cursor: grab; }
#stage.panning { cursor: grabbing; }
/* Move mode: the hand is lit and the tool waits, so it is plain which one a drag does. */
body.moving .tools .btn[aria-pressed="true"] { background: transparent; border-color: var(--border); }
.zoom #move-mode[aria-pressed="true"] { background: var(--pressed); outline: 2px solid var(--accent); outline-offset: -2px; }

[hidden] { display: none !important; }

.btn {
  min-width: var(--btn); min-height: var(--btn);
  display: inline-flex; align-items: center; justify-content: center; gap: 2px;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--panel); color: var(--ink); padding: 0 6px;
  font: inherit; font-weight: 600; cursor: pointer; touch-action: manipulation;
}
.btn.wide { padding: 0 14px; }
.btn svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.btn[aria-pressed="true"], .btn[aria-checked="true"] { background: var(--pressed); border-color: var(--accent); }
.btn:disabled { opacity: 0.4; cursor: default; }
.btn:focus-visible, .swatch:focus-visible, .notch:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
/* The Save buttons' dot: something drawn is not in a file yet. */
.btn.unsaved { position: relative; }
.btn.unsaved::after { content: ""; position: absolute; top: 5px; right: 5px; width: 9px; height: 9px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 0 2px var(--panel); }
.btn.danger { color: #c92a2a; }
@media (prefers-color-scheme: dark) { .btn.danger { color: #ff8787; } }

.cluster { position: fixed; display: flex; gap: 6px; z-index: 3; }
.topleft { top: calc(8px + env(safe-area-inset-top)); left: calc(8px + env(safe-area-inset-left));
  /* Leave room for the top-right cluster (Keep chip about 48-50 px, a 6 px gap, Settings 48 px)
     plus at least 12 px clear. Drawing gives way: its name shortens with "…", so a long name
     never pushes Redo into the chip, whatever the font. */
  max-width: calc(100vw - 16px - 116px - env(safe-area-inset-left) - env(safe-area-inset-right)); }
.topleft > .btn { flex: none; }
.topleft > #drawing-open { flex: 0 1 auto; }
.topright { top: calc(8px + env(safe-area-inset-top)); right: calc(8px + env(safe-area-inset-right)); }
/* Help sits by Settings where the top bar has room; elsewhere it is only in
   Settings' header, next to ✕ (owner: "unless screen real estate is at a
   premium"). The top-left cluster leaves room for the wider right one. */
.roomy-only { display: none; }
@media (min-width: 480px) and (max-width: 699px), (min-width: 820px) {
  .roomy-only { display: inline-flex; }
  .topleft { max-width: calc(100vw - 16px - 170px - env(safe-area-inset-left) - env(safe-area-inset-right)); }
}
.cluster .btn { box-shadow: var(--shadow); }

/* ---- Grid-level slider: vertical on the right edge (phone) ---- */
.levels {
  position: fixed; z-index: 3; right: calc(6px + env(safe-area-inset-right)); top: 50%; transform: translateY(-55%);
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 16px; padding: 4px; box-shadow: var(--shadow);
}
.notches { display: flex; flex-direction: column; gap: 2px; }
.notch {
  width: 44px; height: 44px; border: 0; border-radius: 10px; background: transparent; color: var(--ink);
  display: flex; align-items: center; justify-content: center; cursor: pointer; position: relative; padding: 0;
  touch-action: none;
}
.notch svg { overflow: visible; }
.notch svg path { fill: currentColor; opacity: 0.55; }
.notch svg path.cells { fill: none; stroke: var(--bg); stroke-width: 1.2; opacity: 0.8; }
.notch[aria-checked="true"] { background: var(--accent); color: var(--accent-ink); }
.notch[aria-checked="true"] svg path { opacity: 1; }
.notch[aria-checked="true"] svg path.cells { stroke: var(--accent); opacity: 1; }
.lock { width: 44px; min-width: 44px; }
.lock .shackle { transition: transform 0.15s; }
.lock[aria-pressed="true"] .shackle { transform: none; }
.lock[aria-pressed="false"] .shackle { transform: translate(5px, -1px) rotate(18deg); transform-origin: 16px 11px; }
.readout {
  position: fixed; z-index: 3; right: calc(60px + env(safe-area-inset-right)); top: 50%; transform: translateY(-55%);
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 2px 8px; font-size: 13px; color: var(--muted);
  pointer-events: none; opacity: 0; transition: opacity 0.3s;
}
.readout.show { opacity: 1; }

/* ---- Bottom: palette and tools ---- */
.bottom {
  position: fixed; z-index: 3; left: 0; right: 0; bottom: 0;
  padding: 6px calc(6px + env(safe-area-inset-right)) calc(11px + env(safe-area-inset-bottom)) calc(6px + env(safe-area-inset-left));
  display: flex; flex-direction: column; gap: 6px; pointer-events: none;
}
.bottom > * { pointer-events: auto; }
.palette {
  display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; padding: 4px; margin: 0 auto; max-width: 100%;
  background: var(--panel); border: 1px solid var(--border); border-radius: 16px; box-shadow: var(--shadow);
}
.palette::-webkit-scrollbar { display: none; }
.swatch {
  flex: 0 0 44px; width: 44px; height: 44px; border-radius: 50%; border: 2px solid var(--border); padding: 0; cursor: pointer;
  position: relative; overflow: hidden; background: var(--c);
}
.swatch .tones { position: absolute; inset: 0; display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.swatch .tones i:first-child { grid-column: 1 / 3; }
.swatch[aria-checked="true"] { border: 3px solid var(--ink); box-shadow: 0 0 0 2px var(--bg) inset; }
.swatch.tool { background: var(--panel); color: var(--ink); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 20px; }
.swatch.tool svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2; }
.swatch.tool[aria-pressed="true"] { background: var(--pressed); border-color: var(--accent); }
/* Add-color and auto-shade, pinned at the palette's end; inks scroll under them. */
.pal-pinned { position: sticky; right: -4px; display: flex; gap: 6px; margin: -4px -4px -4px auto; padding: 4px 4px 4px 6px;
  background: var(--panel); border-radius: 0 16px 16px 0; box-shadow: -6px 0 8px -6px rgba(0, 0, 0, 0.35); }
.swatch input[type="color"] { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; cursor: pointer; }

.tools {
  display: flex; gap: 4px; justify-content: space-between; margin: 0 auto; width: 100%; max-width: 440px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 16px; padding: 4px; box-shadow: var(--shadow);
}
.tools .btn { flex: 1 1 0; min-width: 44px; border-color: transparent; background: transparent; }
.tools .btn[aria-pressed="true"] { background: var(--pressed); border-color: var(--accent); }
.tools .opts { border-color: var(--border); }

/* ---- Selection bar and handle ---- */
.selbar {
  /* Centered with auto margins, not translate: a translated fixed box shrinks to half the screen and wraps. */
  position: fixed; z-index: 4; left: 0; right: 0; margin: 0 auto; width: max-content; bottom: calc(132px + env(safe-area-inset-bottom));
  display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; max-width: calc(100vw - 16px);
  background: var(--panel); border: 1px solid var(--border); border-radius: 16px; padding: 4px; box-shadow: var(--shadow);
}
.selbar .btn span { font-size: 20px; font-weight: 700; }
/* One row: the less-used actions sit behind ⋯ on phones (shown inline from 768 px). */
.selbar { flex-wrap: nowrap; }
.selbar .mode { font-size: 14px; padding: 0 6px; min-width: 52px; }
.sel-extra { display: none; gap: 4px; }
.selbar.more { flex-wrap: wrap; }
.selbar.more .sel-extra { display: flex; flex-basis: 100%; justify-content: center; }
.chip { min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; font-weight: 700; color: var(--muted); }
.handle {
  position: fixed; z-index: 4; width: 44px; height: 44px; margin: -22px 0 0 -22px; border-radius: 50%;
  background: var(--accent); border: 3px solid var(--bg); box-shadow: var(--shadow); touch-action: none; cursor: ns-resize;
}
.handle::after { content: "⇕"; color: var(--accent-ink); font-weight: 800; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.handle-track {
  position: absolute; left: 52px; top: 50%; display: none; flex-direction: column; gap: 3px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 6px 8px; transform: translateY(-50%);
  font-size: 12px; color: var(--ink); white-space: nowrap;
}
.handle.dragging .handle-track { display: flex; }
.handle-track .tick { display: flex; align-items: center; gap: 6px; opacity: 0.5; }
.handle-track .tick.on { opacity: 1; font-weight: 800; color: var(--accent); }
.handle-track .tick.off { text-decoration: line-through; opacity: 0.25; }
.handle-track .tick.now::after { content: "◀"; font-size: 9px; }

/* ---- Popover (brush shapes, line styles, marquee shapes) ---- */
.popover {
  position: fixed; z-index: 5; left: 0; right: 0; margin: 0 auto; width: max-content; bottom: calc(132px + env(safe-area-inset-bottom));
  background: var(--panel); border: 1px solid var(--border); border-radius: 16px; padding: 8px; box-shadow: var(--shadow);
  display: grid; grid-template-columns: repeat(4, minmax(64px, 1fr)); gap: 6px; max-width: calc(100vw - 16px);
}
.popover .btn { flex-direction: column; min-height: 64px; font-size: 12px; font-weight: 600; padding: 4px; }
.popover .btn svg { width: 28px; height: 28px; }
.popover h4 { grid-column: 1 / -1; margin: 2px 4px; font-size: 14px; color: var(--muted); }

/* The update notice floats over the bottom, just above whatever bars are
   there (app.js sets its bottom), so it covers no control. It does not fade:
   it is an action. */
.update-bar {
  position: fixed; z-index: 6; left: 0; right: 0; margin: 0 auto; bottom: calc(132px + env(safe-area-inset-bottom));
  width: min(34rem, calc(100vw - 16px)); display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 6px 6px 6px 14px; border-radius: 14px; background: var(--ink); color: var(--bg); font-weight: 700; box-shadow: var(--shadow);
}
.update-text { flex: 1 1 12em; min-width: 0; }
.update-buttons { display: flex; gap: 6px; margin-left: auto; }
.update-reload { background: var(--accent); color: var(--accent-ink); border: 0; padding: 0 18px; }
.update-close { background: transparent; color: var(--bg); border: 2px solid currentColor; }

/* The Keep / Behind / Replace chip: an icon over a short word, 48 px square. */
.mode-chip { flex-direction: column; gap: 0; padding: 2px 4px; line-height: 1; }
.mode-chip svg { width: 22px; height: 22px; }
.mode-chip span { font-size: 10px; font-weight: 700; }
.mode-chip[data-mode="replace"] { border-color: var(--accent); }

.toast {
  position: fixed; z-index: 6; left: 50%; top: calc(64px + env(safe-area-inset-top)); transform: translateX(-50%);
  background: var(--ink); color: var(--bg); padding: 8px 14px; border-radius: 10px; max-width: calc(100vw - 32px);
  font-size: 15px; opacity: 0; pointer-events: none; transition: opacity 0.25s;
}
.toast.show { opacity: 1; }
.replay-bar { position: fixed; z-index: 6; left: 50%; top: calc(64px + env(safe-area-inset-top)); transform: translateX(-50%);
  display: flex; gap: 10px; align-items: center; background: var(--panel); border: 1px solid var(--border); border-radius: 14px; padding: 6px 6px 6px 14px; box-shadow: var(--shadow); }

/* ---- Menu ---- */
dialog#settings, dialog#help, dialog#drawing {
  border: 1px solid var(--border); border-radius: 18px; padding: 0; background: var(--bg); color: var(--ink);
  width: min(560px, calc(100vw - 16px)); max-height: calc(100dvh - 24px); box-shadow: var(--shadow);
}
dialog#help::backdrop, dialog#settings::backdrop, dialog#drawing::backdrop { background: rgba(0, 0, 0, 0.35); }
.menu { padding: 12px 16px 20px; user-select: text; -webkit-user-select: text; }
.menu header { display: flex; justify-content: space-between; align-items: center; position: sticky; top: 0; background: var(--bg); }
.menu header .head-btns { display: flex; gap: 6px; }
.menu h2 { margin: 0; font-size: 22px; }
.menu h3 { margin: 18px 0 6px; font-size: 17px; }
.menu fieldset { border: 1px solid var(--border); border-radius: 12px; margin: 8px 0; padding: 6px 10px 10px; }
.menu legend { font-weight: 600; padding: 0 4px; }
.menu label { display: flex; align-items: center; gap: 10px; min-height: 44px; }
.menu input[type="radio"], .menu input[type="checkbox"] { width: 22px; height: 22px; accent-color: var(--accent); flex: none; }
.menu select { min-height: 44px; font: inherit; border-radius: 8px; padding: 0 8px; }
.menu input[type="range"] { flex: 1; min-height: 44px; accent-color: var(--accent); }
.menu .row { display: flex; gap: 8px; align-items: center; }
.menu .wrap { flex-wrap: wrap; }
.menu .note { color: var(--muted); font-size: 14px; margin: 6px 0; }
/* The Drawing sheet's two status lines: 12 px above, between and below (owner: "the copy needs equal margins/padding"). */
dialog#drawing .menu { padding-bottom: 12px; }
#autosave-status, #file-status { margin: 12px 0 0; }
#autosave-status:empty, #file-status:empty { display: none; }
.menu fieldset .btn { margin-top: 6px; }

/* ---- Top bar: labeled buttons (Drawing; New, Open, Save from 700 px) ---- */
.btn.labeled { gap: 6px; padding: 0 12px 0 8px; }
.btn-words { display: flex; flex-direction: column; align-items: stretch; text-align: left; line-height: 1.05; min-width: 0; }
.btn.labeled svg { flex: none; }
.btn-word { font-size: 15px; white-space: nowrap; }
.btn-sub { font-size: 11px; font-weight: 500; color: var(--muted); max-width: 9em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.btn-sub:empty { display: none; }
.wide-only { display: none; }
@media (min-width: 700px) { .wide-only { display: inline-flex; } }
/* The narrowest phones: Drawing shows its folder only (its label stays for screen readers). */
@media (max-width: 359px) { #drawing-open .btn-words { display: none; } #drawing-open { padding: 0 6px; } }

/* ---- Settings: folding sections, as in Noodle Pads ---- */
.set-fold { border-top: 1px solid var(--border); }
.set-fold h3 { margin: 0; }
.set-head {
  width: 100%; min-height: 48px; display: flex; align-items: center; gap: 10px; padding: 6px 4px;
  border: 0; background: transparent; color: var(--ink); font: inherit; font-size: 17px; font-weight: 700; text-align: left; cursor: pointer;
}
.set-head:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.set-head-caret { flex: none; width: 1em; }
.set-head-chip { flex: 0 1 auto; margin-left: auto; padding: 2px 10px; border-radius: 999px; background: var(--panel); border: 1px solid var(--border); font-size: 13px; font-weight: 600; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 55%; }
.set-body { padding: 0 2px 12px; }
/* No heading: the rule is the break below an open fold. */
.set-about { border-top: 1px solid var(--border); padding-top: 8px; margin-top: 4px; }
/* A quiet button that reads as a link (owner: Show the welcome again "should be less dominating"); still 44 px tall. */
.link-btn { display: block; min-height: 44px; padding: 0 4px; border: 0; background: none; color: var(--accent); font: inherit; font-size: 14px; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.link-btn.about-foot { margin: 14px auto -10px; color: var(--muted); font-weight: 500; }
a.link-btn { display: flex; align-items: center; justify-content: center; width: max-content; }
.link-btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.set-about .btn + .btn { margin-top: 8px; }

/* ---- Welcome card: once, on a first visit (web/welcome.js) ---- */
dialog#welcome {
  border: 1px solid var(--border); border-radius: 22px; padding: 0; background: var(--bg); color: var(--ink);
  width: min(360px, calc(100vw - 24px)); max-height: calc(100dvh - 24px); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
}
dialog#welcome::backdrop { background: rgba(0, 0, 0, 0.42); }
.welcome { position: relative; display: grid; gap: 12px; padding: 18px 20px 16px; text-align: center; }
.welcome-close { position: absolute; right: 8px; top: 8px; border-color: transparent; background: transparent; color: var(--muted); }
.welcome-art { justify-self: center; width: 96px; height: 96px; }
.welcome h2 { margin: 0; font-size: 24px; text-wrap: balance; }
.welcome-say { margin: 0; color: var(--muted); }
.welcome-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; text-align: left; }
.welcome-list li { display: grid; grid-template-columns: 40px 1fr; align-items: center; gap: 10px; }
.welcome-ic { width: 40px; height: 40px; border-radius: 10px; background: var(--pressed); display: grid; place-items: center; font-weight: 800; }
.welcome-ic.lit { background: var(--accent); color: var(--accent-ink); }
.welcome-ic svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.welcome-start { min-height: 52px; background: var(--accent); color: var(--accent-ink); border-color: var(--accent); font-size: 18px; border-radius: 14px; }
.welcome-foot { margin: 0; }
/* The build stamp: release and commit, in the strip under the tool bar, as tall as the strip
   (11 px, the bottom padding of .bottom); a link to the repo.
   Too small for a finger by design, so About's version line is the 44 px link. */
.build-stamp {
  position: fixed; z-index: 4; right: calc(10px + env(safe-area-inset-right)); bottom: env(safe-area-inset-bottom);
  font: 11px/11px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--muted); opacity: 0.8;
  text-decoration: none; user-select: none; -webkit-user-select: none;
}
.build-stamp:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; opacity: 1; }
.version { text-align: center; color: var(--muted); font-size: 14px; margin: 14px 0 4px; }
.version a { color: inherit; display: inline-block; padding: 12px 8px; min-height: 44px; }
.help-report { border-top: 1px solid var(--border); margin: 18px 0 4px; padding-top: 12px; text-align: center; }
.help-report a { display: inline-block; padding: 12px 8px; min-height: 44px; color: var(--accent); font-weight: 700; }

/* ---- Drawing sheet: the name, big file buttons ---- */
.menu .name-field { display: flex; flex-direction: column; align-items: stretch; gap: 4px; font-weight: 600; margin: 8px 0 12px; }
.menu .name-field label { min-height: 0; }
.name-row { display: flex; gap: 8px; }
.name-row input { flex: 1; min-width: 0; }
#name-roll { font-size: 24px; flex: none; }
.name-field input { min-height: 48px; font: inherit; font-size: 18px; padding: 0 12px; border-radius: 10px; border: 1px solid var(--border); background: var(--panel); color: var(--ink); }
.big-buttons { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 8px; }
.btn.big { flex-direction: column; min-height: 84px; gap: 6px; font-size: 16px; }
.btn.big svg { width: 32px; height: 32px; }
/* The Drawing sheet's groups: what to do with the drawing, and pictures to share. */
.sheet-group { margin-top: 14px; }
.sheet-group-title { margin: 0 0 6px; font-size: 13px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.btn.big-row { width: 100%; min-height: 64px; justify-content: flex-start; gap: 14px; padding: 8px 16px; text-align: left; }
.btn.big-row svg { width: 32px; height: 32px; flex: none; }
.big-row-words { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.big-row-words > span:first-child { font-size: 16px; }
.big-row-says { font-size: 13px; font-weight: 500; color: var(--muted); }
.sheet-group .link-btn { margin-top: 2px; }
.btn.watch { margin-top: 14px; }
.confirm { border: 2px solid var(--accent); border-radius: 12px; padding: 8px 12px; margin: 10px 0; }
.confirm p { margin: 4px 0 8px; }

/* ---- Help sheet: icon, then name and what it does ---- */
.help-group { margin: 14px 0 2px; font-size: 13px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.help-group:first-child { margin-top: 4px; }
.set-head-chip.lesson-chip { flex: none; max-width: none; }
.help-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.help-list li { display: grid; grid-template-columns: 44px 1fr; gap: 10px; align-items: start; }
.help-icon { width: 44px; min-height: 36px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); }
.help-icon svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.help-icon svg path[fill="currentColor"] { fill: currentColor; }
.help-icon.help-key { font: 700 13px ui-monospace, monospace; text-align: center; line-height: 1.15; padding: 3px 0; }
.help-icon.help-key .help-text-icon { font-size: 12px; }
.help-text-icon { font-weight: 800; font-size: 15px; }
.help b { margin-right: 4px; }

/* ---- Zoom slider: a rail on the left edge, + at the top, − at the bottom ---- */
.zoom {
  position: fixed; z-index: 3; left: calc(6px + env(safe-area-inset-left)); top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px; padding: 3px; box-shadow: var(--shadow);
}
.zoom .btn { min-width: 44px; min-height: 44px; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 10px; background: transparent; }
/* The track shrinks on short screens so the rail never reaches the bars. */
.zoom-track { position: relative; width: 44px; height: clamp(72px, calc(100dvh - 420px), 220px); touch-action: none; cursor: ns-resize; border-radius: 10px; outline: none; }
.zoom-track:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.zoom-track::before { content: ""; position: absolute; left: 20px; width: 4px; top: 14px; bottom: 14px; border-radius: 2px; background: var(--border); }
.zoom-thumb { position: absolute; left: 8px; width: 28px; height: 28px; border-radius: 50%; top: calc((1 - var(--t, 0.5)) * (100% - 28px));
  background: var(--accent); border: 3px solid var(--panel); box-shadow: var(--shadow); pointer-events: none; }

/* Phones: the level slider is a slim rail (the current size and the lock),
   hanging under the top buttons like the zoom rail opposite. Touching it opens
   all eight notches around the finger, with the chosen one staying put unless
   that would run off the screen or into the bottom bars (--nudge, set by
   app.js); it folds again after the finger lifts (.open, set by app.js). */
@media (max-width: 767px), (max-height: 559px) {
  .levels { top: calc(64px + env(safe-area-inset-top)); bottom: auto; transform: none; flex-direction: column; padding: 3px; gap: 4px; border-radius: 14px; }
  .notch-window { position: relative; width: 44px; height: 44px; }
  .notches { position: absolute; left: 0; top: calc(var(--k, 0) * -46px); border-radius: 12px; z-index: 1; }
  .levels.open .notches { top: calc(var(--k, 0) * -46px + var(--nudge, 0px)); }
  .levels:not(.open) .notch-window { overflow: hidden; border-radius: 10px; }
  .levels.open .notches { background: var(--panel); outline: 1px solid var(--border); box-shadow: var(--shadow); }
  /* The open notches pass over the lock's place, so the lock steps aside, still in reach. */
  .levels.open .lock { transform: translateX(-56px); box-shadow: var(--shadow); }
  .levels.open + .readout { right: calc(122px + env(safe-area-inset-right)); }
  .readout { right: calc(64px + env(safe-area-inset-right)); top: calc(80px + env(safe-area-inset-top)); bottom: auto; transform: none; }
  .popover { width: calc(100vw - 16px); grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); }
}

/* ---- Tablet and up: the slider becomes a bar along the top ---- */
@media (min-width: 768px) and (min-height: 560px) {
  /* A second row under the top bar, so the Drawing, New, Open and Save buttons have the first. */
  .levels { top: calc(64px + env(safe-area-inset-top)); right: auto; left: 50%; transform: translateX(-50%); flex-direction: row; }
  .notches { flex-direction: row; }
  .notch { width: 52px; }
  .readout { top: calc(128px + env(safe-area-inset-top)); right: auto; left: 50%; transform: translateX(-50%); }
  .bottom { flex-direction: row; align-items: flex-end; justify-content: center; gap: 10px; }
  .palette { margin: 0; flex: 0 1 auto; }
  .tools { margin: 0; width: auto; flex: 0 0 auto; }
  .tools .btn { flex: 0 0 52px; }
  .selbar, .popover { bottom: calc(80px + env(safe-area-inset-bottom)); margin: 0 auto; max-width: calc(100vw - 16px); }
  #sel-more { display: none; }
  .sel-extra, .selbar.more .sel-extra { display: flex; flex-basis: auto; }
  .selbar.more { flex-wrap: nowrap; }
  .popover { width: max-content; grid-template-columns: repeat(4, minmax(64px, 1fr)); }
}
/* Short landscape phones: the open rail runs leftward along the screen instead,
   and the palette and tools share one row (the palette scrolls under its pinned
   buttons) so the side rails fit between the top buttons and the bottom. The
   brush picker and selection bar sit between the two side rails. */
@media (max-height: 559px) and (min-width: 540px) {
  .bottom { flex-direction: row; align-items: flex-end; justify-content: center; gap: 6px; }
  .palette { margin: 0; flex: 0 1 auto; min-width: 0; }
  .tools { margin: 0; width: auto; flex: 0 0 auto; }
  .tools .btn { flex: 0 0 48px; }
  .selbar, .popover { bottom: calc(76px + env(safe-area-inset-bottom)); max-width: calc(100vw - 132px); }
  .popover { width: max-content; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); }
}
@media (max-height: 559px) {
  .notches { flex-direction: row-reverse; left: auto; top: 0; right: calc(var(--k, 0) * -46px); }
  .levels.open .notches { right: 0; top: 0; } /* the open row sits level with the rail, never shifted up */
  /* Just above the bottom row, clear of the top buttons and the open rail. */
  .readout { top: auto; bottom: calc(80px + env(safe-area-inset-bottom)); left: 0; right: 0; margin: 0 auto; width: max-content; transform: none; }
}

/* Phones: the zoom rail hangs under the top buttons, and its track stays above
   where the brush picker and the selection bar open. Under 620 px tall there
   is no room for a track worth aiming, so only the buttons remain. */
@media (max-width: 767px), (max-height: 559px) {
  .zoom { top: calc(64px + env(safe-area-inset-top)); transform: none; }
  .zoom-track { height: clamp(72px, calc(100dvh - 540px), 220px); }
}
@media (max-width: 767px) and (max-height: 619px), (max-height: 559px) {
  .zoom-track { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* ---- Loading screen (web/loading.js) ----
   Paper from the first frame; after 0.5 s the grid sweeps in clockwise like a
   progress ring (easing toward 0.9 of a turn) under a bar with the icon's cube
   building. loading.js completes the turn when the app is ready, then fades it. */
@property --p { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.loading { position: fixed; inset: 0; z-index: 50; background: var(--bg); color: var(--ink); transition: opacity 0.15s; }
.loading.gone { opacity: 0; pointer-events: none; }
.loading-sweep { position: absolute; inset: 0; opacity: 0; --p: 0deg;
  -webkit-mask-image: conic-gradient(#000 var(--p), transparent 0); mask-image: conic-gradient(#000 var(--p), transparent 0);
  animation: loading-in 0.2s 0.5s forwards, loading-turn 6s 0.5s cubic-bezier(0.2, 0.7, 0.3, 1) forwards; }
.loading.finishing .loading-sweep { opacity: 1; --p: 360deg; transition: --p 0.2s ease-out; }
.loading-paper { position: absolute; inset: 0; background: var(--line);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='27.7128' height='16'%3E%3Cpath d='M0 0V16M13.8564 0V16M27.7128 0V16M0 0L27.7128 16M0 16L27.7128 0' stroke='%23000' stroke-opacity='.16' fill='none'/%3E%3C/svg%3E"), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='110.851' height='64'%3E%3Cpath d='M0 0V64M55.4256 0V64M110.851 0V64M0 0L110.851 64M0 64L110.851 0' stroke='%23000' stroke-opacity='.45' stroke-width='1.2' fill='none'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='27.7128' height='16'%3E%3Cpath d='M0 0V16M13.8564 0V16M27.7128 0V16M0 0L27.7128 16M0 16L27.7128 0' stroke='%23000' stroke-opacity='.16' fill='none'/%3E%3C/svg%3E"), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='110.851' height='64'%3E%3Cpath d='M0 0V64M55.4256 0V64M110.851 0V64M0 0L110.851 64M0 64L110.851 0' stroke='%23000' stroke-opacity='.45' stroke-width='1.2' fill='none'/%3E%3C/svg%3E");
  -webkit-mask-position: center; mask-position: center; }
.loading-bar { position: absolute; left: 0; right: 0; margin: 0 auto; width: max-content; max-width: calc(100vw - 32px);
  bottom: calc(max(48px, 12vh) + env(safe-area-inset-bottom)); display: flex; align-items: center; gap: 12px;
  padding: 10px 18px 10px 12px; background: var(--panel); border: 1px solid var(--border); border-radius: 16px; box-shadow: var(--shadow);
  opacity: 0; animation: loading-in 0.2s 0.5s forwards; }
.loading-cube { width: 44px; height: 44px; flex: none; }
.loading-words { display: flex; flex-direction: column; line-height: 1.15; }
.loading-name { font-size: 20px; font-weight: 800; }
.loading-tag { font-size: 14px; color: var(--muted); }
.loading-slow { position: absolute; left: 16px; right: 16px; top: 40%; margin: 0 auto; max-width: 340px; text-align: center;
  display: grid; gap: 12px; justify-items: center; padding: 16px; background: var(--panel); border-radius: 16px; box-shadow: var(--shadow); }
@keyframes loading-in { to { opacity: 1; } }
@keyframes loading-turn { from { --p: 0deg; } to { --p: 324deg; } }
@media (prefers-reduced-motion: no-preference) {
  .loading-cube polygon { transform-box: fill-box; transform-origin: center; animation: loading-face 2.4s ease-out infinite both; }
  .loading-cube .f2 { animation-delay: 0.3s; }
  .loading-cube .f3 { animation-delay: 0.6s; }
}
@keyframes loading-face { 0% { opacity: 0; transform: scale(0.6); } 14% { opacity: 1; transform: scale(1); } 80% { opacity: 1; } 92%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .loading-sweep { --p: 360deg; animation: loading-in 0.2s 0.5s forwards; }
}

/* ---- Lessons: the bubble and what it points at (web/tour.js) ---- */
.tour {
  position: fixed; z-index: 20; margin: 0; padding: 12px 14px; border-radius: 14px;
  background: var(--panel); color: var(--ink); border: 2px solid var(--accent); box-shadow: var(--shadow);
  font-size: 16px; text-align: left; backdrop-filter: blur(6px);
}
.tour.in-sheet { position: sticky; bottom: 8px; margin: 14px 0 0; width: auto; }
.tour-progress { margin: 0 0 4px; font-size: 13px; font-weight: 700; color: var(--muted); }
.tour-say { margin: 0 0 10px; line-height: 1.35; }
.tour-btns { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.tour-btns .btn { min-height: 44px; }
.tour-btns .tour-go { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.tour-target { outline: 3px solid var(--accent) !important; outline-offset: 3px; border-radius: 12px; }
@media (prefers-reduced-motion: no-preference) {
  .tour-target { animation: tour-pulse 1.6s ease-in-out infinite; }
}
@keyframes tour-pulse { 50% { outline-offset: 6px; } }
