/* ────────────────────────────────────────────────────────────
   Inter Variable — self-hosted, v2 design system primary face.
   Variable font: single file covers weights 100-900. Loaded
   from /fonts/InterVariable.woff2 (~344 KB, ships with deploy).
   Added 2026-05-26, Phase B.
   ──────────────────────────────────────────────────────────── */
@font-face {
  font-family: "Inter";
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  src: url("./fonts/InterVariable.woff2") format("woff2-variations"),
       url("./fonts/InterVariable.woff2") format("woff2");
  font-feature-settings: "cv11", "ss01", "ss03";
}

/* ────────────────────────────────────────────────────────────
   Lucide icon helper (Phase B.2). Used with the SVG sprite at the
   top of <body> via <svg class="icon"><use href="#i-X"/></svg>.
   - Inherits text color via stroke="currentColor" on each <symbol>
   - Sizes to 1em by default so it scales with parent font-size
   - Variants: .icon.sm (0.875em), .icon.md (1.25em), .icon.lg (1.5em)
   ──────────────────────────────────────────────────────────── */
.icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.125em; /* aligns icon to text baseline */
  flex-shrink: 0;
}
.icon.sm { width: 0.875em; height: 0.875em; }
.icon.md { width: 1.25em;  height: 1.25em; }
.icon.lg { width: 1.5em;   height: 1.5em; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ────────────────────────────────────────────────────────────
   SVG Lab — design tokens (OKLCH, warm-tinted neutrals)
   ──────────────────────────────────────────────────────────── */
:root {
  /* ────────────────────────────────────────────────────────────
     v2 TOKEN REMAP (2026-05-26 — same-day pivot)
     The original warm-graphite oklch values are commented in each
     line. The active values are the v2 vibrant-dark palette — pink
     primary accent, near-black surfaces, mint as secondary accent
     (already applied to brand mark + BETA pill in Phase C earlier).
     This single edit propagates the new look through the WHOLE app
     because every component references these tokens by name.
     ──────────────────────────────────────────────────────────── */

  /* Surfaces — near-black scale, slightly warm */
  --bg:           #0B0B10;  /* was oklch(0.200 0.008 70) — warm graphite */
  --bg-deep:      #050507;  /* was oklch(0.155 0.008 70) */
  --panel:        #14141B;  /* was oklch(0.235 0.010 70) */
  --panel-2:      #1C1C25;  /* was #2C2C35 */
  --panel-3:      #26262F;  /* was oklch(0.315 0.012 70) */
  --panel-sunken: #050507;  /* was #1A1A22 */

  /* Structure — semi-transparent white lines for that "modern dark" feel */
  --line:        rgba(255, 255, 255, 0.06);
  --line-soft:   rgba(255, 255, 255, 0.10);
  --line-faint:  rgba(255, 255, 255, 0.04);

  /* Canvas backdrop dot grid (camera-synced via applyView()). A subtle light
     dot on the dark canvas — the "infinite drawing surface" look that Figma /
     tldraw / Miro use. The dots pan and scale with the camera. */
  --grid-dot:    rgba(255, 255, 255, 0.10);

  /* Text — neutral whites instead of warm-cream */
  --ink:         #F5F5F7;  /* was oklch(0.945 0.008 80) */
  --ink-2:       #A1A1AF;  /* was oklch(0.760 0.012 80) */
  --ink-3:       #8A8A99;  /* lightened 2026-05-29 → WCAG AA (#6B6B78 was ~3.4:1 on panels) */
  --ink-4:       #4B4B58;  /* was oklch(0.400 0.010 80) */

  /* Accents — primary palette pivoted to ELECTRIC LIME (#B5FF3A) per
     user reference 2026-05-26. Tool-active highlight, selection chrome,
     snap rings, slider thumbs, primary button state — all lime.
     Selection chrome uses AMBER (#F2D43D) for visual contrast against
     lime CTAs so a selected shape doesn't blend with an active tool. */
  --accent:      #B5FF3A;  /* electric lime — primary CTA */
  --accent-hi:   #C9FF66;  /* lighter lime — hover */
  --accent-lo:   #8FCC1F;  /* darker lime — pressed */
  --accent-soft: rgba(181, 255, 58, 0.18);
  --accent-glow: rgba(181, 255, 58, 0.40);
  --accent-ink:  #0B0B10;  /* dark text on bright lime button */

  /* Selection chrome — amber, distinct from primary lime */
  --select:      #F2D43D;
  --select-soft: rgba(242, 212, 61, 0.18);

  /* Danger */
  --danger:      #FF4D4D;
  --danger-soft: rgba(255, 77, 77, 0.18);

  /* Canvas — neutral dark surface (user direction: canvas stays clean) */
  --canvas-bg:   #0B0B10;
  --doc-bg:      #f7f3ec;  /* keep — this is the SVG document's background */

  /* Spacing scale */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;

  /* Radius */
  --r-1: 4px;
  --r-2: 6px;
  --r-3: 8px;
  --r-pill: 999px;

  /* Motion — single canonical timing scale (2026-05-29 consolidation).
     The legacy --t-* names and the DESIGN.md --dur-* names had drifted to
     different values (fast 110 vs 160, base 200 vs 240 …), so hover timing
     was inconsistent across the app. Both naming systems now resolve to ONE
     scale: snappy values tuned for a product tool. --dur-* alias --t-* below. */
  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-q:  cubic-bezier(0.22, 1, 0.36, 1);
  --ease-press:  cubic-bezier(0.4, 0, 0.6, 1);
  --t-instant: 80ms;
  --t-fast:    130ms;
  --t-base:    200ms;
  --t-slow:    300ms;

  /* Elevation */
  --shadow-1: 0 1px 0 oklch(0 0 0 / 0.28), 0 1px 2px oklch(0 0 0 / 0.18);
  --shadow-2: 0 6px 16px oklch(0 0 0 / 0.36), 0 1px 0 oklch(0 0 0 / 0.40);
  --shadow-3: 0 14px 38px oklch(0 0 0 / 0.46), 0 2px 0 oklch(0 0 0 / 0.50);
  --inner-hi:    inset 0 1px 0 oklch(1 0 0 / 0.06);
  --inner-hi-2:  inset 0 1px 0 oklch(1 0 0 / 0.10);

  /* Focus ring */
  /* Keyboard focus ring: a 2px dark gap then a crisp solid-lime band. The
     outer band was --accent-soft (0.18 alpha) — too faint to read as a focus
     indicator. Solid lime gives a clearly visible ring for keyboard users. */
  --ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);

  /* ────────────────────────────────────────────────────────────
     v2 DESIGN.md tokens (added 2026-05-26, Phase A)
     ----------------------------------------------------------------
     These are the new vibrant-dark token system per DESIGN.md.
     INTENTIONALLY UNUSED in Phase A — defined here so phases B-H can
     swap component usage from legacy tokens (--bg/--panel/--accent)
     to these new ones surgically, one section at a time.
     Do NOT delete the legacy tokens above; they stay until the full
     migration is done.
     ──────────────────────────────────────────────────────────── */

  /* Surfaces — 6-step near-black scale, slightly warm */
  --surface-0: #050507;
  --surface-1: #0B0B10;
  --surface-2: #14141B;
  --surface-3: #1C1C25;
  --surface-4: #26262F;
  --surface-5: #33333D;

  /* Text scale */
  --text-primary:   #F5F5F7;
  --text-secondary: #A1A1AF;
  --text-tertiary:  #8A8A99;  /* bumped from #6B6B78 (~3.5:1) → WCAG AA on panels (2026-05-29) */
  --text-inverse:   #0B0B10;

  /* Vibrant accent palette (extracted from reference image) */
  /* Legacy v2 tokens — DEFINED BUT UNUSED after 2026-05-26 lime pivot.
     Components that referenced these were swapped to lime/olive/amber.
     Kept here so any stray reference resolves to a known color. */
  --accent-mint:     #5DD5C9;
  --accent-violet:   #D459FA;
  --accent-pink:     #F25287;
  --accent-electric: #F02D71;
  /* --accent-lime: now defined below at #B5FF3A (electric lime, new primary) */
  --accent-amber:    #F2D43D;

  /* Soft accent tints (8% alpha — for backgrounds, hover surfaces) */
  --accent-mint-soft:     rgba( 93, 213, 201, 0.08);
  --accent-violet-soft:   rgba(212,  89, 250, 0.08);
  --accent-pink-soft:     rgba(242,  82, 135, 0.08);
  --accent-electric-soft: rgba(240,  45, 113, 0.08);
  /* --accent-lime-soft: redefined below at lime #B5FF3A */
  --accent-amber-soft:    rgba(242, 212,  61, 0.08);

  /* Semantic mappings — repointed to lime palette (2026-05-26).
     --color-info uses amber (distinct from primary lime), --color-pro
     uses olive (the secondary green from the new reference). */
  --color-primary: #B5FF3A; /* lime */
  --color-success: #B5FF3A; /* lime */
  --color-warning: #F2D43D; /* amber */
  --color-info:    #F2D43D; /* amber */
  --color-pro:     #6B8E3D; /* olive */
  --color-danger:  #FF4D4D;

  /* Brand gradients — pivoted to LIME → OLIVE → AMBER (2026-05-26).
     Replaces the previous mint→violet→pink combo per user direction
     "no pink/blue/purple, use the colors from the new reference image." */
  --gradient-brand: linear-gradient(135deg, #B5FF3A 0%, #6B8E3D 50%, #F2D43D 100%);
  --gradient-brand-soft: linear-gradient(135deg,
    rgba(181, 255,  58, 0.15) 0%,
    rgba(107, 142,  61, 0.15) 50%,
    rgba(242, 212,  61, 0.15) 100%);

  /* PRO badge gradients — also pivoted to lime variants. */
  --gradient-pro:      linear-gradient(135deg, #B5FF3A 0%, #F2D43D 100%);
  --gradient-pro-plus: linear-gradient(110deg,
    #B5FF3A 0%, #C9FF66 33%, #F2D43D 66%, #B5FF3A 100%);

  /* Typography stack — Inter loaded in Phase B via @font-face */
  --font-sans: "Inter", "SF Pro Display", -apple-system, BlinkMacSystemFont,
               "Segoe UI", Roboto, sans-serif;
  /* One canonical UI mono stack (2026-05-29). The app had three different
     hardcoded mono stacks (Cascadia / Source Code Pro / JetBrains); all UI
     mono now resolves here. System-first so it renders instantly with no
     web-font dependency or FOUT. (Source Code Pro stays a Text-tool content
     option, not a UI face.) */
  --font-mono: ui-monospace, "Cascadia Code", "Cascadia Mono", "SF Mono",
               "JetBrains Mono", Menlo, Consolas, monospace;

  /* Type sizes (size / line-height pairs — apply via shorthand) */
  --type-display-size: 32px;  --type-display-line: 40px;
  --type-h1-size:      24px;  --type-h1-line:      32px;
  --type-h2-size:      18px;  --type-h2-line:      24px;
  --type-h3-size:      14px;  --type-h3-line:      20px;
  --type-body-size:    13px;  --type-body-line:    18px;
  --type-small-size:   12px;  --type-small-line:   16px;
  --type-tiny-size:    11px;  --type-tiny-line:    14px;
  --type-mono-size:    12px;  --type-mono-line:    16px;

  /* Letter-spacing presets */
  --tracking-brand:   0.02em;
  --tracking-tight:  -0.01em;
  --tracking-caps:    0.06em;
  --tracking-default: 0;

  /* Spacing (4px base — new names alongside legacy --s-N) */
  --space-0: 0;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Radius (new names alongside legacy --r-N) */
  --radius-xs:   4px;
  --radius-sm:   8px;
  --radius-md:  12px;
  --radius-lg:  16px;
  --radius-xl:  20px;
  --radius-2xl: 24px;
  --radius-pill: 999px;

  /* Elevation (new names alongside legacy --shadow-N) */
  --shadow-e1: 0 1px 2px 0 rgba(0,0,0,0.4);
  --shadow-e2: 0 4px 8px -2px rgba(0,0,0,0.4), 0 2px 4px -2px rgba(0,0,0,0.3);
  --shadow-e3: 0 8px 16px -4px rgba(0,0,0,0.5), 0 4px 8px -4px rgba(0,0,0,0.3);
  --shadow-e4: 0 16px 32px -8px rgba(0,0,0,0.6), 0 8px 16px -8px rgba(0,0,0,0.4);

  /* Accent glows for hover/pulse states */
  --shadow-glow-pink:   0 0 32px rgba(242,  82, 135, 0.35);
  --shadow-glow-violet: 0 0 32px rgba(212,  89, 250, 0.35);
  --shadow-glow-mint:   0 0 32px rgba( 93, 213, 201, 0.35);

  /* Lime-palette glows (post-pivot, 2026-05-26). */
  --shadow-glow-lime:   0 0 32px rgba(181, 255,  58, 0.40);
  --shadow-glow-amber:  0 0 32px rgba(242, 212,  61, 0.35);
  --shadow-glow-olive:  0 0 32px rgba(107, 142,  61, 0.40);

  /* Explicit lime + olive accent tokens for components that want to
     reference them by name. */
  --accent-lime:   #B5FF3A;
  --accent-olive:  #6B8E3D;
  --accent-lime-soft:  rgba(181, 255,  58, 0.18);
  --accent-olive-soft: rgba(107, 142,  61, 0.18);

  /* Glass system — for floating chrome (modals, popovers, tooltips).
     Used on translucent surfaces ONLY; structural surfaces stay solid. */
  --glass-base:       rgba(20, 20, 27, 0.65);
  --glass-strong:     rgba(20, 20, 27, 0.85);
  --glass-light:      rgba(255, 255, 255, 0.04);
  --glass-blur:       blur(24px) saturate(180%);
  --glass-blur-heavy: blur(40px) saturate(200%);
  --glass-border-top: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  --glass-border-all: 0 0 0 1px rgba(255, 255, 255, 0.06);

  /* Motion — new easing/duration tokens.
     --ease-out already exists above with the matching value; reusing it. */
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-linear: linear;

  /* DESIGN.md duration names now alias the canonical --t-* scale above so the
     two systems can't drift apart again. --dur-page has no --t-* equivalent. */
  --dur-instant: var(--t-instant);
  --dur-fast:    var(--t-fast);
  --dur-base:    var(--t-base);
  --dur-slow:    var(--t-slow);
  --dur-page:    480ms;
}

/* ────────────────────────────────────────────────────────────
   Light theme — overrides all color tokens.
   Applied via class="theme-light" on <html> for the current page visit.
   Non-color tokens (spacing, radius, motion) stay in :root and
   do not need overriding.
   ──────────────────────────────────────────────────────────── */
.theme-light {
  color-scheme: light;

  /* Surfaces */
  --bg:           #F6F5F0;
  --bg-deep:      #ECEAE3;
  --panel:        #FFFFFF;
  --panel-2:      #F1EEE6;
  --panel-3:      #E8E4D9;
  --panel-sunken: #E8E4D9;

  /* Structure */
  --line:        rgba(20, 20, 27, 0.08);
  --line-soft:   rgba(20, 20, 27, 0.14);
  --line-faint:  rgba(20, 20, 27, 0.04);

  /* Canvas */
  --grid-dot:    rgba(20, 20, 27, 0.12);
  --canvas-bg:   #E8E4D9;

  /* Text */
  --ink:   #1A1A22;
  --ink-2: #4F4F58;
  --ink-3: #6E6E78;
  --ink-4: #A5A5B0;

  /* Accent — olive-lime for light mode */
  --accent:      #6FAE0E;
  --accent-hi:   #82C816;
  --accent-lo:   #5A8E0A;
  --accent-soft: rgba(111, 174, 14, 0.16);
  --accent-glow: rgba(111, 174, 14, 0.30);
  --accent-ink:  #FFFFFF;
  --accent-lime:       #6FAE0E;
  --accent-olive:      #5A8E0A;
  --accent-lime-soft:  rgba(111, 174, 14, 0.16);
  --accent-olive-soft: rgba( 90, 142, 10, 0.18);

  /* Selection chrome */
  --select:      #B8930D;
  --select-soft: rgba(184, 147, 13, 0.16);

  /* Danger */
  --danger:      #C73A3A;
  --danger-soft: rgba(199,  58,  58, 0.16);

  /* Elevation */
  --shadow-1:   0 1px 0 rgba(20,20,27,0.08), 0 1px 2px rgba(20,20,27,0.05);
  --shadow-2:   0 6px 16px rgba(20,20,27,0.08), 0 1px 0 rgba(20,20,27,0.06);
  --shadow-3:   0 14px 38px rgba(20,20,27,0.10), 0 2px 0 rgba(20,20,27,0.06);
  --inner-hi:   inset 0 1px 0 rgba(255,255,255,0.70);
  --inner-hi-2: inset 0 1px 0 rgba(255,255,255,0.85);
  --shadow-e1:  0 1px 2px 0 rgba(20,20,27,0.08);
  --shadow-e2:  0 4px 8px -2px rgba(20,20,27,0.10), 0 2px 4px -2px rgba(20,20,27,0.06);
  --shadow-e3:  0 8px 16px -4px rgba(20,20,27,0.12), 0 4px 8px -4px rgba(20,20,27,0.06);
  --shadow-e4:  0 16px 32px -8px rgba(20,20,27,0.14), 0 8px 16px -8px rgba(20,20,27,0.08);

  /* Glass (floating panels / modals) */
  --glass-base:       rgba(240, 237, 230, 0.80);
  --glass-strong:     rgba(240, 237, 230, 0.95);
  --glass-light:      rgba(20, 20, 27, 0.04);
  --glass-border-top: inset 0 1px 0 rgba(20, 20, 27, 0.06);
  --glass-border-all: 0 0 0 1px rgba(20, 20, 27, 0.08);

  /* v2 surface scale */
  --surface-0: #ECEAE3;
  --surface-1: #F6F5F0;
  --surface-2: #FFFFFF;
  --surface-3: #F1EEE6;
  --surface-4: #E8E4D9;
  --surface-5: #DDD9CE;

  /* v2 text scale */
  --text-primary:   #1A1A22;
  --text-secondary: #4F4F58;
  --text-tertiary:  #6E6E78;
  --text-inverse:   #F5F5F7;

  /* Semantic */
  --color-primary: #6FAE0E;
  --color-success: #6FAE0E;
  --color-warning: #B8930D;
  --color-info:    #B8930D;
  --color-pro:     #5A8E0A;
  --color-danger:  #C73A3A;
}

/* Light-mode component overrides — things that can't be fixed with token
   swaps alone because they use hardcoded dark values in the base rule. */
.theme-light .seg button.active {
  background: linear-gradient(180deg, var(--panel-2) 0%, var(--panel-3) 100%);
  border-color: var(--line-soft);
  color: var(--ink);
}

/* ────────────────────────────────────────────────────────────
   Base
   ──────────────────────────────────────────────────────────── */
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }

body {
  /* v2 design system: Inter as primary (Phase B). System-font fallbacks
     kick in only if the self-hosted Inter file fails to load — should
     never happen in production since the font ships with the deploy. */
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--ink);
  font-size: 12px;
  line-height: 1.4;
  font-feature-settings: "ss01", "cv11";
  letter-spacing: 0.01em;
  overflow: hidden;
  user-select: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

button, input, select { font-family: inherit; font-size: 12px; color: inherit; }
button { -webkit-appearance: none; }

/* Focus rings are applied per-component below — no global override that would
   force a uniform border-radius onto every focusable element. */
button:focus-visible,
input:focus-visible,
select:focus-visible,
.tool:focus-visible,
.swatch-none:focus-visible,
.actions button:focus-visible,
.file-btn:focus-visible,
.row.gap button:focus-visible,
.zoom-pill button:focus-visible {
  outline: none;
  box-shadow: var(--ring);
}
.tool:focus-visible {
  /* tool buttons keep their own border-radius via inheritance */
  box-shadow: var(--ring);
}

/* Broad keyboard focus-ring fallback (2026-05-29): any interactive control not
   covered by a specific rule above still gets a visible ring. :where() keeps
   specificity at 0 so component-specific focus rules still win. */
:where(button, [role="button"], a[href], input, select, textarea, summary, [tabindex]):focus-visible {
  outline: none;
  box-shadow: var(--ring);
}

/* Disabled controls (2026-05-29): the selection-gated panel buttons used to look
   identical whether enabled or not. */
button:disabled, button[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ────────────────────────────────────────────────────────────
   App grid
   Floating-panel layout (Phase C+, 2026-05-26): toolbar and
   properties panel get extra column width so they can float with
   margin and rounded corners inside their grid cells. Topbar +
   statusbar stay full-bleed (structural surfaces per DESIGN.md §5.3).
   ──────────────────────────────────────────────────────────── */
.app {
  display: grid;
  /* Positioning context for detached panels (2026-08-26). A detached toolbar
     or properties panel is taken out of the grid and floated over the canvas,
     with its left/top measured against this box. */
  position: relative;
  grid-template-columns: 68px 1fr 322px;
  grid-template-rows: auto 1fr 26px;
  grid-template-areas:
    "topbar topbar topbar"
    "toolbar canvas properties"
    "statusbar statusbar statusbar";
  height: 100vh;
  width: 100vw;
  /* Uniform field behind everything (matches the canvas tone). The floating
     panels are elevated cards a step lighter than this, so they read as clean
     rounded rectangles with no dark rectangle framing them. (2026-05-29) */
  background: var(--canvas-bg);
}

/* ────────────────────────────────────────────────────────────
   Topbar
   ──────────────────────────────────────────────────────────── */
.topbar {
  grid-area: topbar;
  background:
    linear-gradient(180deg, var(--panel) 0%, var(--panel-2) 100%);
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  /* Hoist above sibling grid areas. The Pro extensions added animations that
     create stacking contexts on .properties / .canvas-area; without an
     explicit z-index here, dropdowns inside the topbar (Export menu) render
     beneath those siblings. Modal/banner z-indexes (100+) still win. */
  position: relative;
  z-index: 50;
}
.topbar-row {
  display: flex;
  align-items: center;
  padding: 8px var(--s-4);
  gap: var(--s-3);
  flex-wrap: wrap;
  min-height: 44px;
}
.topbar-row + .topbar-row {
  border-top: 1px solid var(--line);
  background: oklch(0 0 0 / 0.18);
  min-height: 38px;
  padding: 6px var(--s-4);
}

.row-label {
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 1.4px;
  color: var(--ink-3);
  font-weight: 600;
  margin-right: var(--s-1);
}
.x-sep { color: var(--ink-3); font-size: 11px; }
.ctrl-sep { width: 1px; height: 18px; background: var(--line); margin: 0 var(--s-1); }

/* Brand */
.brand {
  display: flex; align-items: center; gap: 9px;
  padding-right: var(--s-3);
  margin-right: var(--s-1);
  border-right: 1px solid var(--line);
}
/* Brand mark icon — v2 (2026-05-26 lime pivot). Electric lime glow. */
.brand-mark {
  width: 22px; height: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent-lime);
  filter: drop-shadow(0 0 8px rgba(181, 255, 58, 0.30))
          drop-shadow(0 1px 1px rgba(0, 0, 0, 0.4));
  transition: filter var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-spring);
}
.brand:hover .brand-mark {
  transform: rotate(-6deg) scale(1.05);
  filter: drop-shadow(0 0 14px rgba(181, 255, 58, 0.60))
          drop-shadow(0 1px 1px rgba(0, 0, 0, 0.4));
}
.brand-mark svg { width: 100%; height: 100%; display: block; }

/* Brand wordmark — refined tracking + gradient sweep on hover. */
.brand-name {
  font-weight: 600;
  font-size: 13.5px;
  letter-spacing: var(--tracking-brand);
  color: var(--text-primary);
  /* Solid wordmark (2026-05-29): dropped the background-clip:text gradient
     sweep on hover (decorative gradient-text). The mark stays a clean white
     wordmark and shifts to lime on hover — same accent, no gradient. */
  transition: color var(--dur-base) var(--ease-out);
}
.brand:hover .brand-name {
  color: var(--accent-lime);
}
.brand-name em {
  font-style: normal;
  color: var(--text-tertiary);
  font-weight: 400;
  margin-left: 6px;
}
/* .beta-badge rule removed 2026-05-31 — BETA badge swept from editor /
   profile / billing / email templates per "BETA is internal, not user-
   facing." Stays in changelog.html and internal docs. */

.canvas-controls { gap: 6px; }
.canvas-controls #doc-x,
.canvas-controls #doc-y {
  width: 64px;
}

/* Form-like control: select */
.ctrl-select {
  background: var(--panel-sunken);
  border: 1px solid var(--line);
  color: var(--ink);
  padding: 5px 22px 5px 10px;
  border-radius: var(--r-2);
  font-size: 11px;
  cursor: pointer;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23A1A1AF' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 6px center;
  transition:
    border-color var(--t-fast) var(--ease-out),
    background-color var(--t-fast) var(--ease-out);
}
.ctrl-select:hover { background-color: var(--panel-2); border-color: var(--line-faint); }
.ctrl-select:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.ctrl-select option { background: var(--panel); color: var(--ink); }

/* Field wrapper for input + label */
.field {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--panel-sunken);
  padding: 4px 8px;
  border-radius: var(--r-2);
  border: 1px solid var(--line);
  transition:
    border-color var(--t-fast) var(--ease-out),
    background-color var(--t-fast) var(--ease-out);
}
.field:hover { border-color: var(--line-faint); }
.field:focus-within {
  border-color: var(--accent);
  background: #1F1F28;
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.field span {
  font-size: 9.5px;
  color: var(--ink-3);
  text-transform: uppercase;
  letter-spacing: 0.6px;
  font-weight: 600;
}
.field input[type="number"], .field input[type="text"] {
  background: transparent;
  border: none; outline: none;
  width: 56px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  letter-spacing: 0.02em;
}
.field input[type="color"] {
  width: 22px; height: 22px; padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  background: transparent;
  cursor: pointer;
  overflow: hidden;
}
.field input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.field input[type="color"]::-webkit-color-swatch { border: none; border-radius: 3px; }
/* Disabled geometry inputs (2026-08-01) — X/Y/W/H/unit while the active
   artboard is locked. No generic input:disabled rule existed before this. */
.field input:disabled, .ctrl-select:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* The "show BG" — turn the checkbox into a soft pill toggle */
.field.checkbox {
  padding: 4px 10px 4px 8px;
  cursor: pointer;
  gap: 6px;
}
.field.checkbox input { margin: 0; accent-color: var(--accent); cursor: pointer; }

/* Artboard lock toggle (2026-08-01) — topbar control that prevents
   accidental move/resize drags on the artboard surface; shapes stay fully
   editable regardless of state. Same lime active-toggle language as the
   other on/off property buttons (compare .fill-invert-btn / .stroke-taper-
   btn below) so an ON lock reads as unmistakably "on". */
.ab-lock-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  border-radius: var(--r-2);
  background: var(--panel-sunken);
  border: 1px solid var(--line);
  color: var(--ink-3);
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  transition:
    background-color var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out);
}
.ab-lock-btn svg { width: 14px; height: 14px; flex: none; display: block; }
.ab-lock-btn:hover:not(.active) { border-color: var(--line-faint); color: var(--ink); }
.ab-lock-btn.active {
  background: var(--accent-lime-soft, var(--accent-soft));
  color: var(--accent-lime, var(--accent));
  border-color: var(--accent-lime, var(--accent));
}

/* Undo/Redo — moved from the primary actions row into the Artboard row,
   next to Lock (2026-08-25). Same flat-panel register as .ab-lock-btn
   (panel-sunken surface, thin border, ink-3 label) so they read as
   artboard-row controls rather than primary actions. */
.ab-row-btn {
  display: inline-flex;
  align-items: center;
  padding: 5px 10px;
  border-radius: var(--r-2);
  background: var(--panel-sunken);
  border: 1px solid var(--line);
  color: var(--ink-3);
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  transition:
    background-color var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out);
}
.ab-row-btn:hover { border-color: var(--line-faint); color: var(--ink); }

/* Action button group */
.actions {
  margin-left: auto;
  display: flex;
  gap: 4px;
  align-items: center;
}
/* Premium rounded-rect language (2026-05-30 refresh — pill rolled back).
   Flat panel surfaces + soft border + lime halo on hover. Rounded
   rectangles (10px), NOT pills — pills are reserved for the profile
   page's chip language; the editor's buttons stay button-shaped. */
.actions button, .file-btn {
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--ink);
  padding: 0 14px;
  border-radius: 10px;
  cursor: pointer;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.1px;
  height: 30px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  transition:
    background var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    box-shadow var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out),
    transform var(--t-instant) var(--ease-press);
  position: relative;
}
.actions button:hover, .file-btn:hover {
  background: var(--panel-3);
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.actions button:active, .file-btn:active {
  transform: translateY(1px);
  background: var(--panel);
  box-shadow: none;
}
.actions .divider { width: 1px; height: 16px; background: var(--line); margin: 0 var(--s-1); }

/* Export — primary CTA. Solid lime pill, lime halo on hover. */
.actions button#btn-export {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: transparent;
  font-weight: 600;
}
.actions button#btn-export:hover {
  background: var(--accent-hi);
  color: var(--accent-ink);
  border-color: transparent;
  box-shadow: 0 0 0 4px var(--accent-soft);
}
.actions button#btn-export:active {
  background: var(--accent-lo);
  box-shadow: none;
}

/* ────────────────────────────────────────────────────────────
   Toolbar (left) — floating "hanging rectangle" card (Phase C+, 2026-05-26)
   Lifted off the edges with margin, heavily rounded corners give the
   pill-at-top-and-bottom feel from the reference image.
   ──────────────────────────────────────────────────────────── */
.toolbar {
  grid-area: toolbar;
  /* Defined floating panel (2026-05-29): the toolbar used to be fully
     transparent with a transparent border, so the tools floated edgelessly
     in the dark gutter. It now has the working-surface tone + a hairline
     border so it reads as a contained card — same treatment as .properties
     and the canvas, separated by the dark gutter. */
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  margin: 12px 4px 12px 12px;
  display: flex; flex-direction: column;
  padding: 6px 6px 14px;
  gap: 2px;
  align-items: center;
  position: relative;
  /* min-height: 0 lets the toolbar shrink inside its grid row so overflow can
     scroll on short viewports. Without it the grid item refuses to be smaller
     than its content and the last tools spill below the screen. */
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.toolbar::-webkit-scrollbar { width: 6px; }
.toolbar::-webkit-scrollbar-thumb {
  background: #36363F;
  border-radius: 8px;
  border: 1px solid transparent;
  background-clip: padding-box;
}
.toolbar::-webkit-scrollbar-thumb:hover { background: #424252; }
.toolbar::-webkit-scrollbar-track { background: transparent; }
.tool {
  width: 40px; height: 40px;
  background: transparent;
  border: 1px solid transparent;
  color: var(--ink-2);
  cursor: pointer;
  border-radius: var(--r-2);
  display: flex; align-items: center; justify-content: center;
  position: relative;
  transition:
    background-color var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out),
    transform var(--t-instant) var(--ease-press),
    border-color var(--t-fast) var(--ease-out);
}
.tool svg {
  width: 19px; height: 19px;
  display: block;
  pointer-events: none;
  transition: transform var(--t-base) var(--ease-out);
}
.tool:hover {
  background: #303038;
  color: var(--ink);
  border-color: var(--line-faint);
}
.tool:hover svg { transform: scale(1.04); }
.tool:active { transform: scale(0.94); }

.tool.active {
  /* Lime active-tool gradient (was warm gold). 2026-05-26 lime pivot. */
  background: linear-gradient(135deg, #B5FF3A 0%, #8FCC1F 100%);
  color: var(--accent-ink); /* dark text on bright lime */
  border-color: #6B8E3D;
  box-shadow:
    0 1px 0 rgba(0, 0, 0, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    0 0 16px rgba(181, 255, 58, 0.40);
}
/* Active-tool right-edge indicator bar removed 2026-05-29 (user: "green on
   the right side ... gone"). The lime gradient fill alone marks the active
   tool now. */

.tool-sep {
  width: 22px; height: 1px;
  background: var(--line-soft);
  margin: 6px 0;
}

/* ────────────────────────────────────────────────────────────
   Canvas area
   ──────────────────────────────────────────────────────────── */
.canvas-area {
  grid-area: canvas;
  /* Dark frame tone (matches the page-tab strip + gutter). The lighter
     "workspace" --panel tone is now carried by #canvas's own background, so
     when #canvas's top-right cuts off cleanly under the strip, the small
     triangle behind it shows the dark strip color — not a light pocket.
     (2026-05-30) */
  background: var(--bg);
  /* Bottom corners + bottom-left rounding (2026-05-30 user request): parent
     clips its contents to this radius, so the dotted #canvas SVG below shows
     curved BR + BL corners. Top-left stays square (active page tab attaches
     flush). Top-right is rounded on #canvas directly — see #canvas rule — so
     the curve appears on the dotted area, not on the dark page-tab strip. */
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  /* Lift bottom edge to match the 12px gap the toolbar and properties panels
     have above the statusbar — all three panels now share the same bottom line. */
  margin-bottom: 12px;
  position: relative;
  overflow: hidden;
  isolation: isolate;       /* contain the ::before z-index: -1 trick */
}
/* (Page-tab "comet" outline animation removed — 2026-05-30, user request.) */
#canvas {
  width: 100%; height: 100%; display: block; cursor: default;
  /* Camera-synced dot grid (driven by --grid-step / --grid-x / --grid-y, set in
     applyView()). The dots translate with the pan and scale with the zoom, so
     the dark canvas reads as a real movable drawing surface — the way Figma /
     tldraw / Miro render their backdrops. The SVG itself is transparent, so the
     dots sit on the canvas-area tone; the artboard paints over them. */
  /* Workspace tone now lives on #canvas (was on .canvas-area — moved 2026-05-30
     so the rounded-TR cut-off shows the dark strip behind it, not a light
     pocket). The dot grid layers on top via background-image. */
  background-color: var(--panel);
  background-image: radial-gradient(circle, var(--grid-dot) 1.1px, transparent 1.7px);
  background-size: var(--grid-step, 24px) var(--grid-step, 24px);
  background-position: var(--grid-x, 0px) var(--grid-y, 0px);
  /* Round the dotted canvas's top-right corner directly. The dark page-tab
     strip sits ABOVE #canvas, so the parent (.canvas-area) can't round this
     corner — rounding the parent would round the dark strip instead. By
     rounding #canvas itself, the curve appears where the dotted area meets
     the strip — visually matching the parent-clipped BR + BL corners on the
     same dotted area. 2026-05-30 user request. */
  border-top-right-radius: var(--radius-md);
}
#canvas.cursor-crosshair { cursor: crosshair; }
#canvas.cursor-pen { cursor: crosshair; }
#canvas.cursor-grab { cursor: grab; }
#canvas.cursor-grabbing { cursor: grabbing; }
#canvas.cursor-zoom { cursor: zoom-in; }
#canvas.cursor-zoom-out { cursor: zoom-out; }
#canvas.cursor-text { cursor: text; }

/* Zoom pill — v2 liquid glass (Phase C+, 2026-05-26). */
.zoom-pill {
  position: absolute;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--glass-base);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-pill);
  padding: 4px;
  display: flex; align-items: center; gap: 1px;
  box-shadow:
    var(--glass-border-top),
    var(--shadow-e3);
  font-size: 11px;
}
.zoom-pill button {
  background: transparent;
  border: none;
  color: var(--ink);
  padding: 5px 11px;
  border-radius: var(--r-pill);
  cursor: pointer;
  font-size: 12px;
  font-weight: 500;
  transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
  letter-spacing: 0.02em;
}
.zoom-pill button:hover {
  background: #32323A;
  color: var(--ink);
}
.zoom-pill button:active { background: #1A1A22; }
.zoom-pill #zoom-level {
  min-width: 52px;
  text-align: center;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  padding: 0 4px;
  font-weight: 500;
}
.zoom-pill #zoom-out, .zoom-pill #zoom-in {
  font-size: 14px;
  font-weight: 400;
  padding: 4px 11px;
}

/* ────────────────────────────────────────────────────────────
   Properties (right) — floating card (Phase C+, 2026-05-26).
   Mirror of the toolbar: lifted off the edges with margin, rounded
   corners, subtle gradient + border + inner highlight + drop shadow.
   ──────────────────────────────────────────────────────────── */
.properties {
  grid-area: properties;
  /* Defined floating panel (2026-05-29) — see .toolbar. Working-surface tone
     + hairline border so the properties column has a clean contained edge
     instead of rows floating in the gutter. */
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  margin: 12px 12px 12px 4px;
  padding: 0 0 16px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.properties::-webkit-scrollbar { width: 8px; }
.properties::-webkit-scrollbar-thumb {
  background: #36363F;
  border-radius: 8px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
.properties::-webkit-scrollbar-thumb:hover { background: #424252; background-clip: padding-box; border: 2px solid transparent; }
.properties::-webkit-scrollbar-track { background: transparent; }

.prop-group {
  padding: 0 var(--s-3) var(--s-4);
  margin-bottom: var(--s-3);
  border-bottom: 1px solid var(--line);
  position: relative;
}
.prop-group:last-of-type { border-bottom: none; margin-bottom: 0; }
.prop-group h3 {
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 1.4px;
  color: var(--ink-3);
  font-weight: 600;
  margin-bottom: var(--s-3);
  padding: var(--s-2) 0 6px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.prop-group h3::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--line-soft) 0%, transparent 100%);
}

/* Row */
.row { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
.row.gap { gap: 4px; margin-top: var(--s-2); }
.row.gap button {
  flex: 1 1 calc(50% - 2px);
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--ink);
  padding: 6px 8px;
  border-radius: var(--r-2);
  cursor: pointer;
  font-size: 11px;
  font-weight: 500;
  transition:
    background var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    box-shadow var(--t-fast) var(--ease-out),
    transform var(--t-instant) var(--ease-press),
    color var(--t-fast) var(--ease-out);
}
.row.gap button:hover {
  background: var(--panel-3);
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.row.gap button:active {
  background: var(--panel);
  transform: translateY(1px);
  box-shadow: none;
}

/* Color swatch row in stroke/fill */
.row > input[type="color"] {
  width: 40px; height: 32px; padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  background: transparent;
  cursor: pointer;
  overflow: hidden;
  transition: border-color var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}
.row > input[type="color"]:hover { border-color: var(--line-faint); transform: translateY(-1px); }
.row > input[type="color"]::-webkit-color-swatch-wrapper { padding: 2px; }
.row > input[type="color"]::-webkit-color-swatch { border: none; border-radius: 3px; }

/* No-stroke / no-fill swatch */
.swatch-none {
  width: 32px; height: 32px;
  border-radius: var(--r-2);
  background: var(--panel-sunken);
  border: 1px solid var(--line);
  color: var(--ink-3);
  cursor: pointer;
  position: relative;
  font-size: 14px;
  display: flex; align-items: center; justify-content: center;
  transition:
    background-color var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out);
}
.swatch-none:hover { border-color: var(--accent); color: var(--accent); }
.swatch-none::after {
  content: "";
  position: absolute;
  left: 4px; right: 4px;
  top: 50%;
  height: 1.5px;
  background: var(--danger);
  transform: rotate(-30deg);
  pointer-events: none;
  border-radius: 1px;
}
.swatch-none.active {
  background: var(--danger-soft);
  color: var(--danger);
  border-color: var(--danger);
}
.swatch-none.active::after { background: var(--danger); }

/* Slider row */
.slider-row {
  display: grid;
  grid-template-columns: 48px 1fr 52px;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-3);
}
.slider-row span {
  font-size: 11px;
  color: var(--ink-2);
  font-weight: 500;
}
.slider-row input[type="number"] {
  background: var(--panel-sunken);
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  padding: 4px 6px;
  color: var(--ink);
  width: 100%;
  font-variant-numeric: tabular-nums;
  transition: border-color var(--t-fast) var(--ease-out);
}
.slider-row input[type="number"]:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}

/* Custom range slider */
.slider-row input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  background: transparent;
  cursor: pointer;
  height: 18px;
}
.slider-row input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  /* Fluid fill: left of thumb is accent, right is sunken. --fill-pct is set by
     setRangeFill() in app.js whenever the value changes or selection syncs. */
  background: linear-gradient(
    to right,
    var(--accent)       0%,
    var(--accent)       var(--fill-pct, 0%),
    var(--panel-sunken) var(--fill-pct, 0%),
    var(--panel-sunken) 100%
  );
  border-radius: 999px;
  border: 1px solid var(--line);
}
.slider-row input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: linear-gradient(180deg, var(--accent-hi), var(--accent));
  border: 1px solid var(--accent-lo);
  margin-top: -6px;
  box-shadow: 0 1px 2px oklch(0 0 0 / 0.5), var(--inner-hi-2);
  transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out);
  cursor: grab;
}
.slider-row input[type="range"]:hover::-webkit-slider-thumb {
  transform: scale(1.12);
  box-shadow: 0 2px 6px var(--accent-glow), var(--inner-hi-2);
}
.slider-row input[type="range"]:active::-webkit-slider-thumb {
  cursor: grabbing;
  transform: scale(1.06);
}
.slider-row input[type="range"]::-moz-range-track {
  height: 4px;
  background: linear-gradient(
    to right,
    var(--accent)       0%,
    var(--accent)       var(--fill-pct, 0%),
    var(--panel-sunken) var(--fill-pct, 0%),
    var(--panel-sunken) 100%
  );
  border-radius: 999px;
  border: 1px solid var(--line);
}
.slider-row input[type="range"]::-moz-range-thumb {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: linear-gradient(180deg, var(--accent-hi), var(--accent));
  border: 1px solid var(--accent-lo);
  cursor: grab;
}

/* Segmented control */
.seg {
  display: flex;
  gap: 1px;
  margin-top: var(--s-2);
  background: var(--panel-sunken);
  border-radius: var(--r-2);
  padding: 2px;
  border: 1px solid var(--line);
  align-items: center;
  position: relative;
}
.seg .seg-label {
  font-size: 9.5px;
  color: var(--ink-3);
  padding: 0 8px 0 6px;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  font-weight: 600;
  flex-shrink: 0;
}
.seg button {
  flex: 1;
  background: transparent;
  /* Transparent placeholder border so the active state can add a visible
     1px border without shifting adjacent buttons. 2026-05-30. */
  border: 1px solid transparent;
  color: var(--ink-2);
  padding: 5px 4px;
  cursor: pointer;
  border-radius: var(--r-1);
  font-size: 10.5px;
  font-weight: 500;
  transition:
    background var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out),
    box-shadow var(--t-fast) var(--ease-out);
}
.seg button:hover { color: var(--accent); background: var(--accent-soft); }
.seg button.active {
  /* Matches the topbar action buttons (Copy/Paste/Import/…): dark vertical
     gradient + hairline edge + inner highlight + soft outer shadow. So the
     currently-selected option in any segmented control reads as a real
     "pressed pill" of the same family as the topbar buttons. 2026-05-30.
     Radius matches Copy's (--r-2 = 6px) so the corner curvature is identical;
     --inner-hi-2 (10%) is used instead of --inner-hi (6%) so the raised
     highlight stays readable at the smaller seg height (24px vs 28px). */
  background: linear-gradient(180deg, #303038 0%, #26262F 100%);
  border-color: var(--line);
  border-radius: var(--r-2);
  color: var(--ink);
  box-shadow: var(--shadow-1), var(--inner-hi-2);
}

/* X/Y/W/H grid */
.grid2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-1) 6px;
  margin-top: var(--s-3);
}
.grid2 .field { padding: 4px 8px; }
.grid2 .field input { width: 100%; font-size: 11px; }

/* Layers */
.layers-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 4px;
}
.layers-head h3 { margin-bottom: 0; padding: var(--s-2) 0 6px; }
.layers-head h3::after { display: none; }
.layer-count {
  font-size: 10px;
  color: var(--ink-3);
  background: var(--panel-sunken);
  padding: 2px 8px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

#layers {
  list-style: none;
  max-height: 240px;
  overflow-y: auto;
  margin-top: 4px;
  border-top: 1px solid var(--line-faint);
  border-bottom: 1px solid var(--line-faint);
  background: oklch(0 0 0 / 0.10);
  border-radius: var(--r-1);
}
#layers::-webkit-scrollbar { width: 6px; }
#layers::-webkit-scrollbar-thumb { background: #32323A; border-radius: 6px; }
#layers::-webkit-scrollbar-track { background: transparent; }

#layers li {
  padding: 6px 8px 6px 14px;
  border-radius: 0;
  cursor: grab;
  font-size: 11px;
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--ink-2);
  position: relative;
  user-select: none;
  border-top: 1px solid transparent;
  border-bottom: 1px solid transparent;
  transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
#layers li + li { border-top-color: oklch(0 0 0 / 0.18); }

/* Group stripe */
#layers li.in-group::after {
  content: "";
  position: absolute;
  left: 4px; top: 5px; bottom: 5px;
  width: 3px;
  border-radius: 2px;
  background: var(--group-color, var(--accent));
  box-shadow: 0 0 6px color-mix(in oklch, var(--group-color, var(--accent)) 50%, transparent);
}
#layers li.in-group.group-first::after { border-top-left-radius: 2px; border-top-right-radius: 2px; }
#layers li.in-group.group-last::after  { border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; }

#layers li:active { cursor: grabbing; }
#layers li.dragging {
  opacity: 0.45;
  background: var(--panel-sunken);
}
#layers li.drop-above::before,
#layers li.drop-below::after {
  content: "";
  position: absolute;
  left: 6px; right: 6px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
  pointer-events: none;
  box-shadow: 0 0 8px var(--accent-glow);
}
#layers li.drop-above::before { top: -1px; }
#layers li.drop-below::after { bottom: -1px; }

#layers li:hover {
  background: #32323A;
  color: var(--ink);
}
#layers li.selected {
  background: linear-gradient(90deg, var(--accent-soft) 0%, rgba(181, 255, 58, 0.06) 100%);
  color: var(--ink);
  font-weight: 500;
  box-shadow: inset 2px 0 0 var(--accent);
}
#layers li.selected .swatch { border-color: oklch(1 0 0 / 0.25); }

#layers li .swatch {
  width: 12px; height: 12px;
  border-radius: 3px;
  border: 1px solid oklch(0 0 0 / 0.25);
  flex-shrink: 0;
  box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.04);
}
#layers li .name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  letter-spacing: 0.01em;
}
#layers li .lock-btn {
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 3px;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-3);
  border-radius: var(--r-1);
  flex-shrink: 0;
  transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
#layers li .lock-btn:hover {
  background: oklch(1 0 0 / 0.06);
  color: var(--ink);
}
#layers li .lock-btn.locked { color: var(--accent); }
#layers li.locked { opacity: 0.6; }
#layers li.locked .name { font-style: italic; }

#layers li .delete-btn {
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 3px;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-3);
  border-radius: var(--r-1);
  flex-shrink: 0;
  opacity: 0;
  transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out), opacity var(--t-fast) var(--ease-out);
}
#layers li:hover .delete-btn:not(:disabled) { opacity: 1; }
#layers li:hover .delete-btn:disabled { opacity: 0.3; }
#layers li .delete-btn:not(:disabled):hover { background: oklch(1 0 0 / 0.06); color: var(--danger); }
#layers li .delete-btn:disabled { cursor: not-allowed; }

/* ────────────────────────────────────────────────────────────
   Statusbar
   ──────────────────────────────────────────────────────────── */
.statusbar {
  grid-area: statusbar;
  background: var(--panel);
  border-top: 1px solid var(--line);
  font-size: 11px;
  padding: 0 var(--s-4);
  display: flex; align-items: center; justify-content: space-between;
  color: var(--ink-3);
  letter-spacing: 0.01em;
}
.statusbar #status::before {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  margin-right: 8px;
  box-shadow: 0 0 6px var(--accent-glow);
  vertical-align: 1px;
  /* Static "ready" dot. The old infinite opacity pulse was idle decoration
     (and repainted forever); a status indicator doesn't need to breathe. */
}
.cursor-pos {
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.04em;
}
.statusbar-right {
  display: flex;
  align-items: center;
  gap: var(--s-3);
}
.statusbar .version {
  font-size: 10.5px;
  color: var(--ink-3);
  letter-spacing: 0.04em;
  cursor: help;
  font-variant-numeric: tabular-nums;
}
.statusbar .version::before {
  content: "";
  display: inline-block;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
  margin-right: 7px;
  vertical-align: 1px;
  opacity: 0.7;
}
.legal-links {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 10.5px;
  color: var(--ink-3);
  letter-spacing: 0.04em;
}
.legal-links a {
  color: var(--ink-3);
  text-decoration: none;
  transition: color var(--t-fast) var(--ease-out);
}
.legal-links a:hover { color: var(--accent); }
.legal-links .sep { opacity: 0.5; }

/* ────────────────────────────────────────────────────────────
   Hint toast
   ──────────────────────────────────────────────────────────── */
/* Hint toast — v2 liquid glass (Phase C+, 2026-05-26). */
.hint {
  position: fixed;
  bottom: 60px;
  left: 80px; /* clear the 68px toolbar rail (2026-05-29) */
  background: var(--glass-base);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid rgba(255, 255, 255, 0.08);
  padding: 12px 16px;
  border-radius: var(--radius-lg);
  font-size: 11.5px;
  color: var(--ink-2);
  pointer-events: none;
  opacity: 0;
  transform: translateY(6px);
  transition:
    opacity var(--t-base) var(--ease-out),
    transform var(--t-base) var(--ease-out);
  max-width: 380px;
  line-height: 1.5;
  box-shadow:
    var(--glass-border-top),
    var(--shadow-e3);
  z-index: 50;
}
.hint.show { opacity: 1; transform: translateY(0); }
.hint strong {
  color: var(--accent);
  margin-right: 6px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
/* .hint itself is pointer-events:none so it never blocks canvas hovers,
   but inline links inside hints (e.g. "Start over" in the restored-
   autosave hint) need to be clickable. */
.hint a {
  pointer-events: auto;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.hint a:hover { color: var(--ink); }

/* ────────────────────────────────────────────────────────────
   Context menu
   ──────────────────────────────────────────────────────────── */
/* Context menu — v2 liquid glass (Phase C+, 2026-05-26). */
.ctx-menu {
  position: fixed;
  /* Below the modal layer (100) so a right-click menu never paints over an
     open dialog; above the rest of the chrome. Was 1000. */
  z-index: 99;
  background: var(--glass-strong);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: var(--radius-lg);
  padding: 6px;
  min-width: 220px;
  box-shadow:
    var(--glass-border-top),
    var(--shadow-e3);
  display: flex;
  flex-direction: column;
  gap: 1px;
  font-size: 12px;
  /* Elastic "bubble pop" entrance — overshoots past full size then settles. */
  animation: ctx-pop 240ms var(--ease-spring);
  transform-origin: top left;
}
@keyframes ctx-pop {
  from { opacity: 0; transform: scale(0.82); }
  60%  { opacity: 1; }
  to   { opacity: 1; transform: scale(1); }
}
.ctx-menu[hidden] { display: none; }
.ctx-menu button {
  background: transparent;
  border: none;
  color: var(--ink);
  padding: 7px 12px;
  cursor: pointer;
  text-align: left;
  border-radius: var(--r-1);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.ctx-menu button:hover {
  /* Text glows lime on hover (matches the universal hover language); a faint
     frosted lift marks the active row instead of a solid lime fill. */
  background: var(--glass-light);
  color: var(--accent-lime);
}
.ctx-menu button:hover .kbd { color: var(--accent-lime); opacity: 0.7; }
.ctx-menu button:disabled { color: var(--ink-4); cursor: default; }
.ctx-menu button:disabled:hover { background: transparent; color: var(--ink-4); }
.ctx-menu hr {
  border: none;
  border-top: 1px solid var(--line-soft);
  margin: 4px 6px;
}
.ctx-menu .kbd {
  font-size: 10px;
  color: var(--ink-3);
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
}

/* ────────────────────────────────────────────────────────────
   SVG overlay guides
   ──────────────────────────────────────────────────────────── */
#overlay .selbox {
  fill: none;
  stroke: var(--select);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 4 3;
}

/* Artboard resize chrome — drag the artboard's edges/corners to resize it.
   Lime, to set it apart from the amber shape-selection chrome. The frame is a
   thin lime outline; handles are dark squares with a lime ring (fill lime on
   hover). Shown only when the Select tool is active and nothing is selected. */
#overlay .ab-frame {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  opacity: 0.55;
  pointer-events: none;
}
/* Locked artboard frame (2026-08-01) — muted + dashed instead of lime-solid,
   so a locked artboard reads as "selected but not draggable" at a glance.
   No resize handles are drawn at all for a locked artboard (see
   renderArtboardChrome in app.js), so this frame is the only chrome shown. */
#overlay .ab-frame.locked {
  stroke: var(--ink-3);
  stroke-dasharray: 5 4;
  opacity: 0.7;
}
#overlay .ab-handle {
  fill: var(--bg);
  stroke: var(--accent);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}
#overlay .ab-handle:hover { fill: var(--accent); }
#overlay .ab-guide {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 7 5;
  opacity: 0.9;
  pointer-events: none;
}
#overlay .ab-guide.center {
  stroke-dasharray: 2 4;
}

/* Artboard name labels (Figma/Paper style) — sit above each artboard. Click to
   select, drag to move, double-click to rename. The active artboard's label is
   lime; others are muted until hovered. */
#artboards .ab-label {
  fill: var(--ink-2);
  font-family: var(--font-sans);
  font-weight: 500;
  letter-spacing: 0.02em;
  cursor: move;
  -webkit-user-select: none;
  user-select: none;
  transition: fill var(--t-fast) var(--ease-out);
}
#artboards .ab-label.active { fill: var(--accent); }
#artboards .ab-label:hover { fill: var(--accent-hi); }
#artboards .ab-label .ab-lock-status {
  fill: var(--danger);
  font-weight: 750;
  letter-spacing: 0.08em;
}
/* Artboard groups (2026-08-28): a dashed lasso drawn behind the artboards
   that share a group name, so a set reads as one unit on the canvas. Muted
   until the active artboard belongs to it, then lime like the rest of the
   artboard chrome. The label above it frames the whole group on click. */
#artboards .ab-group-frame {
  fill: none;
  stroke: var(--ink-3);
  stroke-width: 1.25;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 9 7;
  opacity: 0.45;
}
#artboards .ab-group-frame.active {
  stroke: var(--accent);
  opacity: 0.6;
}
/* Invisible fat stroke over the group frame: grab it anywhere along the
   dashed border to drag the whole group. Fill stays none so only the border
   line is hit-testable. */
#artboards .ab-group-grab {
  fill: none;
  stroke: transparent;
  cursor: move;
}
#artboards .ab-group-label {
  fill: var(--ink-3);
  font-family: var(--font-sans);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: move;
  -webkit-user-select: none;
  user-select: none;
  transition: fill var(--t-fast) var(--ease-out);
}
#artboards .ab-group-label.active { fill: var(--accent); }
#artboards .ab-group-label:hover { fill: var(--accent-hi); }

.artboard-rename-input {
  position: fixed;
  z-index: 130;
  box-sizing: border-box;
  padding: 2px 8px;
  border: 1px solid var(--accent);
  border-radius: 4px;
  background: var(--panel);
  color: var(--ink);
  font: 500 12px/1.4 var(--font-sans);
  letter-spacing: 0;
  outline: none;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.28);
}
.artboard-rename-input::selection {
  background: color-mix(in oklab, var(--accent) 45%, transparent);
}
#overlay .anchor {
  fill: white;
  stroke: var(--select);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
#overlay .anchor.smooth { fill: var(--select); }
#overlay .path-edit-line {
  fill: none;
  stroke: var(--select);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  opacity: 0.95;
  pointer-events: none;
}
#overlay .handle-line {
  stroke: var(--select);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  fill: none;
}
#overlay .handle-dot {
  fill: var(--select);
  stroke: white;
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
#overlay .resize {
  fill: white;
  stroke: var(--select);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
#overlay .preview {
  fill: rgba(242, 212, 61, 0.06);
  stroke: var(--select);
  stroke-width: 1;
  stroke-dasharray: 4 3;
  vector-effect: non-scaling-stroke;
}
#overlay .pen-preview {
  fill: none;
  stroke: var(--select);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  vector-effect: non-scaling-stroke;
}
#overlay .snap-ring {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
  animation: snap-pulse 1.2s ease-in-out infinite;
}
#overlay .snap-dot {
  fill: var(--accent);
  vector-effect: non-scaling-stroke;
}

/* Rotation handle — small stem with a dot above the selection bbox. The dot
   is the grab target; the corner rings (rot-corner-zone) are invisible but
   pick up "just past the corner" drags. */
#overlay .rot-stem {
  stroke: var(--accent);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  opacity: 0.65;
}
#overlay .rot-handle {
  fill: var(--accent);
  stroke: white;
  stroke-width: 1.2;
  vector-effect: non-scaling-stroke;
  cursor: grab;
  transition: transform 120ms cubic-bezier(0.16, 1, 0.3, 1);
}
#overlay .rot-handle:hover {
  fill: var(--accent-hi);
}
#overlay .rot-corner-zone {
  /* invisible but pickable */
  cursor: grab;
}

/* While a rotation drag is active, every cursor in the document shows the
   "grabbing" state — keeps feedback consistent even when the pointer
   crosses out of the original handle bounds during the drag. */
body.cursor-rotating,
body.cursor-rotating * {
  cursor: grabbing !important;
}
@keyframes snap-pulse {
  0%, 100% { opacity: 0.7; }
  50%      { opacity: 1; }
}

/* ────────────────────────────────────────────────────────────
   Text properties section
   ──────────────────────────────────────────────────────────── */
.prop-text .field.full {
  width: 100%;
}
.prop-text .field.full > span {
  min-width: 32px;
}
.prop-text .field.full .ctrl-select {
  flex: 1;
  width: 100%;
}
textarea.text-content {
  width: 100%;
  min-height: 56px;
  max-height: 160px;
  resize: vertical;
  padding: var(--s-2) var(--s-3);
  background: var(--panel-sunken);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  color: var(--ink);
  font-family: inherit;
  font-size: 12px;
  line-height: 1.4;
  outline: none;
  transition: border-color var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out);
  margin-bottom: var(--s-2);
}
textarea.text-content:hover { border-color: var(--line-faint); }
textarea.text-content:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Style toggle buttons (B / I / U) render their label glyph straight */
#text-style-seg button b,
#text-style-seg button i,
#text-style-seg button u {
  font-size: 13px;
  font-style: normal;
  text-decoration: none;
}
#text-style-seg button b      { font-weight: 700; }
#text-style-seg button i      { font-style: italic; font-family: 'Georgia', 'Times New Roman', serif; }
#text-style-seg button u      { text-decoration: underline; text-underline-offset: 2px; }

/* ────────────────────────────────────────────────────────────
   Inline text editor — textarea overlaid on the canvas while typing
   ──────────────────────────────────────────────────────────── */
.text-editor {
  position: absolute;
  z-index: 100;
  margin: 0;
  padding: 0;
  border: 1px dashed var(--accent);
  border-radius: 2px;
  outline: none;
  resize: none;
  overflow: hidden;
  background: oklch(1 0 0 / 0.04);
  color: inherit;
  white-space: pre;
  word-wrap: normal;
  font-family: inherit;
  font-size: 16px;
  line-height: 1.2;
  caret-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  user-select: text;
}
.text-editor::selection { background: var(--accent-soft); }

/* ────────────────────────────────────────────────────────────
   Entrance reveal (2026-05-29: de-choreographed).
   The old version slid the topbar/toolbar/properties/statusbar in from
   four different directions with staggered delays — an orchestrated
   page-load sequence, which a product tool should not do (the register
   rule: "Product loads into a task; users don't want to watch it load").
   Replaced with a single quick whole-app opacity fade so first paint isn't
   a hard flash, but nothing moves and nothing staggers.
   ──────────────────────────────────────────────────────────── */
.app { animation: fade-in 180ms var(--ease-out) both; }

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0ms !important;
    transition-duration: 0ms !important;
  }
}

/* ────────────────────────────────────────────────────────────
   Pro extensions — gradients, swatches, effects, alignment,
   booleans, components, autotrace, pages, rulers, modals
   ──────────────────────────────────────────────────────────── */

/* Split button + dropdown — pill-shaped split (2026-05-30 refresh).
   The two halves keep their rounded outer corners and share a hairline
   divider in the middle, so the pair reads as one continuous pill.
   Used for both #export-split and #user-menu. */
.split-btn { position: relative; display: inline-flex; }
.split-btn > button:not(.caret) {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  border-right: none;
}
.split-btn .caret {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  padding: 0 10px;
  border-left: 1px solid var(--line);
}
.split-btn .menu {
  position: absolute; top: calc(100% + 6px); right: 0;
  background: var(--panel); border: 1px solid var(--line-soft); border-radius: var(--r-3);
  box-shadow: var(--shadow-2); padding: 6px; min-width: 180px; z-index: 80;
  display: flex; flex-direction: column; gap: 2px;
}
.split-btn .menu button {
  text-align: left; padding: 7px 10px; font-size: 12px;
  background: transparent; border: none; color: var(--ink);
  border-radius: var(--r-2); cursor: pointer;
  transition: background var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out);
}
.split-btn .menu button:hover { background: var(--panel-2); color: var(--accent); }

/* Fill type segmented tabs */
.seg-tabs button { padding: 4px 8px; font-size: 11px; }

/* Gradient + pattern editors */
.gradient-editor, .pattern-picker {
  margin-top: 6px;
  padding: 8px; border: 1px dashed var(--line-soft); border-radius: var(--r-2);
  background: var(--panel-sunken);
  display: flex; flex-direction: column; gap: 6px;
}
.gradient-preview {
  height: 22px; border-radius: var(--r-1); border: 1px solid var(--line);
  cursor: pointer;
}
.gradient-editor .row.gap button.mini,
.gradient-editor .row.gap .field { font-size: 11px; }
.pattern-picker .grid-pats {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px;
}
.pattern-picker .pat-cell {
  width: 100%; aspect-ratio: 1/1; border: 1px solid var(--line);
  border-radius: var(--r-1); cursor: pointer; background-size: 14px 14px;
}
.pattern-picker .pat-cell.active {
  outline: 2px solid var(--accent); outline-offset: 1px;
}

/* Eyedropper icon button */
/* Small text buttons in property rows. There was no bare .mini rule, so
   these fell back to the browser's default system button: a light
   ButtonFace behind the app's light text, which rendered "Apply" as white
   on white (measured 1.05:1). .swatches-head .mini is more specific and
   still wins for the swatch "+" button. */
.mini {
  padding: 2px 8px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  color: var(--ink-2);
  font: inherit;
  font-size: 11px;
  line-height: 1.6;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.mini:hover {
  background: var(--panel-3);
  border-color: var(--accent);
  color: var(--accent);
}

.mini-icon {
  padding: 3px 7px; background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--r-2); color: var(--ink-2); cursor: pointer;
  transition:
    background var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    box-shadow var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out);
}
.mini-icon:hover {
  background: var(--panel-3);
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Swatches */
.swatches {
  margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--line-faint);
}
.swatches-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--ink-3); margin-bottom: 4px;
}
.swatches-head .mini {
  background: var(--panel-2); border: 1px solid var(--line); color: var(--ink-2);
  border-radius: var(--r-1); width: 18px; height: 18px; cursor: pointer; line-height: 1;
}
.swatches-grid {
  display: grid; grid-template-columns: repeat(10, 1fr); gap: 3px;
}
.swatch-chip {
  aspect-ratio: 1/1; border-radius: 3px; border: 1px solid var(--line);
  cursor: pointer; padding: 0;
}
.swatch-chip:hover { outline: 1px solid var(--accent); }
.swatch-chip.active { outline: 2px solid var(--accent); outline-offset: 1px; }
.swatch-chip[data-removable]:active { transform: scale(0.95); }

/* Align row icons */
.align-row button {
  width: 30px; height: 26px; padding: 0;
  font-family: 'Segoe UI Symbol', sans-serif; font-size: 16px;
}

/* Pages strip — v2 redesign (Phase C). White-pill active tab + smooth
   hover transitions, matching the reference image's segmented control. */
.pages-strip {
  /* Tab strip for "round-out" tabs (Chris Coyier / Frontend Masters technique:
     https://frontendmasters.com/blog/modern-css-round-out-tabs/). Each tab is
     clip-path:shape()'d into a silhouette with rounded TOP corners and bottom
     corners that flare OUTWARD into the workspace below — a paper-tab look.
     The strip is just the dark chrome backdrop; no baseline border needed —
     the tabs' own flared feet visually land on the workspace. */
  display: flex; align-items: flex-end; gap: 2px;
  /* No left padding — the first tab sits flush against the strip's left edge,
     so its bottom-left flare merges directly into the workspace below (both
     are --panel) and the "notch" between toolbar and Page 1 disappears. */
  padding: 10px 14px 0 0; background: var(--bg);
  overflow-x: auto;
  position: relative; z-index: 2;
}
.page-tab {
  /* Round-out tabs — verbatim CSS clip-path:shape() from the Frontend Masters
     article (Block 8, the variablized recommended version). The shape begins
     at bottom-left and walks: flare-out curve up, vertical, top-left curve in,
     horizontal across the top, top-right curve in, vertical down, flare-out
     curve to bottom-right. Result: a tab silhouette with rounded TOP corners
     and bottom corners that flare OUTWARD — exactly like a Chrome paper tab. */
  --tabGirth: 10px;

  position: relative;
  display: inline-flex;           /* preserve internal text + dot + close-× alignment */
  align-items: center;
  padding: 7px 22px;              /* extra inline padding so text clears the bottom flares */
  /* Inactive: subtle midpoint between strip (--bg) and active tab (--panel) —
     visible silhouette, clearly behind the active tab. */
  background: color-mix(in srgb, var(--bg) 75%, var(--panel) 25%);
  border: none;                   /* clip-path replaces all border-based shaping */
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 11.5px;
  font-weight: 500;
  white-space: nowrap;
  letter-spacing: 0.01em;
  transition:
    background-color var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out);

  /* Asymmetric round-out tab — Frontend Masters Block 8 with the LEFT-bottom
     flare removed. The tab's left edge is a straight vertical at x=0 from the
     bottom up to the rounded top-left corner — aligned with the workspace's
     left edge below (strip has padding-left:0), so the tab body sits flush
     against the dotted "pan" on the left. The RIGHT side keeps Block 8's
     outward flare — the tab still has its "pan-foot" curvature on the trailing
     side. Walk: straight up the left, curve into top-left, across the top,
     curve into top-right, straight down the right, flare out at bottom-right. */
  clip-path: shape(
    from bottom left,
    vline to var(--tabGirth),
    curve to var(--tabGirth) 0 with 0 0,
    hline to calc(100% - calc(var(--tabGirth) * 2)),
    curve to calc(100% - var(--tabGirth)) var(--tabGirth) with calc(100% - var(--tabGirth)) 0,
    vline to calc(100% - var(--tabGirth)),
    curve to 100% 100% with calc(100% - var(--tabGirth)) 100%
  );

  /* Fallback for engines without clip-path: shape() support — verbatim Block 9. */
  @supports not (clip-path: shape(from top left, hline to 0)) {
    padding-inline: 1rem;
    border-start-start-radius: var(--tabGirth);
    border-start-end-radius: var(--tabGirth);
  }
}
.page-tab:hover {
  background: color-mix(in srgb, var(--bg) 60%, var(--panel) 40%);
  /* Lime glow on hover — text turns accent + drop-shadow gives the
     "green light" feel the user asked for. drop-shadow respects clip-path,
     so the glow follows the round-out tab silhouette. */
  color: var(--accent);
  filter: drop-shadow(0 0 6px var(--accent-glow));
}
.page-tab.active {
  /* Active tab — visually MERGED with the dotted canvas below. The same
     camera-synced radial-gradient dot pattern (driven by --grid-step/x/y on
     :root) paints across the tab so the tab reads as a piece of the canvas
     lifted up into the strip — not a separate panel. The clip-path shape gives
     the rounded silhouette. A rotating lime conic-gradient "shine" traces the
     tab's perimeter (same mechanism as the feedback pill, clipped to the
     round-out silhouette), and an additional drop-shadow filter extends the
     glow OUTSIDE the silhouette into the canvas area below. */
  background:
    radial-gradient(circle, var(--grid-dot) 1.1px, transparent 1.7px) var(--grid-x, 0px) var(--grid-y, 0px) / var(--grid-step, 24px) var(--grid-step, 24px),
    var(--panel);
  color: var(--ink);
  font-weight: 600;
  isolation: isolate;       /* contain the ::before z-index:-1 trick */
  /* No glow animation here (removed 2026-09-26). A filter applies BEFORE
     clip-path, so the drop-shadow that used to "breathe" around this tab was
     clipped away by the tab's own silhouette: pixel diffs of the tab at the
     glow's peak and with no filter at all were identical. It still repainted
     every frame, which kept an idle editor busy for nothing. */
}
/* The two separate perimeter rings (tab + canvas) have been replaced by a
   SINGLE comet element (#page-comet) that travels a continuous compound
   path: tab left → top → right → (turn) → canvas top → right → bottom → left
   → (close) back to tab bottom-left → up the tab left again. The path is
   generated in JS (updatePageCometPath) based on the active tab's measured
   bounds + canvas-area's bounds, so one moving light reads as ONE continuous
   green shine flowing around the page's outline. (2026-05-29) */
.page-tab.active:hover {
  /* On hover, brighten the text — the conic shine already provides motion. */
  color: var(--accent);
}
/* Status slot — the green dot and the close × occupy ONE spot (browser-tab
   pattern). The dot shows by default; hovering the tab cross-fades the dot out
   and the × in, so the × lands exactly where the dot was. */
.tab-slot {
  /* Enlarged to a reliable hit target (was 13px — too small, clicks often
     fell through to the parent tab and switched pages instead of deleting).
     Now an 18px square so the × is comfortably clickable. */
  position: relative;
  width: 18px; height: 18px;
  margin-left: 8px;
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
}
.tab-slot .page-dot {
  /* Retired from view (2026-09-21): the close × now shows at all times, so the
     dot would sit underneath it. The active tab is still distinct via its fill,
     perimeter shine and lime hover. Kept so the pulse can be restored by
     removing this one line. */
  display: none;
  /* The dot stays small + centered; pointer-events:none so clicks pass through
     to the × beneath. */
  position: absolute;
  top: 50%; left: 50%;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 6px var(--accent-glow);
  transition: opacity var(--dur-fast) var(--ease-out);
  pointer-events: none;
  /* Soft pulse — the green dot "breathes" so the active tab feels alive. */
  animation: page-dot-pulse 2.4s ease-in-out infinite;
}
@keyframes page-dot-pulse {
  /* Scale only: a looping box-shadow repaints the page every frame (2026-09-26). */
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50%      { transform: translate(-50%, -50%) scale(1.15); }
}
.tab-slot .x {
  /* The × fills the entire 18px slot — large click target. Text remains
     small and visually centered, but the click area covers the whole slot. */
  position: absolute;
  inset: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 15px;
  line-height: 1;
  border-radius: 50%;
  opacity: 0.55;         /* always visible so the close control is discoverable */
  color: var(--ink-2);
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.page-tab:hover .tab-slot .page-dot { opacity: 0; animation: none; }
.page-tab:hover .tab-slot .x { opacity: 0.9; }
.tab-slot .x:hover { opacity: 1 !important; color: var(--ink); background: rgba(255, 255, 255, 0.08); }
.page-tab.active .tab-slot .x { color: var(--ink); }

.page-add {
  background: transparent;
  border: 1px dashed rgba(255, 255, 255, 0.12);
  color: var(--text-tertiary);
  /* Rounded RECTANGLE, not a pill (user request, repeated) — matches the
     page tab's 9px corner radius for a consistent shape language. */
  border-radius: 9px;
  padding: 6px 14px;
  /* Lift off the canvas so its bottom edge isn't kissing the dotted workspace
     below — user said it felt cramped. 6px gap keeps it visually contained
     in the strip while still aligned with the tabs' baseline area. */
  margin-bottom: 6px;
  cursor: pointer;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
  transition:
    color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    border-style var(--dur-fast) var(--ease-out);
}
.page-add:hover {
  color: var(--text-primary);
  border-color: rgba(255, 255, 255, 0.25);
  border-style: solid;
}

/* Rulers */
.rulers {
  position: absolute; inset: 0; pointer-events: none;
  font-family: var(--font-mono); font-size: 9px;
  color: var(--ink-3);
}
.ruler { position: absolute; background: var(--panel-sunken); border-color: var(--line-faint); }
.ruler-x { top: 0; left: 18px; right: 0; height: 18px; border-bottom: 1px solid; }
.ruler-y { top: 18px; left: 0; bottom: 0; width: 18px; border-right: 1px solid; }
.ruler-corner {
  position: absolute; top: 0; left: 0; width: 18px; height: 18px;
  background: var(--panel-sunken); border-right: 1px solid var(--line-faint);
  border-bottom: 1px solid var(--line-faint);
}
.canvas-area.has-rulers .ruler-x .tick,
.canvas-area.has-rulers .ruler-y .tick {
  position: absolute; color: var(--ink-3);
}

/* Code panel */
.code-panel {
  position: fixed; right: 0; top: 0; bottom: 0;
  width: min(380px, 100vw); background: var(--panel); border-left: 1px solid var(--line);
  display: flex; flex-direction: column; z-index: 90;
  box-shadow: var(--shadow-3);
}
.code-panel-head {
  display: flex; align-items: center; gap: 8px; padding: 10px 12px;
  border-bottom: 1px solid var(--line);
}
.code-panel-head h3 { flex: 1; font-size: 12px; }
.code-panel-head button {
  padding: 4px 10px; background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--r-1); color: var(--ink); cursor: pointer;
}
.code-panel-head button.ghost { background: transparent; }
.code-panel textarea {
  flex: 1; resize: none; background: var(--bg-deep); color: var(--ink);
  font-family: var(--font-mono); font-size: 11px;
  padding: 10px; border: none; outline: none; white-space: pre;
}

/* Modals — v2 redesign (Phase C+, 2026-05-26).
   True liquid glass: heavy backdrop blur on the scrim AND on the card,
   visible top-edge highlight, deep shadow for depth. */
.modal {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(8px) saturate(140%);
  -webkit-backdrop-filter: blur(8px) saturate(140%);
  display: flex; align-items: center; justify-content: center;
  animation: modal-scrim-in 240ms var(--ease-out);
}
.modal[hidden] { display: none; }
.modal-card {
  background: var(--glass-base);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-xl);
  box-shadow:
    var(--glass-border-top),
    var(--shadow-e4),
    0 0 80px rgba(0, 0, 0, 0.5);
  padding: 20px;
  min-width: 360px; max-width: 90vw;
  display: flex; flex-direction: column; gap: 12px;
  animation: modal-card-in 320ms var(--ease-spring);
}
@keyframes modal-scrim-in {
  from { opacity: 0; backdrop-filter: blur(0); -webkit-backdrop-filter: blur(0); }
  to   { opacity: 1; }
}
@keyframes modal-card-in {
  from { opacity: 0; transform: translateY(12px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.modal-head {
  display: flex; align-items: center; justify-content: space-between;
}
.modal-head h3 { font-size: 13px; }
.modal-head .ghost {
  background: transparent; border: none; color: var(--ink-3); cursor: pointer;
  font-size: 18px; line-height: 1;
}

.trace-preview-card {
  width: min(980px, 94vw);
  max-height: 92vh;
}
.trace-preview-meta {
  min-height: 18px;
  color: var(--ink-3);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.trace-preview-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
  min-height: 0;
}
.trace-preview-grid figure {
  margin: 0;
  display: grid;
  grid-template-rows: auto minmax(220px, 44vh);
  gap: 6px;
  min-width: 0;
}
.trace-preview-grid figcaption {
  color: var(--ink-2);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.trace-preview-frame {
  display: grid;
  place-items: center;
  overflow: hidden;
  border: 1px solid var(--line-soft);
  border-radius: var(--r-2);
  background:
    linear-gradient(45deg, rgba(255,255,255,0.055) 25%, transparent 25% 75%, rgba(255,255,255,0.055) 75%),
    linear-gradient(45deg, rgba(255,255,255,0.055) 25%, transparent 25% 75%, rgba(255,255,255,0.055) 75%);
  background-color: var(--bg-deep);
  background-position: 0 0, 8px 8px;
  background-size: 16px 16px;
}
.trace-preview-frame img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
.trace-preview-controls {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
  gap: 10px;
  align-items: end;
}
.trace-preview-footer {
  justify-content: flex-end;
}
.trace-preview-card.is-busy .trace-preview-frame,
.trace-preview-card.is-busy .trace-preview-footer {
  opacity: 0.55;
}
.trace-preview-card.is-busy button,
.trace-preview-card.is-busy select {
  pointer-events: none;
}

@media (max-width: 760px) {
  .trace-preview-grid,
  .trace-preview-controls {
    grid-template-columns: 1fr;
  }
  .trace-preview-grid figure {
    grid-template-rows: auto minmax(160px, 30vh);
  }
}

/* AI Generate — launcher button + centered modal (2026-07-04). */
#btn-ai-generate {
  display: inline-flex; align-items: center; gap: 6px;
}
#btn-ai-generate .icon { width: 14px; height: 14px; }
.pro-tick {
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.06em;
  color: var(--accent-ink, #0B0B10);
  background: var(--accent, #B5FF3A);
  border-radius: var(--r-pill, 999px);
  padding: 1px 6px;
  margin-left: 2px;
}

.ai-generate-card {
  /* Compact until there is a result to show. The card only earns the extra
     width once Generate has been pressed (owner directive 2026-08-26): an
     empty right half on a 1080px card read as broken alignment. */
  width: min(560px, 92vw);
  max-height: 90vh;
  overflow-y: auto;
  transition: width 260ms var(--ease-out, cubic-bezier(0.2, 0.7, 0.3, 1));
}
.ai-generate-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.ai-generate-inputs {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ai-generate-inputs textarea {
  resize: vertical;
  width: 100%;
  box-sizing: border-box;
  background: var(--panel-sunken);
  border: 1px solid var(--line);
  color: var(--ink);
  font-family: inherit;
  font-size: 13px;
  line-height: 1.5;
  padding: 10px 12px;
  border-radius: var(--r-2);
  outline: none;
  transition: border-color var(--t-fast) var(--ease-out);
}
.ai-generate-inputs textarea:focus { border-color: var(--accent); }
.ai-generate-dropzone {
  border: 1px dashed var(--line-strong, rgba(255,255,255,0.18));
  border-radius: var(--r-3);
  padding: 16px;
  cursor: pointer;
  transition: border-color 130ms, background 130ms;
}
.ai-generate-dropzone:hover,
.ai-generate-dropzone:focus-visible {
  border-color: var(--accent, #B5FF3A);
  background: var(--accent-soft, rgba(181,255,58,0.08));
  outline: none;
}
.ai-generate-dropzone-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
  color: var(--ink-2);
  font-size: 12.5px;
}
.ai-generate-dropzone-empty .icon { width: 20px; height: 20px; color: var(--ink-3); }
.ai-generate-dropzone-hint { font-size: 11px; color: var(--ink-4); }
.ai-generate-dropzone-preview {
  position: relative;
  display: flex;
  justify-content: center;
}
.ai-generate-dropzone-preview img {
  max-width: 100%;
  max-height: 160px;
  border-radius: var(--r-2);
}
.ai-generate-dropzone-preview .ghost {
  position: absolute;
  top: -8px; right: -8px;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel-2, #1C1C25);
  border: 1px solid var(--line-soft);
  border-radius: 50%;
}
.ai-generate-action-row {
  align-items: center;
  justify-content: space-between;
}
.ai-generate-upgrade-note {
  margin: 0;
  font-size: 12px;
  color: var(--ink-2);
}
.ai-generate-error {
  margin: 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--danger, #FF6B6B);
  border: 1px solid rgba(255, 107, 107, 0.35);
  background: rgba(255, 107, 107, 0.08);
  border-radius: var(--r-2);
  padding: 8px 12px;
}
.ai-generate-upgrade-note a { color: var(--accent, #B5FF3A); text-decoration: underline; }

/* The generated-SVG stage. Owner directive 2026-08-25: warm cream ground so
   dark artwork never disappears into the dark modal, and a finished, premium
   frame rather than the utilitarian checkerboard (which .trace-preview-frame
   still uses for auto-trace; these overrides win by coming later). */
.ai-generate-preview-frame {
  min-height: 220px;
  max-height: 40vh;
  padding: 22px;
  background: linear-gradient(180deg, #FBFAF4 0%, #F2EFE6 100%);
  border: 1px solid rgba(20, 20, 26, 0.18);
  border-radius: 16px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 -14px 28px rgba(31, 29, 20, 0.06),
    0 18px 40px rgba(0, 0, 0, 0.5),
    0 0 0 1px rgba(255, 255, 255, 0.05);
}
.ai-generate-preview-frame img {
  display: block;
  max-width: 100%;
  max-height: calc(40vh - 44px);
  object-fit: contain;
  margin: 0 auto;
  filter: drop-shadow(0 6px 18px rgba(31, 29, 20, 0.14));
}

/* Topbar CTA: the one lime button in row one, on purpose. */
.ai-generate-cta,
.topbar .actions button.ai-generate-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--accent, #B5FF3A);
  border: 1px solid rgba(0, 0, 0, 0.25);
  color: #10130A;
  font-weight: 700;
}
.topbar .actions button.ai-generate-cta:hover {
  background: var(--accent, #B5FF3A);
  filter: brightness(1.07);
  color: #10130A;
}
.ai-generate-cta .icon { width: 14px; height: 14px; }
.ai-generate-preview-meta {
  margin-top: 8px;
  font-size: 12px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.ai-generate-preview-actions { margin-top: 10px; }

/* Owner directive 2026-08-25: the whole tool visible in one rounded card,
   no scrolling. Wide screens go two-column (inputs left, result right) and
   the card widens to earn it; the cream stage absorbs the height budget so
   the meta line and the Discard/Regenerate/Add buttons never fall below the
   fold. Narrow screens keep the single column with the 40vh stage cap. */
@media (min-width: 900px) {
  .ai-generate-card.is-wide { width: min(1080px, 94vw); }
  .ai-generate-card.is-wide .ai-generate-body { flex-direction: row; align-items: stretch; gap: 22px; }
  .ai-generate-card.is-wide .ai-generate-inputs { flex: 0 0 38%; }
  .ai-generate-card.is-wide .ai-generate-preview { flex: 1; min-width: 0; display: flex; flex-direction: column; }
  .ai-generate-card.is-wide .ai-generate-preview-frame {
    min-height: 200px;
    max-height: calc(90vh - 300px);
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .ai-generate-card.is-wide .ai-generate-preview-frame img {
    max-height: calc(90vh - 344px);
    width: auto;
    height: auto;
  }
  .ai-generate-card.is-wide .ai-generate-body .ai-generate-status {
    flex: 1;
    justify-content: center;
  }
}

.ai-generate-status {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 24px 0;
}
.ai-generate-status .trace-spinner { margin-bottom: 12px; }
.ai-generate-status-text {
  font-size: 13px;
  color: var(--ink-2);
}

@media (max-width: 600px) {
  .ai-generate-card { width: 94vw; }
}

/* Gradient stop bar */
.gradient-bar {
  position: relative; height: 30px; border-radius: var(--r-1);
  border: 1px solid var(--line); cursor: copy;
}
.gradient-bar .stop {
  position: absolute; top: -2px; bottom: -2px; width: 10px;
  margin-left: -5px; border: 2px solid var(--ink); background: transparent;
  border-radius: 3px; cursor: ew-resize;
  box-shadow: 0 0 0 1px var(--bg-deep);
}
.gradient-bar .stop.active { border-color: var(--accent); }
.gradient-bar .stop .inner { position: absolute; inset: 2px; border-radius: 2px; }

/* Symbols list */
.symbols-list, .symbols-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; margin-top: 4px;
}
.symbol-tile {
  aspect-ratio: 1/1; border: 1px solid var(--line); border-radius: var(--r-2);
  background: var(--panel-sunken); padding: 4px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.symbol-tile svg { width: 100%; height: 100%; }
.symbol-tile.active { outline: 2px solid var(--accent); }

/* Knife / eyedropper / add-anchor cursors */
.cursor-knife { cursor: crosshair; }
.cursor-eyedropper { cursor: copy; }

/* Knife stroke overlay */
.knife-stroke {
  stroke: var(--accent); stroke-width: 1; stroke-dasharray: 4 3;
  fill: none; pointer-events: none;
}

/* Snap a few buttons to a compact size */
#bool-union, #bool-sub, #bool-int, #bool-xor,
#al-l, #al-cx, #al-r, #al-t, #al-cy, #al-b,
#dist-h, #dist-v { flex: 1; }

/* ────────────────────────────────────────────────────────────
   Examples modal
   ──────────────────────────────────────────────────────────── */
.examples-card { min-width: 560px; max-width: 720px; }
.examples-help {
  margin: 0 0 14px;
  color: var(--ink-3);
  font-size: 12.5px;
  letter-spacing: 0.01em;
}
.examples-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
}
.example-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--panel-sunken);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: 12px;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  color: var(--ink-2);
  transition: border-color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out),
              background-color var(--t-fast) var(--ease-out);
}
.example-card:hover {
  border-color: var(--accent);
  background: oklch(from var(--panel-sunken) calc(l + 0.015) c h);
  transform: translateY(-1px);
}
.example-card .example-thumb {
  width: 100%;
  aspect-ratio: 3/2;
  background: oklch(from var(--bg) calc(l + 0.02) c h);
  border-radius: var(--r-2);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.example-card .example-thumb svg { width: 100%; height: 100%; display: block; }
.example-card .example-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.01em;
}
.example-card .example-desc {
  font-size: 11.5px;
  color: var(--ink-3);
  line-height: 1.4;
}

/* ────────────────────────────────────────────────────────────
   Onboarding modal — first-run, 4 panels, skippable
   ──────────────────────────────────────────────────────────── */
.onboarding-card {
  max-width: 480px;
  min-width: 360px;
  width: calc(100vw - 60px);
  padding: 0;
  display: flex;
  flex-direction: column;
}
.onboarding-step {
  padding: 32px 32px 14px;
  min-height: 280px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.onboarding-step .onb-eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}
.onboarding-step h2 {
  margin: 0;
  /* Was 'Lora' serif — a display serif in product UI chrome is off-system.
     The onboarding modal is UI, not content, so it uses the UI sans. */
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 22px;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.onboarding-step p {
  margin: 0;
  color: var(--ink-2);
  font-size: 14px;
  line-height: 1.55;
}
.onboarding-step ul {
  margin: 4px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.onboarding-step li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  color: var(--ink-2);
  font-size: 13px;
  line-height: 1.5;
}
.onboarding-step li .kbd {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  padding: 1px 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--accent);
  background: oklch(from var(--accent) l c h / 0.10);
  border: 1px solid oklch(from var(--accent) l c h / 0.3);
  border-radius: 4px;
  line-height: 1.3;
}
.onboarding-step li b {
  color: var(--ink);
  font-weight: 600;
}
.onboarding-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px 16px;
  border-top: 1px solid var(--line);
  gap: 12px;
}
.onboarding-skip {
  background: transparent;
  border: none;
  color: var(--ink-3);
  font-size: 12px;
  letter-spacing: 0.02em;
  cursor: pointer;
  padding: 6px 10px;
  border-radius: var(--r-2);
  transition: color var(--t-fast) var(--ease-out);
}
.onboarding-skip:hover { color: var(--ink-2); }
.onboarding-dots {
  display: flex;
  gap: 6px;
}
.onboarding-dots .dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: oklch(from var(--ink-3) l c h / 0.4);
  transition: background var(--t-fast) var(--ease-out);
}
.onboarding-dots .dot.active { background: var(--accent); }
.onboarding-nav {
  display: flex;
  gap: 8px;
}
.onboarding-back, .onboarding-next {
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 7px 14px;
  border-radius: var(--r-2);
  cursor: pointer;
  border: 1px solid var(--line);
  transition: border-color var(--t-fast) var(--ease-out),
              background-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out);
}
.onboarding-back {
  background: transparent;
  color: var(--ink-2);
}
.onboarding-back:hover {
  border-color: var(--ink-3);
  color: var(--ink);
}
.onboarding-next {
  background: var(--accent);
  border-color: var(--accent);
  color: #0B0B10;
  font-weight: 600;
}
.onboarding-next:hover {
  background: oklch(from var(--accent) calc(l + 0.04) c h);
  border-color: oklch(from var(--accent) calc(l + 0.04) c h);
}

/* ────────────────────────────────────────────────────────────
   Feedback widget — floating pill bottom-right, expands to a panel
   ──────────────────────────────────────────────────────────── */
.feedback-widget {
  position: fixed;
  /* Bottom-right corner of the viewport (user request 2026-05-29) — was
     offset to right:334px to clear the properties panel; user prefers it
     in the true bottom-right corner, even if that sits over the panel. */
  right: 16px;
  bottom: 16px;
  z-index: 95;  /* below modals (100) so opening a modal still covers it */
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}
.feedback-toggle {
  /* isolation creates a new stacking context so the ::before shine layer can
     sit BEHIND the pill content (z-index:-1) without escaping to behind
     other page content. */
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px 7px 11px;
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink-2);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  box-shadow: 0 4px 12px oklch(0 0 0 / 0.28), 0 1px 0 oklch(0 0 0 / 0.18);
  cursor: pointer;
  overflow: hidden;     /* clip the shine to the pill silhouette */
  transition: color var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
/* Rotating lime "shine" — a conic-gradient that sweeps around the pill's
   border, restored by user request (2026-05-29). The mask cuts a 1px-wide
   ring around the perimeter so only the border lights up, not the whole pill.
   `inset:-1px` extends past the pill so the conic continues smoothly across
   the rounded corners. */
.feedback-toggle::before {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: inherit;
  background: conic-gradient(
    from 0deg,
    transparent 0deg,
    var(--accent) 60deg,
    var(--accent-glow) 90deg,
    transparent 180deg,
    transparent 360deg
  );
  animation: feedback-shine 4s linear infinite;
}
/* Repaint the pill body OVER the conic so only the border-band remains lit. */
.feedback-toggle::after {
  content: "";
  position: absolute;
  inset: 1px;
  z-index: -1;
  border-radius: inherit;
  background: var(--panel);
}
@keyframes feedback-shine {
  to { transform: rotate(360deg); }
}
.feedback-toggle:hover {
  transform: translateY(-1px);
  border-color: var(--accent-soft);
}
.feedback-toggle svg { color: var(--accent); flex-shrink: 0; }

.feedback-panel {
  width: 320px;
  max-width: calc(100vw - 40px);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  box-shadow: 0 12px 28px oklch(0 0 0 / 0.40), 0 2px 0 oklch(0 0 0 / 0.18);
  padding: 14px 14px 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  animation: feedback-pop 200ms var(--ease-out);
}
@keyframes feedback-pop {
  from { transform: translateY(8px) scale(0.97); opacity: 0; }
  to   { transform: translateY(0)    scale(1);    opacity: 1; }
}
.feedback-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.feedback-head h3 {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.feedback-x {
  background: transparent;
  border: none;
  color: var(--ink-3);
  font-size: 18px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
  transition: color var(--t-fast) var(--ease-out);
}
.feedback-x:hover { color: var(--ink); }
.feedback-help {
  margin: 0;
  font-size: 11.5px;
  color: var(--ink-3);
  line-height: 1.45;
  letter-spacing: 0.01em;
}
.feedback-email,
.feedback-panel textarea {
  resize: vertical;
  width: 100%;
  box-sizing: border-box;
  background: var(--panel-sunken);
  border: 1px solid var(--line);
  color: var(--ink);
  font-family: inherit;
  font-size: 13px;
  line-height: 1.5;
  padding: 10px 12px;
  border-radius: var(--r-2);
  outline: none;
  transition: border-color var(--t-fast) var(--ease-out);
}
.feedback-email {
  resize: none;
  min-height: 0;
}
.feedback-panel textarea {
  min-height: 90px;
  max-height: 240px;
}
.feedback-email:focus,
.feedback-panel textarea:focus { border-color: var(--accent); }
.feedback-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}
.feedback-status {
  font-size: 11px;
  color: var(--ink-3);
  letter-spacing: 0.02em;
  min-height: 1em;
}
.feedback-status.ok  { color: var(--accent); }
.feedback-status.err { color: #E04444; }
.feedback-submit {
  background: var(--accent);
  color: #0B0B10;
  border: none;
  border-radius: var(--r-2);
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background-color var(--t-fast) var(--ease-out);
}
.feedback-submit:hover {
  background: oklch(from var(--accent) calc(l + 0.04) c h);
}
.feedback-submit:disabled {
  opacity: 0.55;
  cursor: default;
}

/* Text-on-path sub-panel (revealed inside prop-text when textPathRef is set). */
.prop-sub {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed var(--line-faint);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.prop-sub-label {
  font-size: 10px;
  color: var(--ink-3);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  font-weight: 600;
  margin-bottom: 2px;
}

/* True mesh-gradient editor */
.mesh-hint {
  font-size: 11px;
  color: var(--ink-3);
  line-height: 1.5;
  margin-bottom: 10px;
}
#mesh-grid-seg .seg-label { margin-right: 6px; }
.mesh-grid-wrap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin: 12px 0;
  align-items: stretch;
}
.mesh-grid {
  display: grid;
  gap: 4px;
  background: var(--bg-deep);
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  padding: 6px;
  aspect-ratio: 1 / 1;
}
.mesh-grid .mesh-node {
  position: relative;
  width: 100%; height: 100%;
  border-radius: 4px;
  border: 2px solid rgba(0,0,0,0.35);
  cursor: pointer;
  padding: 0;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.18);
  transition: transform 0.1s ease, border-color 0.1s ease;
}
.mesh-grid .mesh-node:hover { transform: scale(1.08); border-color: var(--accent); }
.mesh-grid .mesh-node:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mesh-grid .mesh-node input[type="color"] {
  position: absolute; inset: 0; opacity: 0; cursor: pointer; border: none;
}
.mesh-preview {
  border: 1px solid var(--line);
  border-radius: var(--r-1);
  background-color: var(--bg-deep);
  background-size: 100% 100%;
  background-position: center;
  background-repeat: no-repeat;
  aspect-ratio: 1 / 1;
  min-height: 120px;
}

/* ============================================================
   Auth (subsection 31) — sign-in button, modal, sign-up bar
   ============================================================ */

/* Topbar user-menu pill (2026-05-30 v2).
   Single-button pill matching profile.html's .account-trigger:
   one continuous border holding avatar + name + chevron. Replaces the
   prior split-btn pattern (which had a hairline divider between the
   name and the chevron). The chevron is intentionally larger here
   than profile.html's 10px because users reported it reading as too
   small in the editor topbar. */
.user-menu { position: relative; display: inline-flex; }
.user-menu .user-pill {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 4px 12px 4px 4px;
  height: auto;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out);
}
.user-menu .user-pill:hover { border-color: var(--line-soft); background: var(--panel-2); }
.user-menu .user-pill[aria-expanded="true"] { border-color: var(--accent); }
.user-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-lo) 100%);
  color: var(--accent-ink);
  font-weight: 700; font-size: 11.5px;
  letter-spacing: 0.02em;
  flex-shrink: 0;
}
.user-menu .user-pill .user-name { font-size: 13px; font-weight: 500; color: var(--ink); line-height: 1; }
.user-menu .user-pill .user-chev { font-size: 14px; line-height: 1; color: var(--ink-3); }
#user-menu-dropdown {
  position: absolute; top: calc(100% + 6px); right: 0;
  background: var(--panel); border: 1px solid var(--line-soft);
  border-radius: var(--r-3); box-shadow: var(--shadow-2);
  padding: 6px; min-width: 200px; z-index: 80;
  display: flex; flex-direction: column; gap: 2px;
}
#user-menu-dropdown button {
  text-align: left; padding: 7px 10px; font-size: 12px;
  background: transparent; border: none; color: var(--ink);
  border-radius: var(--r-2); cursor: pointer;
  transition: background var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out);
}
#user-menu-dropdown button:hover { background: var(--panel-2); color: var(--accent); }
.menu-note {
  max-width: 230px;
  padding: 8px 10px;
  color: var(--ink-3);
  font-size: 11.5px;
  line-height: 1.35;
  border-bottom: 1px solid var(--line);
}

.cloud-save-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--ink-3);
  font-size: 11.5px;
  white-space: nowrap;
}
.actions .cloud-save-status {
  min-height: 34px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-2);
  font-weight: 600;
}
.cloud-save-status::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: currentColor;
}
.cloud-save-status.is-saving { color: var(--accent); }
.cloud-save-status.is-offline { color: #E04444; }
.cloud-save-status.is-online,
.cloud-save-status.is-saved { color: #7edc92; }
.cloud-save-status.is-error { color: #E04444; }
.cloud-save-status.is-local { color: var(--ink-3); }

/* Project size next to the save chip. The number is what the row costs in
   the cloud after gzip, not what the drawing feels like on the canvas. */
.cloud-save-size {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-2);
  color: var(--ink-3);
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
}
.cloud-save-size.is-warn { color: #E8B54A; border-color: #E8B54A55; }
.cloud-save-size.is-over { color: #E04444; border-color: #E0444455; }

/* Per-artboard size accounting (2026-09-20). The chip answers "how big",
   this answers "where". 64% of the document rescued from production was
   artwork sitting on no artboard at all, and nothing on screen said so. */
.cloud-size-wrap { position: relative; display: inline-flex; }
.cloud-save-size { font-family: inherit; }
.cloud-save-size[aria-haspopup="dialog"] { cursor: pointer; }
.cloud-save-size[aria-haspopup="dialog"]:hover { border-color: var(--line-soft); color: var(--ink-2); }
.cloud-save-size[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }
.cloud-save-size:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cloud-size-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 90;
  width: 300px;
  max-height: 60vh;
  overflow-y: auto;
  padding: 12px;
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-2);
}
.cloud-size-panel:focus { outline: none; }
.cloud-size-title {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ink-3);
  margin-bottom: 10px;
}
.cloud-size-row { margin-bottom: 9px; }
.cloud-size-row:last-of-type { margin-bottom: 0; }
.cloud-size-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 11.5px;
  margin-bottom: 4px;
}
.cloud-size-name {
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cloud-size-row.is-loose .cloud-size-name { color: #E8B54A; }
.cloud-size-row.is-parent .cloud-size-name { color: var(--ink-3); }
.cloud-size-bytes { color: var(--ink-2); font-weight: 700; white-space: nowrap; }
.cloud-size-bar {
  display: block;
  height: 4px;
  border-radius: 999px;
  background: var(--panel-3);
  overflow: hidden;
}
.cloud-size-bar i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
}
.cloud-size-row.is-loose .cloud-size-bar i { background: #E8B54A; }
.cloud-size-row.is-parent .cloud-size-bar i { background: var(--ink-4); }
/* Crash buffer (2026-09-20). A bar, never a modal: the drawing stays
   reachable while the user decides. */
.restore-bar {
  position: fixed;
  left: 50%;
  /* Above the hint toast (bottom: 60px) and the zoom bar, so nothing the user needs is covered while they decide. */
  bottom: 126px;
  transform: translateX(-50%);
  z-index: 120;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: min(92vw, 640px);
  padding: 10px 14px;
  background: var(--panel);
  border: 1px solid var(--accent);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-2);
  font-size: 12px;
  color: var(--ink);
}
.restore-bar-text { flex: 1 1 auto; line-height: 1.45; }
.restore-bar-yes,
.restore-bar-no {
  flex: 0 0 auto;
  min-height: 30px;
  padding: 0 12px;
  border-radius: var(--r-2, 8px);
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
}
.restore-bar-yes {
  border: 1px solid var(--accent);
  background: var(--accent);
  color: var(--accent-ink);
}
.restore-bar-yes:hover { background: var(--accent-hi); border-color: var(--accent-hi); }
.restore-bar-no {
  border: 1px solid var(--line-soft);
  background: transparent;
  color: var(--ink-2);
}
.restore-bar-no:hover { color: var(--ink); border-color: var(--ink-3); }
.restore-bar-yes:focus-visible,
.restore-bar-no:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.cloud-size-hint {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  line-height: 1.5;
  color: var(--ink-3);
}

/* Incremental cloud saves (2026-09-20). The error chip never says "failed"
   while a confirm probe is still possible, so it reads "Not saved: N
   artboards pending" and offers the one action that helps. */
.cloud-save-status.is-error { border-color: #E0444455; }
.cloud-save-retry {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 10px;
  border: 1px solid #E0444455;
  border-radius: 10px;
  background: var(--panel-2);
  color: #E04444;
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
.cloud-save-retry:hover { border-color: #E04444; color: #ff6b6b; }

/* Auth modal — reuses .modal / .modal-card base */
.auth-card { max-width: 420px; }
.auth-lede {
  color: var(--ink-2);
  font-size: 13px;
  line-height: 1.55;
  margin: 4px 0 18px;
}
.auth-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 10px 16px;
  background: #fff;
  color: #1a1a1a;
  border: 1px solid #dadce0;
  border-radius: 6px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: box-shadow 0.15s ease, background-color 0.15s ease;
}
.auth-google:hover { background: #f8f9fa; box-shadow: 0 1px 3px rgba(0,0,0,0.18); }
.auth-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--ink-3);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.10em;
  margin: 18px 0;
}
.auth-divider::before, .auth-divider::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--line);
}
.auth-form { display: flex; flex-direction: column; gap: 12px; }
.auth-label { display: flex; flex-direction: column; gap: 6px; font-size: 11.5px; color: var(--ink-2); }
.auth-label > span:first-child {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
  color: var(--ink-3);
}
.auth-label input[type="email"] {
  padding: 9px 12px;
  background: var(--bg-deep);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--ink);
  font-family: inherit;
  font-size: 14px;
}
.auth-label input[type="email"]:focus {
  outline: none;
  border-color: var(--accent);
}
.auth-optin {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 12px;
  color: var(--ink-2);
  cursor: pointer;
  line-height: 1.45;
}
.auth-optin input { margin-top: 2px; flex-shrink: 0; }
.auth-turnstile:not(:empty) { margin: 4px 0; }
.auth-submit {
  padding: 10px 16px;
  background: var(--accent);
  color: #0B0B10;
  border: none;
  border-radius: 6px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: filter 0.15s ease;
}
.auth-submit:hover { filter: brightness(1.07); }
.auth-submit:disabled { opacity: 0.55; cursor: not-allowed; }
.auth-status {
  font-size: 12.5px;
  color: var(--ink-2);
  margin: 12px 0 0;
  min-height: 1.2em;
  line-height: 1.4;
}
.auth-status.is-error { color: #E04444; }
.auth-status.is-success { color: #4CDD8B; }
.auth-fine-print {
  font-size: 11px;
  color: var(--ink-3);
  margin: 14px 0 0;
  line-height: 1.5;
}
.auth-fine-print a { color: var(--ink-2); text-decoration: underline; text-underline-offset: 2px; }
.auth-fine-print a:hover { color: var(--accent); }

/* Sign-up suggestion bar — floating bottom-left card */
.signup-bar {
  position: fixed;
  bottom: 16px;
  /* Clear the 68px toolbar rail so the card floats over the canvas, not over
     the bottom tools (was left:16px, which covered Hand/Zoom). (2026-05-29) */
  left: 80px;
  width: 280px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 14px 14px 12px;
  box-shadow: 0 6px 24px rgba(0,0,0,0.32);
  z-index: 60;
  font-family: inherit;
  animation: signupBarIn 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
@keyframes signupBarIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0);  }
}
.signup-bar-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 4px;
}
.signup-bar-head strong {
  font-size: 13px;
  color: var(--ink);
  line-height: 1.3;
}
.signup-bar-x {
  background: none;
  border: none;
  color: var(--ink-3);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  width: 20px; height: 20px;
  flex-shrink: 0;
}
.signup-bar-x:hover { color: var(--ink); }
.signup-bar-msg {
  font-size: 12px;
  color: var(--ink-2);
  line-height: 1.5;
  margin: 0 0 12px;
}
.signup-bar-actions {
  display: flex;
  gap: 6px;
  align-items: center;
}
.signup-bar-cta {
  flex: 1;
  padding: 7px 12px;
  background: var(--accent);
  color: #0B0B10;
  border: none;
  border-radius: 5px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.signup-bar-cta:hover { filter: brightness(1.07); }
.signup-bar-skip {
  padding: 7px 12px;
  background: transparent;
  color: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: 5px;
  font-size: 12px;
  cursor: pointer;
}
.signup-bar-skip:hover { color: var(--ink); border-color: var(--ink-3); }

/* ============================================================
   My Projects modal (subsection 32)
   ============================================================ */
.projects-card {
  max-width: 460px;
  max-height: min(760px, calc(100vh - 32px));
  display: flex;
  flex-direction: column;
}
.projects-lede {
  color: var(--ink-2);
  font-size: 12.5px;
  line-height: 1.5;
  margin: 4px 0 16px;
}
.projects-current {
  margin: 0 0 12px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: rgba(255,255,255,0.025);
}
.projects-current label {
  display: block;
  margin: 0 0 7px;
  color: var(--ink-3);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.project-name-edit {
  display: flex;
  gap: 8px;
}
.project-name-edit input {
  min-width: 0;
  flex: 1;
  padding: 9px 10px;
  color: var(--ink);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  font: inherit;
  font-size: 13px;
}
.project-name-edit input:focus {
  outline: none;
  border-color: var(--accent);
}
.project-name-edit button {
  padding: 8px 10px;
  color: #0B0B10;
  background: var(--accent);
  border: none;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}
#project-name-help,
.projects-limit,
.limit-note {
  margin: 7px 0 0;
  color: var(--ink-3);
  font-size: 11.5px;
  line-height: 1.4;
}
.projects-limit {
  margin: 0 0 10px;
}
.projects-limit.is-full {
  color: #ffbd66;
}
.projects-list {
  list-style: none;
  margin: 0;
  padding: 0;
  height: min(300px, 34vh);
  min-height: 188px;
  overflow-y: auto;
  overflow-x: visible;
  border: 1px solid var(--line);
  border-radius: 6px;
}
.projects-empty {
  padding: 20px;
  text-align: center;
  font-size: 12.5px;
  color: var(--ink-3);
}
.project-row {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--line);
}
.project-row:last-child { border-bottom: none; }
.project-row.is-active { background: var(--bg-deep); }
.project-load {
  flex: 1;
  background: transparent;
  border: none;
  color: var(--ink);
  text-align: left;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  cursor: pointer;
  font-family: inherit;
}
.project-load:hover { background: rgba(255,255,255,0.04); }
.project-name {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink);
}
.project-meta {
  font-size: 11.5px;
  color: var(--ink-3);
}
.project-actions {
  position: relative;
  display: flex;
  align-items: stretch;
  flex-shrink: 0;
  border-left: 1px solid var(--line);
}
.project-menu-toggle {
  width: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--ink-3);
  font-size: 18px;
  letter-spacing: 0;
  cursor: pointer;
}
.project-menu-toggle:hover,
.project-menu-toggle[aria-expanded="true"] {
  color: var(--ink);
  background: rgba(255,255,255,0.045);
}
.project-menu {
  position: absolute;
  right: 8px;
  top: calc(100% - 6px);
  z-index: 5;
  min-width: 132px;
  padding: 5px;
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  box-shadow: var(--shadow-2);
}
.project-menu button {
  width: 100%;
  padding: 8px 9px;
  color: var(--ink-2);
  background: transparent;
  border: none;
  border-radius: 5px;
  text-align: left;
  font-size: 12px;
  cursor: pointer;
}
.project-menu button:hover {
  color: var(--ink);
  background: var(--panel-2);
}
.project-action-delete:hover {
  color: #ff7777;
  background: rgba(255,80,80,0.08);
}
.projects-footer {
  margin-top: 14px;
  display: flex;
  justify-content: flex-end;
}
.projects-new {
  padding: 8px 14px;
  background: var(--accent);
  color: #0B0B10;
  border: none;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.projects-new:hover { filter: brightness(1.07); }
.projects-new:disabled {
  opacity: 0.48;
  cursor: not-allowed;
  filter: none;
}

.workspace-is-busy .app {
  pointer-events: none;
  user-select: none;
}
.workspace-busy {
  position: fixed;
  inset: 0;
  z-index: 118;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(10, 10, 14, 0.9);
  backdrop-filter: blur(2px);
}
.workspace-busy[hidden] {
  display: none;
}
.workspace-busy-card {
  width: min(430px, 100%);
  padding: 24px 26px;
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  background: var(--panel);
  box-shadow: 0 22px 70px rgba(0,0,0,0.42);
  color: var(--ink);
  text-align: center;
}
.workspace-busy-spinner {
  width: 28px;
  height: 28px;
  margin: 0 auto 14px;
  border: 3px solid rgba(181, 255, 58, 0.18);
  border-top-color: var(--accent);
  border-radius: 999px;
  animation: traceSpin 780ms linear infinite;
}
.workspace-busy-title {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.01em;
}
.workspace-busy-copy {
  margin-top: 8px;
  color: var(--ink-3);
  font-size: 12.5px;
  line-height: 1.45;
}
.workspace-busy-steps {
  display: grid;
  gap: 8px;
  margin: 16px auto 0;
  max-width: 340px;
  text-align: left;
}
.workspace-busy-steps[hidden] {
  display: none;
}
.workspace-busy-step {
  position: relative;
  display: grid;
  grid-template-columns: 12px 1fr;
  gap: 9px;
  color: var(--ink-3);
  font-size: 11.5px;
  line-height: 1.35;
}
.workspace-busy-step::before {
  content: "";
  width: 7px;
  height: 7px;
  margin-top: 4px;
  border-radius: 999px;
  border: 1px solid rgba(181, 255, 58, 0.35);
  background: rgba(181, 255, 58, 0.08);
  box-shadow: 0 0 0 0 rgba(181, 255, 58, 0);
}
.workspace-busy-step.is-active {
  color: var(--ink);
}
.workspace-busy-step.is-active::before {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 0 5px rgba(181, 255, 58, 0.12);
}
.workspace-busy-step.is-done {
  color: var(--ink-2);
}
.workspace-busy-step.is-done::before {
  background: rgba(181, 255, 58, 0.55);
  border-color: rgba(181, 255, 58, 0.55);
}
.workspace-busy-step-name {
  display: block;
  font-weight: 700;
}
.workspace-busy-step-copy {
  display: block;
  margin-top: 1px;
  color: var(--ink-3);
}

/* ────────────────────────────────────────────────────────────
   "Work not saved" warning strip (Phase 1 funnel hardening).
   Anonymous users only; persists across reloads, dismissible per
   tab-session.
   ──────────────────────────────────────────────────────────── */
.save-warning {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 109;
  /* Neutral dark surface with a faint lime hint at the bottom edge —
     no more heavy green tint (2026-05-26 user feedback "lighter, less green"). */
  background: var(--panel);
  border-bottom: 1px solid rgba(181, 255, 58, 0.18);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  color: var(--ink);
  font-size: 12.5px;
  line-height: 1.4;
  letter-spacing: 0.01em;
  padding: 10px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.save-warning strong { color: var(--ink); font-weight: 600; }
.save-warning-msg { flex: 1; }
.save-warning-cta {
  background: transparent;
  border: none;
  padding: 0;
  margin-left: 6px;
  color: var(--accent);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.save-warning-cta:hover { filter: brightness(1.15); }
.save-warning-xbtn {
  background: transparent;
  border: none;
  color: var(--ink-3);
  font-size: 20px;
  cursor: pointer;
  padding: 0 6px;
  line-height: 1;
  margin-left: auto;
  flex-shrink: 0;
  transition: color var(--t-fast) var(--ease-out);
}
.save-warning-xbtn:hover { color: var(--ink); }
/* Push .app down by the warning's height when visible. Stack with the
   top of the viewport. */
body:has(.save-warning:not([hidden])) .app { padding-top: 44px; }
body:has(.save-warning:not([hidden])) .app .topbar { animation: none; }

/* ===== Auto-trace busy overlay (added 2026-05-26) =====
   Sits on top of the canvas, blocks pointer events so the user can't draw
   mid-trace, but leaves topbar + properties panel reachable (they're outside
   .canvas-area). Cancel aborts the remote request. */
.trace-overlay {
  position: absolute;
  inset: 0;
  background: rgba(15, 14, 12, 0.72);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
  animation: fadeInOverlay 160ms var(--ease-out) both;
}
.trace-overlay.is-targeted {
  background: transparent;
  backdrop-filter: none;
  align-items: flex-start;
  padding-top: 16px;
}
@keyframes fadeInOverlay { from { opacity: 0; } to { opacity: 1; } }
.trace-overlay-card {
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  padding: 28px 32px;
  max-width: 380px;
  text-align: center;
  box-shadow: 0 16px 48px rgba(0,0,0,0.4);
  color: var(--ink, #eee);
}
.trace-overlay.is-targeted .trace-overlay-card {
  max-width: 360px;
  padding: 16px 18px;
  box-shadow: 0 10px 34px rgba(0,0,0,0.28);
}
.trace-spinner {
  width: 36px;
  height: 36px;
  border: 3px solid rgba(181, 255, 58, 0.18);
  border-top-color: var(--accent, #B5FF3A);
  border-radius: 50%;
  margin: 0 auto 18px;
  animation: traceSpin 720ms linear infinite;
}
.trace-overlay.is-targeted .trace-spinner {
  width: 24px;
  height: 24px;
  margin-bottom: 10px;
}
@keyframes traceSpin { to { transform: rotate(360deg); } }
.trace-overlay-title {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.01em;
  margin-bottom: 6px;
}
.trace-overlay-meta {
  font-size: 12px;
  color: var(--ink-3, #8a8478);
  font-variant-numeric: tabular-nums;
  margin-bottom: 14px;
}
.trace-overlay-hint {
  font-size: 11.5px;
  color: var(--ink-3, #8a8478);
  line-height: 1.5;
  margin-bottom: 14px;
  opacity: 0.85;
}
.trace-overlay-steps {
  display: grid;
  gap: 7px;
  margin: 0 0 16px;
  text-align: left;
}
.trace-overlay-steps[hidden] {
  display: none;
}
.trace-overlay-step {
  position: relative;
  display: grid;
  grid-template-columns: 12px 1fr;
  gap: 9px;
  color: var(--ink-3, #8a8478);
  font-size: 11.5px;
  line-height: 1.35;
}
.trace-overlay-step::before {
  content: "";
  width: 7px;
  height: 7px;
  margin-top: 4px;
  border-radius: 999px;
  border: 1px solid rgba(181, 255, 58, 0.35);
  background: rgba(181, 255, 58, 0.08);
  box-shadow: 0 0 0 0 rgba(181, 255, 58, 0);
}
.trace-overlay-step.is-active {
  color: var(--ink, #eee);
}
.trace-overlay-step.is-active::before {
  background: var(--accent, #B5FF3A);
  border-color: var(--accent, #B5FF3A);
  box-shadow: 0 0 0 5px rgba(181, 255, 58, 0.12);
}
.trace-overlay-step.is-done {
  color: var(--ink-2, #c7c2b8);
}
.trace-overlay-step.is-done::before {
  background: rgba(181, 255, 58, 0.55);
  border-color: rgba(181, 255, 58, 0.55);
}
.trace-step-name {
  display: block;
  font-weight: 700;
}
.trace-step-copy {
  display: block;
  margin-top: 1px;
  color: var(--ink-3, #8a8478);
}
.trace-overlay-cancel {
  background: transparent;
  color: var(--ink, #eee);
  border: 1px solid var(--line-soft);
  border-radius: 6px;
  padding: 7px 18px;
  font-size: 12.5px;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out);
}
.trace-overlay-cancel:hover {
  background: rgba(181, 255, 58, 0.08);
  border-color: var(--accent, #B5FF3A);
}
#overlay .trace-target-fx {
  pointer-events: none;
}
#overlay .trace-target-veil {
  fill: var(--accent-soft);
  opacity: 0.38;
}
#overlay .trace-target-frame {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 8 6;
  animation: traceTargetPulse 900ms ease-in-out infinite alternate;
}
#overlay .trace-target-scan {
  stroke: var(--accent);
  stroke-width: 2.5;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  opacity: 0.78;
  filter: drop-shadow(0 0 8px var(--accent-glow));
}
@keyframes traceTargetPulse {
  from { opacity: 0.55; }
  to { opacity: 1; }
}

/* Auto-trace large-group summary row in the Layers panel (added 2026-05-26).
   When an auto-trace produces 20K+ shapes, renderLayers collapses them into
   ONE summary row instead of 20K <li>s (which would freeze the UI). The
   summary row shows count, swatch (gradient to distinguish from a normal
   shape swatch), and a trash button to delete the whole group. */
.layers li.layer-summary {
  font-style: italic;
  background: rgba(181, 255, 58, 0.04);
}
.layers li.layer-summary .name {
  color: var(--ink-2, #b9b1a3);
}
.layers li.layer-summary .swatch {
  border: 1px dashed rgba(181, 255, 58, 0.4);
}

/* ────────────────────────────────────────────────────────────
   Cursor follower glow (2026-05-26 — user request).
   A soft lime light that follows the pointer, mimicking the ambient
   green glow in the reference dashboard image. Uses mix-blend-mode
   so it brightens whatever is behind it instead of overlaying.
   Hidden under prefers-reduced-motion. Positioned by JS via inline
   transform — see app.js init block.
   ──────────────────────────────────────────────────────────── */
#cursor-glow {
  position: fixed;
  top: 0; left: 0;
  /* Tightened to ~20% of original size per user request 2026-05-26 —
     glow now sits close to the cursor instead of bathing the whole area. */
  width: 120px;
  height: 120px;
  margin-left: -60px;
  margin-top: -60px;
  border-radius: 50%;
  pointer-events: none; /* never blocks interaction */
  /* z-index ladder (2026-05-29): topbar 50 · dropdowns 80 · code-panel 90 ·
     feedback 95 · cursor-glow 96 · ctx-menu 99 · modal 100 · save-warning 109 ·
     The glow sits *below* modals/menus so it never washes
     over dialog content (was 9999, painting over everything). */
  z-index: 96;
  background: radial-gradient(
    circle,
    rgba(181, 255, 58, 0.42) 0%,
    rgba(181, 255, 58, 0.21) 28%,
    rgba(181, 255, 58, 0)    62%
  );
  filter: blur(14px);
  mix-blend-mode: screen;
  will-change: transform;
  opacity: 0;
  transition: opacity 400ms var(--ease-out);
}
#cursor-glow.is-active { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  #cursor-glow { display: none; }
}

/* ────────────────────────────────────────────────────────────
   Universal hover lime — text + icons turn lime on hover for any
   interactive element (2026-05-26 user request). Specific component
   rules with stronger selectors still win where they exist (e.g. the
   Export button which has its own bg-shift hover).
   ──────────────────────────────────────────────────────────── */
button:hover,
button:hover svg.icon,
button:hover .icon,
a:hover,
.tool:hover,
.field:hover > span,
[role="button"]:hover {
  color: var(--accent-lime);
}
/* Icons inherit via currentColor on stroke — make explicit for sprite uses */
button:hover svg.icon use,
a:hover svg.icon use {
  color: var(--accent-lime);
}
/* Don't lime the text on a button that's ALREADY accent-bg
   (e.g. the Export primary button). Its text needs to stay dark for contrast.
   NOTE: .page-tab.active:hover is intentionally NOT in this list — the active
   page tab fills with --panel (NOT accent), so its hover text should turn
   lime like the rest of the UI, matching the toolbar icon hover behaviour. */
.actions button#btn-export:hover,
.feedback-submit:hover,
.signup-bar-cta:hover,
.projects-new:hover,
.auth-submit:hover,
.onboarding-next:hover {
  color: var(--accent-ink);
}

/* ────────────────────────────────────────────────────────────
   Invisible scrollbars (2026-05-26 user request).
   Hides the scrollbar UI everywhere while keeping scroll functional.
   Covers Chromium (::-webkit-scrollbar), Firefox (scrollbar-width),
   legacy Edge/IE (-ms-overflow-style). Wins over the per-panel
   scrollbar styling above thanks to specificity + display:none.
   ──────────────────────────────────────────────────────────── */
* {
  scrollbar-width: none;       /* Firefox */
  -ms-overflow-style: none;    /* legacy Edge / IE */
}
*::-webkit-scrollbar {          /* Chrome / Safari / modern Edge */
  width: 0 !important;
  height: 0 !important;
  display: none !important;
  background: transparent !important;
}

/* ────────────────────────────────────────────────────────────
   Responsive layout (2026-05-29 — user request: "make it responsive").
   The base layout is a fixed 3-column grid (68 / 1fr / 322) that
   overflows under ~960px and breaks badly below ~720px (the canvas
   gets squeezed to nothing and the side panels overflow off-screen).
   These queries progressively reclaim space, then stack to a single
   column on phones. CSS-only, no JS, no build. This stops the layout
   breaking when a window is resized or on tablets and phones.
   ──────────────────────────────────────────────────────────── */

/* Small laptops — trim the side panels so the canvas keeps room. */
@media (max-width: 1100px) {
  .app { grid-template-columns: 64px 1fr 292px; }
  /* feedback widget stays at right:16px — user prefers bottom-right corner */
}

/* Tablets — narrower still; tighten the topbar rows. */
@media (max-width: 860px) {
  .app { grid-template-columns: 58px 1fr 248px; }
  .topbar-row { padding: 6px 10px; gap: var(--s-2); }
}

/* Phones — stack to one column. Toolbar becomes a horizontal scroll
   strip, canvas takes the middle, properties is a capped scrollable
   card below. Everything stays inside 100vh because body can't scroll
   (box-sizing:border-box keeps the banner padding-top from overflowing). */
@media (max-width: 720px) {
  .app {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto minmax(150px, 1fr) minmax(0, 36vh) 26px;
    grid-template-areas:
      "topbar"
      "toolbar"
      "canvas"
      "properties"
      "statusbar";
  }

  /* Toolbar: vertical card → horizontal scroll strip of tools. */
  .toolbar {
    flex-direction: row;
    align-items: center;
    gap: 4px;
    margin: 8px 8px 0;
    padding: 6px 8px;
    overflow-x: auto;
    overflow-y: hidden;
    border-radius: 16px;
  }
  .toolbar .tool { flex: 0 0 auto; }
  /* Separators flip from horizontal lines to vertical dividers in a row. */
  .tool-sep { width: 1px; height: 22px; margin: 0 4px; }

  /* Properties: floating card below the canvas, scrolls internally. */
  .properties {
    margin: 8px 8px 0;
    border-radius: 16px;
  }

  /* Side panels are stacked (not on the left/right edges) at this width, so
     the floating widgets return to the normal viewport corners. */
  .feedback-widget { right: 16px; }
  .signup-bar { left: 16px; }
  .hint { left: 16px; }
}

/* Export artboard picker modal (2026-05-31).
   Multi-select: shown when >1 artboards. Pick any subset; export them. */
.scope-help {
  color: var(--ink-2);
  font-size: 13px;
  margin: 0 0 12px 0;
}
.scope-actions-row {
  display: flex;
  gap: 14px;
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line);
}
.link-btn {
  background: transparent;
  border: 0;
  padding: 4px 0;
  font-size: 12px;
  color: var(--ink-3);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out);
  letter-spacing: -0.005em;
}
.link-btn:hover { color: var(--accent); }
.scope-list {
  max-height: 280px;
  overflow-y: auto;
  margin: 0 -4px 14px -4px;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.scope-item {
  display: grid;
  grid-template-columns: 18px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--r-2);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out);
}
.scope-item:hover { background: var(--panel-2); }
.scope-item input[type="checkbox"] {
  accent-color: var(--accent);
  width: 16px;
  height: 16px;
  cursor: pointer;
  margin: 0;
}
.scope-item-name {
  font-size: 13.5px;
  color: var(--ink);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.scope-item-dims {
  font-size: 11.5px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}
.scope-item.is-active .scope-item-name::after {
  content: "active";
  margin-left: 8px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  opacity: 0.85;
}
.scope-footer { justify-content: flex-end; }
.scope-footer #scope-go:not(:disabled) {
  background: var(--accent);
  color: var(--accent-ink);
}
.scope-footer #scope-go:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* App-native confirm/prompt dialog (replaces window.confirm / prompt) */
.app-dialog-card { max-width: 440px; z-index: 1; }
#app-dialog { z-index: 1200; } /* above projects/export modals that can spawn it */
.app-dialog-message {
  color: var(--ink-2);
  font-size: 13px;
  line-height: 1.55;
}
.app-dialog-input {
  width: 100%;
  min-height: 36px;
  padding: 8px 11px;
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  background: var(--panel-2);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  outline: none;
}
.app-dialog-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft, rgba(181, 255, 58, 0.14));
}
.app-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 2px;
}
.app-dialog-btn {
  min-height: 34px;
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}
.app-dialog-btn:hover { border-color: var(--accent); color: var(--accent); }
.app-dialog-btn.primary {
  background: var(--accent);
  border-color: transparent;
  color: var(--accent-ink, #0b0b10);
}
.app-dialog-btn.primary:hover {
  background: var(--accent-hi, var(--accent));
  color: var(--accent-ink, #0b0b10);
}
.app-dialog-btn.primary.danger {
  background: #e04444;
  color: #fff;
}
.app-dialog-btn.primary.danger:hover { background: #f25555; color: #fff; }

/* Invert-fill toggle (2026-07-17): square-with-punched-hole icon. Paints the
   region OUTSIDE the shape instead of the inside — see the "companion path"
   feature in the PRO EXTENSIONS block of app.js. */
.fill-invert-btn {
  width: 32px; height: 32px;
  border-radius: var(--r-2);
  background: var(--panel-sunken);
  border: 1px solid var(--line);
  color: var(--ink-3);
  cursor: pointer;
  position: relative;
  display: flex; align-items: center; justify-content: center;
  transition:
    background-color var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out),
    opacity var(--t-fast) var(--ease-out);
}
.fill-invert-btn .fill-invert-hole { fill: var(--panel-sunken); transition: fill var(--t-fast) var(--ease-out); }
.fill-invert-btn:hover:not(:disabled) { border-color: var(--accent-lime, var(--accent)); color: var(--accent-lime, var(--accent)); }
.fill-invert-btn.active {
  background: var(--accent-lime-soft, var(--accent-soft));
  color: var(--accent-lime, var(--accent));
  border-color: var(--accent-lime, var(--accent));
}
.fill-invert-btn.active .fill-invert-hole { fill: var(--accent-lime-soft, var(--accent-soft)); }
.fill-invert-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* Per-end stroke taper controls (2026-07-20). Open strokes can taper at the
   start, end, or both; Length controls how much of the path is used. */
.stroke-taper-seg .seg-label {
  padding-right: 6px;
}
.stroke-taper-seg button {
  min-width: 0;
  padding-inline: 3px;
  font-size: 10px;
}
.stroke-taper-seg button.active:not([data-value="off"]) {
  border-color: var(--accent-lime, var(--accent));
  color: var(--accent-lime, var(--accent));
}
.stroke-taper-seg.is-disabled,
.stroke-taper-amount.is-disabled {
  opacity: 0.35;
}
.stroke-taper-seg button:disabled,
.stroke-taper-amount input:disabled {
  cursor: not-allowed;
}
.stroke-taper-amount {
  margin-top: var(--s-2);
}

/* The "Connect to AI" button and its pairing-code panel were removed on
   2026-09-26: the MCP no longer pairs with a tab (app.js sections 36, 38). */

/* ---------- Loud limit denial (2026-08-25): shared shake + red note used by
   the export scope modal, the export split-button popover, and AI Generate.
   See app.js PRO EXTENSIONS subsection "Loud limit denial". ---------- */
@keyframes limit-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}
.limit-shake { animation: limit-shake 400ms ease-in-out; }
.limit-denied-note {
  margin-top: 6px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--danger, #ff6b6b);
}
.limit-denied-note a { color: inherit; text-decoration: underline; }
.limit-popover {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 90;
  width: max-content;
  max-width: 260px;
  margin-top: 0;
  background: var(--panel);
  border: 1px solid rgba(255, 77, 77, 0.35);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-2);
  padding: 8px 10px;
}

/* ---------- Export button when the plan's exports are spent (2026-08-26).
   The lime CTA turns red and breathes until an upgrade (or a new billing
   period) frees exports up again, so nobody spends an hour on artwork they
   cannot download. Set from app.js by updateExportQuotaAlert().
   The breath fades a layer's opacity instead of animating box-shadow, which
   repainted the whole page every frame (see the Upgrade button below). ---------- */
.actions .split-btn.is-quota-spent > button#btn-export {
  position: relative;
  isolation: isolate;
  background: var(--danger);
  color: #FFF3F3;
  border-color: transparent;
  box-shadow: 0 0 8px rgba(255, 77, 77, 0.30);
}
.actions .split-btn.is-quota-spent > button#btn-export::before {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: inherit;
  box-shadow: 0 0 0 4px var(--danger-soft), 0 0 20px rgba(255, 77, 77, 0.70);
  opacity: 0;
  animation: export-quota-beam 2.6s ease-in-out infinite;
  will-change: opacity;
  pointer-events: none;
}
.actions .split-btn.is-quota-spent > button#btn-export:hover {
  background: var(--danger);
  color: #FFF3F3;
  border-color: transparent;
  box-shadow: 0 0 0 4px var(--danger-soft);
}
.actions .split-btn.is-quota-spent > button.caret {
  border-color: var(--danger-soft);
  color: var(--danger);
}
@keyframes export-quota-beam {
  0%, 100% { opacity: 0; }
  50%      { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .actions .split-btn.is-quota-spent > button#btn-export::before { animation: none; }
}

/* ---------- Topbar Upgrade button (2026-08-31) ----------
   Shown only to signed-in free users. It mirrors the export-quota beam above,
   but in the brand lime with a silver sweep across the face, so it reads as an
   invitation rather than the red "you are blocked" state. The sweep and the
   beam both stop under prefers-reduced-motion.

   Compositor only (2026-09-26): both loops animate transform or opacity and
   nothing else. They used to animate box-shadow and left, which made the
   browser repaint and lay out the whole page every frame; with 500 shapes on
   the canvas that alone kept an idle editor about a quarter busy. The beam's
   peak glow now lives on ::before and fades in and out; the sweep moves with
   transform inside .btn-upgrade-sheen, which clips it to the button so the
   button itself no longer clips the glow. */
.actions .btn-upgrade {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  padding: 0 12px;
  height: 28px;
  border-radius: 7px;
  border: 1px solid transparent;
  background: linear-gradient(180deg, var(--accent-hi), var(--accent));
  color: var(--accent-ink);
  font: inherit;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  white-space: nowrap;
  gap: 5px;
  box-shadow: 0 0 8px var(--accent-glow);
}
/* The beam's peak, faded in and out. inset -1px matches the border box, which
   is where the button's own shadow starts. */
.actions .btn-upgrade::before {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: inherit;
  box-shadow: 0 0 0 4px var(--accent-soft), 0 0 20px var(--accent-glow);
  opacity: 0;
  animation: upgrade-beam 2.8s ease-in-out infinite;
  will-change: opacity;
  pointer-events: none;
}
/* The silver sweep is absolutely positioned, so it passes over the bolt and
   the label together rather than around them. */
.actions .btn-upgrade .icon {
  width: 14px;
  height: 14px;
  flex: none;
}
.actions .btn-upgrade:hover {
  background: linear-gradient(180deg, #DAFF8F, var(--accent-hi));
  color: var(--accent-ink);
  box-shadow: 0 0 0 4px var(--accent-soft), 0 0 22px var(--accent-glow);
}
.actions .btn-upgrade-sheen {
  position: absolute;
  inset: 0;
  border-radius: 6px;
  overflow: hidden;
  pointer-events: none;
}
/* The silver pass. A skewed highlight swept across the button on the same
   cadence as the beam, which is what gives it the metallic read. It travels
   from left -60% to 130% of the button: 190% of the button is 475% of its
   own 40% width. */
.actions .btn-upgrade-sheen::after {
  content: "";
  position: absolute;
  top: -50%;
  left: -60%;
  width: 40%;
  height: 200%;
  transform: translateX(0) skewX(-20deg);
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.75) 50%,
    rgba(255, 255, 255, 0) 100%
  );
  animation: upgrade-sheen 2.8s ease-in-out infinite;
  will-change: transform;
}
@keyframes upgrade-beam {
  0%, 100% { opacity: 0; }
  50%      { opacity: 1; }
}
@keyframes upgrade-sheen {
  0%        { transform: translateX(0) skewX(-20deg); }
  55%, 100% { transform: translateX(475%) skewX(-20deg); }
}
@media (prefers-reduced-motion: reduce) {
  .actions .btn-upgrade::before { animation: none; }
  .actions .btn-upgrade-sheen::after { animation: none; opacity: 0; }
}

/* ---------- Usage panel (2026-08-25): topbar "Usage" button + dropdown.
   Mirrors .split-btn .menu positioning but is its own widget since it holds
   meters, not a button list. ---------- */
.usage-widget { position: relative; display: inline-flex; }
.usage-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 90;
  width: 260px;
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-2);
  padding: 12px;
}
.usage-panel-plan {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.usage-panel-plan-label {
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--ink-3);
  font-weight: 700;
}
.usage-panel-plan-chip {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent-ink, #0b0b10);
  background: var(--accent);
  padding: 2px 8px;
  border-radius: var(--r-pill);
}
.usage-meter { margin-bottom: 10px; }
.usage-meter:last-of-type { margin-bottom: 0; }
.usage-meter-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-size: 11.5px;
  margin-bottom: 4px;
}
.usage-meter-label { color: var(--ink-2); }
.usage-meter-value { color: var(--ink); font-weight: 600; }
.usage-meter-bar {
  height: 4px;
  border-radius: 999px;
  background: var(--panel-2, #1c1c25);
  overflow: hidden;
}
.usage-meter-fill { height: 100%; background: var(--accent); border-radius: inherit; }
.usage-meter.is-full .usage-meter-fill { background: var(--danger, #ff6b6b); }
.usage-meter-note { font-size: 10.5px; color: var(--ink-3); margin-top: 3px; }
.usage-panel-upgrade {
  display: block;
  text-align: center;
  margin-top: 10px;
  padding: 7px 10px;
  border-radius: var(--r-2);
  background: var(--accent);
  color: var(--accent-ink, #0b0b10);
  font-size: 12px;
  font-weight: 700;
  text-decoration: none;
}
.usage-panel-empty, .usage-panel-loading {
  font-size: 12px;
  color: var(--ink-2);
  line-height: 1.5;
}
.usage-panel-empty a { color: var(--accent); text-decoration: underline; }

/* MCP usage in the Usage panel (2026-09-27): compact allowance, trial,
   top-up balance, top tools and projects, and a More link to /usage. */
.usage-panel { max-height: calc(100vh - 90px); overflow-y: auto; }
.usage-mcp {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line-soft);
}
.usage-mcp-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.usage-mcp-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 11.5px;
  margin-bottom: 4px;
}
.usage-mcp-label { color: var(--ink-2); min-width: 0; }
.usage-mcp-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.usage-mcp-value { color: var(--ink); font-weight: 600; white-space: nowrap; }
.usage-mcp-list { margin-top: 8px; }
.usage-mcp-list-title { font-size: 10.5px; color: var(--ink-3); margin-bottom: 3px; }
.usage-mcp .usage-meter { margin-bottom: 8px; }
.usage-mcp-try-title { font-size: 12.5px; font-weight: 700; color: var(--ink); margin-bottom: 3px; }
.usage-mcp-try-text { font-size: 11.5px; color: var(--ink-2); line-height: 1.45; margin-bottom: 6px; }
.usage-mcp-link { font-size: 12px; color: var(--accent); text-decoration: underline; }
.usage-mcp-more {
  display: block;
  text-align: center;
  margin-top: 10px;
  padding: 6px 10px;
  border-radius: var(--r-2);
  border: 1px solid var(--line-soft);
  color: var(--ink);
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
}
.usage-mcp-more:hover { border-color: var(--accent); }

/* ────────────────────────────────────────────────────────────
   Fit menu (2026-08-26). The Fit button in the zoom pill opens
   this instead of firing one fixed framing.
   ──────────────────────────────────────────────────────────── */
.fit-menu {
  position: absolute;
  bottom: 62px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 40;
  min-width: 236px;
  padding: 5px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--glass-base);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-e3);
}
.fit-menu button {
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-align: left;
  background: transparent;
  border: none;
  border-radius: var(--r-2);
  padding: 8px 10px;
  cursor: pointer;
  color: var(--ink);
  font: inherit;
}
.fit-menu button:hover,
.fit-menu button:focus-visible { background: var(--surface-4, #26262F); outline: none; }
.fit-menu button:disabled { opacity: 0.45; cursor: default; }
.fit-menu button:disabled:hover { background: transparent; }
.fit-menu strong { font-size: 12px; font-weight: 600; }
.fit-menu em { font-size: 11px; font-style: normal; color: var(--ink-2); }

/* ────────────────────────────────────────────────────────────
   Floating artboard navigator (2026-08-26). Appears when a page
   holds more than one artboard. Draggable by its header.
   ──────────────────────────────────────────────────────────── */
.ab-nav {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 39;
  width: 188px;
  background: var(--glass-base);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-e3);
  font-size: 12px;
  color: var(--ink);
  user-select: none;
}
.ab-nav-head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 8px;
  cursor: grab;
}
.ab-nav.dragging .ab-nav-head { cursor: grabbing; }
.ab-nav-grip { color: var(--ink-2); font-size: 12px; line-height: 1; }
.ab-nav-title { font-weight: 600; letter-spacing: 0.01em; }
.ab-nav-count {
  margin-left: auto;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
}
.ab-nav-collapse {
  background: transparent;
  border: none;
  color: var(--ink-2);
  cursor: pointer;
  padding: 0 2px;
  font-size: 14px;
  line-height: 1;
}
.ab-nav-collapse:hover { color: var(--ink); }
.ab-nav-body {
  padding: 0 5px 5px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ab-nav.collapsed .ab-nav-body { display: none; }
.ab-nav-list {
  max-height: 190px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ab-nav-list::-webkit-scrollbar { width: 6px; }
.ab-nav-list::-webkit-scrollbar-thumb { background: var(--surface-5, #33333D); border-radius: 3px; }
.ab-nav-item {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  border-radius: var(--r-2);
  padding: 6px 7px;
  cursor: pointer;
  color: var(--ink-2);
  font: inherit;
  overflow: hidden;
}
.ab-nav-item:hover { background: var(--surface-4, #26262F); color: var(--ink); }
.ab-nav-item.active { background: var(--surface-4, #26262F); color: var(--ink); font-weight: 600; }
.ab-nav-item .ab-nav-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: transparent;
  border: 1px solid var(--ink-2);
  flex: 0 0 auto;
}
.ab-nav-item.active .ab-nav-dot { background: var(--accent); border-color: var(--accent); }
.ab-nav-item .ab-nav-name {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ab-nav-item .ab-nav-lock { color: var(--ink-2); font-size: 10px; flex: 0 0 auto; }
.ab-nav-add {
  width: 100%;
  background: transparent;
  border: 1px dashed var(--line);
  border-radius: var(--r-2);
  color: var(--ink-2);
  padding: 6px 7px;
  cursor: pointer;
  font: inherit;
  font-size: 11px;
}
.ab-nav-add:hover { color: var(--accent); border-color: var(--accent); }

/* ────────────────────────────────────────────────────────────
   Detachable panels (2026-08-26)

   The toolbar and the properties panel can be popped out of the grid
   and floated anywhere over the canvas, which hands their column back
   to the drawing surface. Detached they stay deliberately small: a
   capped height with the panel's own scrollbar, plus collapse-to-bar,
   so a floating panel never swallows the canvas it is meant to free up.

   No DOM is reparented on detach. The panel keeps its place in the
   markup and only changes how it is positioned, so every listener,
   selector and id keeps working in both states.
   ──────────────────────────────────────────────────────────── */
.panel-bar {
  position: sticky;
  top: 0;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  user-select: none;
  flex: 0 0 auto;
}
.properties .panel-bar { padding: 7px 10px 7px 14px; margin-bottom: 10px; }
.toolbar .panel-bar { width: 100%; justify-content: center; padding: 2px 0 6px; margin-bottom: 4px; }
/* No room for a label in a 68px tool strip. */
.toolbar .panel-grip, .toolbar .panel-bar-title { display: none; }
.panel-grip { color: var(--ink-3, var(--ink-2)); font-size: 11px; line-height: 1; }
.panel-bar-title {
  flex: 1 1 auto;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.panel-collapse, .panel-detach, .panel-orient {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: var(--r-2);
  color: var(--ink-2);
  cursor: pointer;
  padding: 3px;
  line-height: 1;
  font-size: 13px;
}
.panel-collapse:hover, .panel-detach:hover, .panel-orient:hover { color: var(--accent); background: var(--surface-4, #26262F); }
/* Collapsing and re-orienting only mean anything once the panel floats. */
.panel-collapse, .panel-orient { display: none; }
.detached .panel-collapse, .toolbar.detached .panel-orient { display: inline-flex; }
.detached .panel-detach svg { transform: rotate(180deg); }
.toolbar.detached.horizontal .panel-orient svg { transform: rotate(90deg); }
/* Three buttons have to fit across a tool strip, so trim their spacing. */
.toolbar .panel-bar { gap: 2px; }
.toolbar .panel-collapse, .toolbar .panel-detach, .toolbar .panel-orient { padding: 2px; }

.toolbar.detached, .properties.detached {
  position: absolute;
  grid-area: auto;
  z-index: 46;
  margin: 0;
  max-height: 62vh;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-e3), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.properties.detached { width: 306px; }
.toolbar.detached { width: 68px; padding: 4px 4px 0; }

/* Floating tools, laid out across instead of down. Mirrors the phone
   layout's horizontal strip, so the tools keep one familiar shape. */
.toolbar.detached.horizontal {
  flex-direction: row;
  align-items: center;
  gap: 4px;
  width: 520px;
  height: auto;
  max-height: none;
  padding: 4px 0 4px 4px;
  overflow-x: auto;
  overflow-y: hidden;
}
.toolbar.detached.horizontal .panel-bar {
  position: sticky;
  left: 0;
  top: auto;
  align-self: stretch;
  border-bottom: none;
  border-right: 1px solid var(--line);
  border-radius: var(--radius-md) 0 0 var(--radius-md);
  width: auto;
  margin: 0 4px 0 0;
  padding: 0 5px 0 2px;
}
.toolbar.detached.horizontal .tool { flex: 0 0 auto; }
.toolbar.detached.horizontal::-webkit-scrollbar { height: 6px; width: 6px; }
/* Grabbing the strip to scroll it beats the tools' own pointer cursor. */
.toolbar.detached.scroll-dragging,
.toolbar.detached.scroll-dragging .tool { cursor: grabbing; }
.toolbar.detached.horizontal .tool-sep { flex: 0 0 auto; width: 1px; height: 22px; margin: 0 4px; }

/* Resize grip. Sticky rather than absolute so it stays pinned to the panel
   edge while the panel's own content scrolls behind it. */
.panel-resize { display: none; }
.detached .panel-resize {
  display: block;
  position: sticky;
  bottom: 0;
  z-index: 4;
  flex: 0 0 auto;
  height: 10px;
  margin-top: auto;
  background: var(--panel);
  cursor: ns-resize;
}
.detached .panel-resize::after {
  content: "";
  display: block;
  width: 28px;
  height: 2px;
  margin: 4px auto 0;
  border-radius: 2px;
  background: var(--line);
}
.detached .panel-resize:hover::after { background: var(--accent); }
.toolbar.detached.horizontal .panel-resize {
  position: sticky;
  right: 0;
  bottom: auto;
  height: auto;
  width: 10px;
  align-self: stretch;
  margin: 0 0 0 auto;
  cursor: ew-resize;
}
.toolbar.detached.horizontal .panel-resize::after {
  width: 2px;
  height: 28px;
  margin: auto 4px;
}
.panel-bar { cursor: default; }
.detached .panel-bar { cursor: grab; }
.detached.dragging .panel-bar { cursor: grabbing; }
/* Collapsed: only the bar is left, so the panel parks as a small chip. */
.detached.collapsed { max-height: none; overflow: hidden; }
.detached.collapsed > *:not(.panel-bar) { display: none; }
.detached.collapsed .panel-bar { border-bottom: none; margin-bottom: 0; border-radius: var(--radius-md); }

/* Hand the emptied column back to the canvas. Scoped above the phone
   breakpoint, where the layout is a single stacked column and floating a
   panel over it would only get in the way. */
@media (min-width: 721px) {
  .app.tools-detached { grid-template-columns: 0 1fr 322px; }
  .app.props-detached { grid-template-columns: 68px 1fr 0; }
  .app.tools-detached.props-detached { grid-template-columns: 0 1fr 0; }
}
@media (max-width: 720px) {
  .panel-detach { display: none; }
  .properties .panel-bar, .toolbar .panel-bar { display: none; }
}

/* Artboard groups in the navigator (2026-08-28). Each group is a headed
   block: click the header to frame the whole group, × to ungroup. Rows carry
   a tick box (visible on hover, or once ticked) for building up a set. */
.ab-nav-group {
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  padding: 2px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ab-nav-group.active { border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.ab-nav-group-head { display: flex; align-items: center; gap: 2px; }
.ab-nav-group-name {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  background: transparent;
  border: none;
  border-radius: var(--r-2);
  color: var(--ink-2);
  font: inherit;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-align: left;
  padding: 5px 6px;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ab-nav-group-name:hover { color: var(--accent); background: var(--surface-4, #26262F); }
.ab-nav-group.active .ab-nav-group-name { color: var(--accent); }
.ab-nav-group-count {
  margin-left: auto;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}
.ab-nav-group-ungroup {
  flex: 0 0 auto;
  background: transparent;
  border: none;
  color: var(--ink-3);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 2px 5px;
  border-radius: var(--r-2);
}
.ab-nav-group-ungroup:hover { color: var(--danger); background: var(--surface-4, #26262F); }
.ab-nav-row { display: flex; align-items: center; gap: 2px; }
.ab-nav-row .ab-nav-item { flex: 1 1 auto; min-width: 0; }
.ab-nav-check {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: transparent;
  color: var(--bg);
  font-size: 9px;
  line-height: 1;
  padding: 0;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--t-fast) var(--ease-out);
}
.ab-nav-row:hover .ab-nav-check,
.ab-nav-check:focus-visible { opacity: 1; }
.ab-nav-check.on {
  opacity: 1;
  background: var(--accent);
  border-color: var(--accent);
}
.ab-nav-actions {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 2px 0;
  border-top: 1px solid var(--line);
}
.ab-nav-selcount { color: var(--ink-2); font-size: 11px; margin-right: auto; }
.ab-nav-actions button {
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  color: var(--ink-2);
  font: inherit;
  font-size: 11px;
  padding: 3px 8px;
  cursor: pointer;
}
.ab-nav-actions button:hover { color: var(--accent); border-color: var(--accent); }
#ab-nav-group { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }


/* Framed-in-another-site notice (2026-09-20). Shown only when the editor is
   loaded inside someone else's iframe, e.g. a BuildHop directory preview. */
.framed-notice {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 6px 34px 6px 12px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--line-soft);
  color: var(--ink-2);
  font-size: 12px;
  line-height: 1.4;
}
.framed-notice a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
}
.framed-notice a:hover { color: var(--accent-hi); }
.framed-notice-close {
  position: absolute;
  right: 8px;
  background: transparent;
  border: 0;
  color: var(--ink-3);
  font-size: 16px;
  line-height: 1;
  padding: 2px 6px;
  cursor: pointer;
}
.framed-notice-close:hover { color: var(--ink); }

/* SVG Lab MCP panel (2026-09-23; codeless 2026-09-26). Reuses .modal /
   .modal-card; follows the auth modal's type scale and the lime accent. */
.mcp-card { width: min(560px, 94vw); max-height: 92vh; overflow-y: auto; }
.mcp-lede { color: var(--ink-2); font-size: 13px; line-height: 1.55; margin: 0; }
.mcp-status { font-size: 12.5px; color: var(--ink-2); margin: 0; min-height: 1.2em; line-height: 1.4; }
.mcp-status.is-ok { color: var(--accent); }
.mcp-status.is-error { color: #E04444; }
.mcp-card h4 {
  margin: 0; font-size: 10.5px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.mcp-key-panel {
  display: block;
  padding: 12px 14px; border: 1px solid var(--line-soft, rgba(255,255,255,0.1));
  border-radius: 8px; background: var(--panel-2);
}
.mcp-key-panel > summary {
  cursor: pointer; font-size: 12.5px; color: var(--ink-2); list-style-position: inside;
}
.mcp-key-panel > summary:hover { color: var(--ink); }
.mcp-key-panel[open] > summary { color: var(--ink); }
.mcp-key-panel > * + *:not(summary) { margin-top: 10px; }
.mcp-key-intro { margin: 0; font-size: 12px; color: var(--ink-2); line-height: 1.45; }
.mcp-key-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.mcp-key-meta { font-size: 11.5px; color: var(--ink-3); font-family: var(--font-mono); text-align: right; }
.mcp-key-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.mcp-primary, .mcp-secondary, .mcp-danger {
  padding: 8px 14px; border-radius: 6px; font-size: 13px; font-weight: 600; cursor: pointer;
  transition: filter 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.mcp-primary { background: var(--accent); color: var(--accent-ink, #0B0B10); border: none; }
.mcp-primary:hover:not(:disabled) { filter: brightness(1.07); }
.mcp-secondary { background: transparent; color: var(--ink); border: 1px solid var(--line-soft, rgba(255,255,255,0.14)); }
.mcp-secondary:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.mcp-danger { background: transparent; color: var(--ink-2); border: 1px solid var(--line-soft, rgba(255,255,255,0.14)); }
.mcp-danger:hover:not(:disabled) { border-color: #E04444; color: #ff6b6b; }
.mcp-key-note { margin: 0; font-size: 12px; color: var(--ink-2); line-height: 1.45; }
.mcp-request { margin: 0; }
.mcp-request a.mcp-primary { display: inline-block; text-decoration: none; }
/* 2026-09-26: the plans link leads, the early access request follows. */
.mcp-request { display: flex; flex-wrap: wrap; gap: 8px; }
.mcp-request a.mcp-secondary { display: inline-block; text-decoration: none; }
.mcp-copy-row {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 8px 8px 12px; border: 1px solid var(--line); border-radius: 6px;
  background: var(--bg-deep, #07070B);
}
.mcp-copy-row.is-block { align-items: flex-start; }
.mcp-copy-text {
  flex: 1; min-width: 0; margin: 0;
  font-family: var(--font-mono); font-size: 12px; line-height: 1.5; color: var(--ink);
  white-space: pre-wrap; word-break: break-all; user-select: all;
}
.mcp-copy-btn {
  flex: none; padding: 5px 10px; border-radius: 5px; font-size: 12px; cursor: pointer;
  background: var(--panel-2); color: var(--ink); border: 1px solid var(--line-soft, rgba(255,255,255,0.14));
}
.mcp-copy-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.mcp-copy-btn.is-copied { border-color: var(--accent); color: var(--accent); }
.mcp-guide { display: flex; flex-direction: column; gap: 8px; }
.mcp-guide p { margin: 0; font-size: 12.5px; color: var(--ink-2); line-height: 1.5; }
.mcp-guide a { color: var(--ink); text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 2px; }
.mcp-guide a:hover { color: var(--accent); }

/* "Early access" / "Requested" badge on the account menu's MCP item
   (2026-09-24). The item itself keeps full contrast: it is an invitation,
   not a disabled row. */
#btn-mcp { gap: 8px; }  /* the menu's buttons are already centred flex rows */
.menu-badge {
  flex: none; padding: 2px 7px; border-radius: 999px;
  font-size: 10px; font-weight: 600; line-height: 1.4; letter-spacing: 0.02em;
  color: var(--accent); background: var(--accent-soft, rgba(181, 255, 58, 0.14));
  border: 1px solid rgba(181, 255, 58, 0.28);
}
.menu-badge.is-requested {
  color: var(--ink-2); background: transparent; border-color: var(--line-soft, rgba(255,255,255,0.14));
}

/* Universal hidden override — comes last to beat class rules that set display. */
/* MCP modal: connected apps (OAuth grants, 2026-09-24) */
.mcp-conn { margin-top: 14px; }
.mcp-conn h4 { margin: 0 0 8px; }
.mcp-conn-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.mcp-conn-list li { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 13px; padding: 8px 10px; border: 1px solid var(--line, rgba(255,255,255,0.08)); border-radius: 8px; }
.mcp-conn-list li span { min-width: 0; overflow-wrap: anywhere; }
.mcp-conn-empty { margin: 0; font-size: 12.5px; color: var(--ink-2); line-height: 1.5; }

/* ────────────────────────────────────────────────────────────
   SVG Lab MCP invitation (2026-09-26)
   First onboarding panel, the account-menu pointer, and the menu item's
   "request early access" state. Scripts: app.js sections 28 and 38.
   ──────────────────────────────────────────────────────────── */
.onboarding-modal.is-mcp-step .onboarding-card { max-width: 520px; }
.onboarding-modal.is-mcp-step .onboarding-step { padding-top: 22px; gap: 12px; }
.onb-shots {
  display: flex; justify-content: center; align-items: flex-end; gap: 12px;
  height: 172px; margin: 0 -32px 6px; padding: 18px 32px 0;
  overflow: hidden; position: relative;
  background:
    radial-gradient(120% 90% at 50% 100%, rgba(181, 255, 58, 0.10), transparent 60%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.02), rgba(255, 255, 255, 0));
  border-bottom: 1px solid var(--line);
}
.onb-shot {
  flex: none; width: 92px; padding: 4px; border-radius: 16px;
  background: #1C1C24;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.07) inset, 0 18px 30px -16px rgba(0, 0, 0, 0.9);
  transform: translateY(18px);
}
.onb-shot:nth-child(2) { width: 104px; transform: translateY(4px); }
.onb-shot:nth-child(1) { transform: translateY(26px) rotate(-5deg); }
.onb-shot:nth-child(3) { transform: translateY(26px) rotate(5deg); }
.onb-shot img { display: block; width: 100%; height: auto; aspect-ratio: 780 / 1688; border-radius: 12px; background: #F4EFE6; }
.onboarding-step .onb-note { font-size: 11.5px; color: var(--ink-3); }
.onboarding-next.is-secondary {
  background: transparent; border-color: var(--line); color: var(--ink-2); font-weight: 500;
}
.onboarding-next.is-secondary:hover {
  background: transparent; border-color: var(--ink-3); color: var(--ink);
}
a.onboarding-request { display: inline-flex; align-items: center; text-decoration: none; white-space: nowrap; }
a.onboarding-request:hover { color: var(--accent-ink); }
@media (max-width: 520px) {
  /* The editor is wider than a phone, so the page itself scrolls sideways;
     pin the modal to the screen width instead of the page width. */
  .onboarding-modal { right: auto; bottom: auto; width: 100vw; height: 100vh; height: 100dvh; }
  .onboarding-card { min-width: 0; width: calc(100vw - 32px); }
  .onboarding-step { padding: 26px 22px 12px; min-height: 0; }
  .onb-shots { margin: 0 -22px 4px; padding: 16px 22px 0; height: 150px; }
  .onb-shot { width: 80px; }
  .onb-shot:nth-child(2) { width: 90px; }
  .onboarding-footer { flex-wrap: wrap; padding: 12px 16px 14px; }
  .onboarding-modal.is-mcp-step .onboarding-nav { order: -1; width: 100%; flex-direction: column-reverse; }
  .onboarding-modal.is-mcp-step .onboarding-nav > * { justify-content: center; text-align: center; padding: 10px 14px; font-size: 13px; }
}

/* Account-menu pointer: a callout under the account button. */
.mcp-pointer {
  position: fixed; z-index: 90; width: 280px; max-width: calc(100vw - 24px);
  padding: 14px 14px 12px;
  background: var(--panel); color: var(--ink);
  border: 1px solid rgba(181, 255, 58, 0.7);
  border-radius: var(--r-3);
  box-shadow: 0 0 0 4px rgba(181, 255, 58, 0.08), var(--shadow-2);
  animation: mcp-pointer-in 360ms var(--ease-out) both;
}
.mcp-pointer::before {
  content: ""; position: absolute; top: -8px; left: calc(var(--arrow-x, 50%) - 7px);
  width: 14px; height: 14px; transform: rotate(45deg); border-top-left-radius: 3px;
  background: var(--panel);
  border-left: 1px solid rgba(181, 255, 58, 0.7); border-top: 1px solid rgba(181, 255, 58, 0.7);
}
.mcp-pointer-title { margin: 0 0 4px; font-size: 13px; font-weight: 600; line-height: 1.35; color: var(--ink); }
.mcp-pointer-title::before {
  content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 8px; vertical-align: 1px;
  border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px rgba(181, 255, 58, 0.18);
}
.mcp-pointer-body { margin: 0 0 12px; font-size: 12px; line-height: 1.5; color: var(--ink-2); }
.mcp-pointer-actions { display: flex; gap: 8px; }
.mcp-pointer-actions button {
  font: inherit; font-size: 12px; padding: 6px 12px; border-radius: var(--r-2); cursor: pointer;
  border: 1px solid var(--line); background: transparent; color: var(--ink-2);
}
.mcp-pointer-actions .mcp-pointer-go { background: var(--accent); border-color: var(--accent); color: #0B0B10; font-weight: 600; }
.mcp-pointer-actions .mcp-pointer-go:hover { color: #0B0B10; filter: brightness(1.06); }
.mcp-pointer-actions .mcp-pointer-close:hover { color: var(--ink); border-color: var(--ink-3); }
@keyframes mcp-pointer-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .mcp-pointer { animation: none; } }

/* ────────────────────────────────────────────────────────────
   After MCP early access (2026-09-27, from 2026-10-03 07:00 UTC).
   The first-run panel's connect steps and the "Connect your AI" chip under
   the account button. Scripts: app.js sections 28a, 28 and 38.
   ──────────────────────────────────────────────────────────── */
/* The three example screens are shown whole on this panel (owner, 2026-09-27):
   no crop, no offsets past the edge. Height follows the widths below; the
   source images are 780 x 1688, so they stay sharp when scaled down. */
.onboarding-modal.is-mcp-after .onb-shots {
  flex: none; height: auto; align-items: center; gap: 14px;
  padding: 16px 32px 14px;
}
.onboarding-modal.is-mcp-after .onb-shot { width: 72px; transform: rotate(-4deg); }
.onboarding-modal.is-mcp-after .onb-shot:nth-child(2) { width: 82px; transform: none; }
.onboarding-modal.is-mcp-after .onb-shot:nth-child(3) { transform: rotate(4deg); }
/* The connect panel is taller than the early access one: keep the footer on
   screen on short laptop screens (smaller screens, then scroll the text). */
.onboarding-modal.is-mcp-after .onboarding-card { max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px); }
.onboarding-modal.is-mcp-after .onboarding-step { min-height: 0; overflow-y: auto; }
.onboarding-modal.is-mcp-after .onboarding-footer { flex: none; }
@media (max-height: 820px) {
  .onboarding-modal.is-mcp-after .onb-shots { padding: 12px 32px 10px; gap: 12px; }
  .onboarding-modal.is-mcp-after .onb-shot { width: 50px; padding: 3px; border-radius: 11px; }
  .onboarding-modal.is-mcp-after .onb-shot:nth-child(2) { width: 56px; }
  .onboarding-modal.is-mcp-after .onb-shot img { border-radius: 8px; }
}
@media (max-height: 700px) {
  .onboarding-modal.is-mcp-after .onboarding-step { gap: 8px; padding-top: 16px; padding-bottom: 6px; }
  .onboarding-modal.is-mcp-after .onb-shots { padding: 8px 32px 8px; }
  .onboarding-modal.is-mcp-after .onb-shot { width: 46px; }
  .onboarding-modal.is-mcp-after .onb-shot:nth-child(2) { width: 52px; }
  .onboarding-step ol.onb-connect { gap: 6px; }
}
@media (max-width: 520px) {
  .onboarding-modal.is-mcp-after .onb-shots { padding: 14px 22px 12px; }
  .onboarding-modal.is-mcp-after .onb-shot { width: 62px; }
  .onboarding-modal.is-mcp-after .onb-shot:nth-child(2) { width: 70px; }
}
.onboarding-modal.is-mcp-after .onboarding-step { gap: 10px; }
.onboarding-modal.is-mcp-after .onboarding-step > p:not(.onb-note) { font-size: 13.5px; }
.onboarding-step ol.onb-connect {
  margin: 2px 0 0; padding: 0; list-style: none; counter-reset: onb-connect;
  display: flex; flex-direction: column; gap: 8px;
}
.onboarding-step ol.onb-connect > li {
  counter-increment: onb-connect;
  display: flex; flex-direction: column; gap: 6px;
  position: relative; padding-left: 30px;
  color: var(--ink-2); font-size: 13px; line-height: 1.5;
}
.onboarding-step ol.onb-connect > li::before {
  content: counter(onb-connect);
  position: absolute; left: 0; top: 1px;
  width: 20px; height: 20px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 600; color: var(--accent);
  background: rgba(181, 255, 58, 0.10); border: 1px solid rgba(181, 255, 58, 0.3);
}
.onb-copy-row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 6px 6px 10px; border: 1px solid var(--line-soft, rgba(255,255,255,0.14)); border-radius: var(--r-2);
  background: var(--bg-deep, #07070B);
}
.onb-copy-row code {
  flex: 1; min-width: 0; font-family: var(--font-mono); font-size: 12.5px; color: var(--ink);
  user-select: all; overflow-wrap: anywhere;
}
.onb-copy {
  flex: none; padding: 4px 10px; border-radius: 5px; font: inherit; font-size: 12px; cursor: pointer;
  background: var(--panel-2); color: var(--ink); border: 1px solid var(--line-soft, rgba(255,255,255,0.14));
}
.onb-copy:hover, .onb-copy.is-copied { border-color: var(--accent); color: var(--accent); }
.onboarding-step .onb-free { font-size: 12px; color: var(--ink-2); }
.onboarding-step .onb-free a { color: var(--ink); text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 2px; }
.onboarding-step .onb-free a:hover { color: var(--accent); }

/* "Connect your AI" chip in the top bar, just left of the account button
   (signed in, until its X). Inside .actions, so it overrides the bar's
   button look for its two inner buttons. */
.mcp-chip {
  flex: none;
  display: inline-flex; align-items: stretch;
  height: 30px;
  background: var(--panel-2); color: var(--ink);
  border: 1px solid rgba(181, 255, 58, 0.45);
  border-radius: 10px;
  animation: mcp-pointer-in 360ms var(--ease-out) both;
}
.mcp-chip button, .actions .mcp-chip button {
  display: inline-flex; align-items: center; justify-content: center;
  height: 28px; border: 0; background: transparent; box-shadow: none; border-radius: 0;
  font: inherit; font-size: 12px; color: inherit; cursor: pointer; transform: none;
}
/* The entrance plays once; moving between the bar and the strip on a
   resize must not replay it. */
.mcp-chip.is-settled { animation: none; }
.mcp-chip .mcp-chip-open {
  gap: 7px; padding: 0 4px 0 11px; border-radius: 9px 0 0 9px;
}
.mcp-chip-dot {
  flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
  box-shadow: 0 0 0 3px rgba(181, 255, 58, 0.18);
}
.mcp-chip-title { font-weight: 600; color: var(--ink); white-space: nowrap; }
.mcp-chip-sub { color: var(--ink-3); white-space: nowrap; font-weight: 400; }
.mcp-chip.is-compact .mcp-chip-sub { display: none; }
/* No room in the bar: fixed at the right end of the page tabs strip. */
.mcp-chip.is-floating { position: fixed; z-index: 45; box-shadow: var(--shadow-2); }
.mcp-chip .mcp-chip-open:hover { background: transparent; }
.mcp-chip .mcp-chip-open:hover .mcp-chip-title { color: var(--accent); }
.mcp-chip .mcp-chip-close {
  width: 28px; padding: 0 8px 0 4px; color: var(--ink-3); border-radius: 0 9px 9px 0;
}
.mcp-chip-close .icon { width: 12px; height: 12px; }
.mcp-chip .mcp-chip-close:hover { background: transparent; color: var(--ink); }
.mcp-chip-open:focus-visible, .mcp-chip-close:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
@media (prefers-reduced-motion: reduce) { .mcp-chip { animation: none; } }

/* The menu item while the account can still apply, and its highlight when
   the pointer opens the menu. */
#user-menu-dropdown #btn-mcp { white-space: nowrap; }
#user-menu-dropdown #btn-mcp.is-invite { color: var(--accent); }
#user-menu-dropdown #btn-mcp.is-spotlight {
  background: rgba(181, 255, 58, 0.12);
  box-shadow: 0 0 0 1px rgba(181, 255, 58, 0.45) inset;
}

/* ────────────────────────────────────────────────────────────
   AI presence on artboard groups (2026-09-26). An AI assistant working
   through the MCP holds an artboard group: a coloured frame on the group's
   lasso and a pill with the client's name ("Claude", "Codex", ...), its
   current step and Pause / Stop. Colours are Okabe-Ito based and avoid the
   lime accent, amber selection and red lock; colour is never the only cue
   (slot 2 is dashed, slot 3 dotted, and the pill always names the client).
   ──────────────────────────────────────────────────────────── */
:root {
  --presence-1: #56B4E9; /* sky */
  --presence-2: #D98CC4; /* orchid */
  --presence-3: #A3A8FF; /* periwinkle */
  --presence-ink: #0B0B10;
}
#ai-presence .ai-presence-frame {
  fill: none;
  stroke: var(--presence-1);
  opacity: 0.55;
}
#ai-presence .ai-presence-frame.slot-2 { stroke: var(--presence-2); }
#ai-presence .ai-presence-frame.slot-3 { stroke: var(--presence-3); }
#ai-presence .ai-presence-frame.is-active { opacity: 0.8; }
/* One breath per AI step (app.js aiBreath), never a loop: a looping
   animation costs a style pass every frame (measured 2026-09-26). */
#ai-presence .ai-presence-frame.is-breathing { animation: ai-presence-breathe 2.4s ease-in-out 1 both; }
@keyframes ai-presence-breathe {
  0% { opacity: 0.55; }
  40% { opacity: 1; }
  100% { opacity: 0.8; }
}
#ai-presence .ai-pill { cursor: default; }
#ai-presence .ai-pill-bg { fill: var(--presence-1); }
#ai-presence .ai-pill.slot-2 .ai-pill-bg { fill: var(--presence-2); }
#ai-presence .ai-pill.slot-3 .ai-pill-bg { fill: var(--presence-3); }
#ai-presence .ai-pill.is-ended .ai-pill-bg {
  fill: var(--surface-3, #1E1E26);
  stroke: var(--presence-1);
  stroke-width: 1;
}
#ai-presence .ai-pill.slot-2.is-ended .ai-pill-bg { stroke: var(--presence-2); }
#ai-presence .ai-pill.slot-3.is-ended .ai-pill-bg { stroke: var(--presence-3); }
#ai-presence .ai-pill-text {
  fill: var(--presence-ink);
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  -webkit-user-select: none;
  user-select: none;
}
#ai-presence .ai-pill-name { font-weight: 650; }
#ai-presence .ai-pill.is-ended .ai-pill-text { fill: var(--ink, #EDEDF0); }
#ai-presence .ai-pill-dot { fill: var(--presence-ink); }
#ai-presence .ai-pill-dot.is-breathing { animation: ai-presence-pulse 1.2s ease-in-out 2; }
#ai-presence .ai-pill.is-idle .ai-pill-dot { opacity: 0.45; }
@keyframes ai-presence-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}
#ai-presence .ai-pill-btn { cursor: pointer; outline: none; }
#ai-presence .ai-pill-btn rect { fill: rgba(11, 11, 16, 0.14); transition: fill var(--t-fast, 120ms) ease-out; }
#ai-presence .ai-pill-btn:hover rect,
#ai-presence .ai-pill-btn:focus-visible rect { fill: rgba(11, 11, 16, 0.28); }
#ai-presence .ai-pill-btn:focus-visible rect { stroke: var(--presence-ink); stroke-width: 1.5; }
#ai-presence .ai-pill.is-ended .ai-pill-btn rect { fill: rgba(237, 237, 240, 0.1); }
#ai-presence .ai-pill-btn text {
  fill: var(--presence-ink);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 650;
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
}
#ai-presence .ai-pill.is-ended .ai-pill-btn text { fill: var(--ink, #EDEDF0); }
#overlay .ab-frame.ai-held { stroke: var(--presence-1); }
.ab-nav-item .ab-nav-ai {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  flex: 0 0 auto;
  margin-left: auto;
  font-size: 10px;
  font-weight: 600;
  color: var(--presence-1);
}
.ab-nav-item .ab-nav-ai.slot-2 { color: var(--presence-2); }
.ab-nav-item .ab-nav-ai.slot-3 { color: var(--presence-3); }
.ab-nav-item .ab-nav-ai svg {
  width: 11px;
  height: 11px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
}
.ab-nav-item.ai-held { box-shadow: inset 3px 0 0 var(--presence-1); }
.ab-nav-group-name.ai-held::after { content: " \2022 AI"; color: var(--presence-1); font-weight: 600; }
.ab-nav-group-ungroup:disabled { opacity: 0.3; cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) {
  #ai-presence .ai-presence-frame.is-breathing,
  #ai-presence .ai-pill-dot.is-breathing { animation: none; }
}

/* Watch mode (2026-09-26): while an AI assistant designs in this project,
   this tab only watches its artboards. One calm line at the top of the
   canvas, with Take over and Pause. */
.ai-watch-banner {
  position: absolute;
  top: 12px;
  left: 0;
  right: 0;
  margin: 0 auto;
  width: max-content;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: calc(100% - 32px);
  padding: 6px 6px 6px 14px;
  border-radius: 999px;
  background: rgba(11, 11, 16, 0.86);
  border: 1px solid var(--presence-1);
  color: var(--ink, #EDEDF0);
  font-family: var(--font-sans);
  font-size: 12.5px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.ai-watch-banner.slot-2 { border-color: var(--presence-2); }
.ai-watch-banner.slot-3 { border-color: var(--presence-3); }
.ai-watch-banner .ai-watch-dot {
  width: 7px;
  height: 7px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--presence-1);
}
.ai-watch-banner .ai-watch-dot.is-breathing { animation: ai-presence-pulse 1.2s ease-in-out 2; }
.ai-watch-banner.slot-2 .ai-watch-dot { background: var(--presence-2); }
.ai-watch-banner.slot-3 .ai-watch-dot { background: var(--presence-3); }
.ai-watch-banner .ai-watch-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ai-watch-banner .ai-watch-btn {
  flex: 0 0 auto;
  padding: 4px 11px;
  border-radius: 999px;
  border: 1px solid rgba(237, 237, 240, 0.18);
  background: rgba(237, 237, 240, 0.08);
  color: inherit;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.ai-watch-banner .ai-watch-btn:hover,
.ai-watch-banner .ai-watch-btn:focus-visible { background: rgba(237, 237, 240, 0.16); outline: none; border-color: var(--presence-1); }
@media (prefers-reduced-motion: reduce) {
  .ai-watch-banner .ai-watch-dot.is-breathing { animation: none; }
}

/* The presence overlay: its own layer above the canvas (see app.js
   aiPresenceLayer). Only the pills take the pointer. */
.ai-presence-svg {
  position: absolute;
  left: 0;
  top: 0;
  overflow: visible;
  pointer-events: none;
  z-index: 5;
  will-change: transform;
  contain: strict;
}
.ai-presence-svg .ai-pill { pointer-events: all; }
.ai-presence-svg .ai-presence-frame { pointer-events: none; }

[hidden] { display: none !important; }
