:root {
  --bg:#1a1a1e; --bg-secondary:#242428; --bg-hover:#35353d; --surface:#2a2a30; --surface-raised:#323238; 
  --border:rgba(255,255,255,0.1); --border-strong:rgba(255,255,255,0.14); --text:#f2f2f7; 
  --text-secondary:#8e8e93; --text-tertiary:#636366; --accent:#007aff; --accent-hover:#0a84ff; 
  --accent-dim:rgba(0,122,255,0.15); --success:#34c759; --radius:8px; 
  /* Keep UI fonts independent of the Type tool's asynchronously registered family aliases. */
  --font:system-ui, sans-serif; --properties-panel-w:220px;
  --right-dock-w:286px; /* paint-row content width: 44+26+26+64+66 cols + 4*8 gaps + panel padding/border */
  --panel-header-h:21px; /* fixed side-panel header height (Properties = master): 14px title + 6px pad + 1px border. Never grows to fit a button. */
  --ruler-size:20px; --ruler-bg:#242428; --ruler-tick:rgba(242,242,247,0.48); --ruler-text:rgba(242,242,247,0.68);
  --guide-color:#00dcff; --guide-selected:#3167ff;
  --snap-guide:#ff2fd2;
}
html, body { height:100%; height:100dvh; overflow:hidden; overscroll-behavior:none; touch-action:none; user-select:none; -webkit-user-select:none; margin:0; }

body.is-dragging, body.is-dragging * { cursor: default !important; }
/* Workspace divider drag: one window-wide shield carries the cursor. A `body.x *` rule would restyle
   every element in the document when the drag starts and ends (a visible hitch with artwork loaded). */
body.is-resizing-ws::after { content:""; position:fixed; inset:0; z-index:2147483647; cursor:ns-resize; }
body.is-panning, body.is-panning * { cursor: grabbing !important; }
body.is-hist-dragging, body.is-hist-dragging * { cursor: grabbing !important; }
body.is-hist-resizing, body.is-hist-resizing * { cursor: ns-resize !important; }
body.is-scrubbing-prop, body.is-scrubbing-prop * { cursor: ew-resize !important; }
body.is-guide-creating, body.is-guide-creating * { cursor: default !important; }
body.ruler-bound-hover, body.ruler-bound-hover * { cursor: default !important; }
body.guide-cur-v, body.guide-cur-v * { cursor: ew-resize !important; }
body.guide-cur-h, body.guide-cur-h * { cursor: ns-resize !important; }

body { padding:10px; box-sizing:border-box; background:var(--bg); color:var(--text); font-family:var(--font); display:flex; flex-direction:column; align-items:center; gap:10px; }
/* Form controls otherwise use browser font defaults (such as Arial), also aliased by artwork fonts. */
button, input, select, textarea { font-family:var(--font); }
h2 { position:relative; margin:0; font-weight:600; letter-spacing:0.5px; flex-shrink:0; }
.app-logo { position:absolute; right:100%; top:50%; transform:translateY(-50%); height:1.5em; width:auto; margin-right:0.4em; cursor:pointer; user-select:none; transition:opacity 0.15s ease; }
.app-logo:hover { opacity:0.82; }
.app-logo:focus-visible { outline:2px solid var(--accent); outline-offset:3px; border-radius:6px; }

.app-header { position:relative; width:100%; min-height:32px; display:block; flex-shrink:0; }
.app-header h2 { position:absolute; left:50%; top:50%; transform:translate(-50%, -50%); display:flex; align-items:center; gap:0.4em; }
.app-header .app-logo { position:static; transform:none; height:1.5em; margin-right:0; }
.app-header .new-artboard-actions { position:absolute; left:0; top:50%; transform:translateY(-50%); }
.header-left-controls { position:absolute; right:calc(50% + 132px); top:50%; transform:translateY(-50%); display:flex; align-items:center; justify-content:flex-end; gap:6px; }
.ws-reset-btn { height:30px; display:inline-flex; align-items:center; justify-content:center; box-sizing:border-box; background:var(--bg-secondary); color:var(--text); border:1px solid var(--border); border-radius:4px; padding:0 12px; font-family:var(--font); font-size:11px; font-weight:600; letter-spacing:0.2px; cursor:pointer; transition:0.15s; touch-action:manipulation; box-shadow:inset 0 1px 0 rgba(255,255,255,0.04); }
.ws-reset-btn:hover { background:var(--bg-secondary); color:var(--text); border-color:var(--border); }
/* Right header cluster -- spans from the guide controls' left anchor to the header right
   edge so the Pen mode bar can center itself in the gap between Snap and Info. */
.header-right-cluster { position:absolute; left:calc(50% + 132px); right:0; top:50%; transform:translateY(-50%); display:flex; align-items:center; justify-content:space-between; gap:6px; }
.header-action-controls { display:flex; align-items:center; gap:6px; flex:0 0 auto; }
.settings-btn { height:30px; display:inline-flex; align-items:center; justify-content:center; gap:6px; box-sizing:border-box; background:var(--bg-secondary); color:var(--text-secondary); border:1px solid var(--border); border-radius:4px; padding:0 12px 0 10px; font-family:var(--font); font-size:11px; line-height:1; font-weight:600; letter-spacing:0.2px; cursor:pointer; transition:0.15s; touch-action:manipulation; box-shadow:inset 0 1px 0 rgba(255,255,255,0.04); }
.settings-btn:hover, .settings-btn:focus-visible { background:var(--bg-secondary); color:var(--text-secondary); border-color:var(--border); outline:none; }
.settings-btn .settings-icon { width:10px; height:10px; flex:0 0 10px; display:block; }
.settings-btn span { display:block; line-height:1; }
.about-btn .about-icon { width:12px; height:12px; flex:0 0 12px; display:block; }
.app-version { position:fixed; right:14px; top:14px; z-index:100; max-width:35vw; height:30px; display:flex; align-items:center; gap:6px; overflow:hidden; white-space:nowrap; color:var(--text-secondary); background:transparent; border:none; padding:0; font-family:monospace; font-size:11px; font-weight:600; letter-spacing:0.5px; cursor:pointer; transition:color 0.15s ease; touch-action:manipulation; }
.app-version[hidden] { display:none; }
.app-version:hover, .app-version:focus-visible { color:var(--text); outline:none; }
.app-version:focus-visible { text-decoration:underline; text-underline-offset:3px; }
.app-version-icon { width:14px; height:14px; }
.app-version-text { min-width:0; overflow:hidden; text-overflow:ellipsis; }
.header-guide-controls { margin-left:0; display:flex; align-items:center; gap:6px; flex:0 0 auto; }
.header-guide-btn { height:30px; padding:0 11px; box-sizing:border-box; display:inline-flex; align-items:center; justify-content:center; gap:6px; color:var(--text); background:var(--bg-secondary); border:1px solid var(--border); border-radius:4px; font-family:var(--font); font-size:11px; font-weight:600; letter-spacing:0.2px; cursor:pointer; transition:0.15s; touch-action:manipulation; box-shadow:inset 0 1px 0 rgba(255,255,255,0.04); }
.header-guide-btn:hover, .header-guide-btn:focus-visible { color:var(--text); background:var(--bg-secondary); border-color:var(--border); outline:none; }
.header-guide-label { line-height:1; }
.header-guide-check { position:relative; width:13px; height:13px; flex:0 0 13px; box-sizing:border-box; border:1px solid rgba(255,255,255,0.22); border-radius:3.5px; background:rgba(255,255,255,0.045); transition:0.15s; box-shadow:inset 0 1px 0 rgba(255,255,255,0.07); }
.header-guide-btn:hover .header-guide-check, .header-guide-btn:focus-visible .header-guide-check { border-color:rgba(255,255,255,0.28); background:rgba(255,255,255,0.07); }
.header-guide-btn.is-checked { color:var(--text); background:var(--bg-secondary); border-color:var(--border); }
.header-guide-btn.is-checked:hover, .header-guide-btn.is-checked:focus-visible { background:var(--bg-secondary); border-color:var(--border); }
.header-guide-check { overflow:visible; }
.header-guide-btn.is-checked .header-guide-check::after { content:''; position:absolute; left:4px; top:-4px; width:4.5px; height:10px; border:solid var(--accent); border-width:0 2.5px 2.5px 0; border-radius:1px; transform:rotate(45deg); }
.header-snap-btn { margin-left:10px; }

/* --- Information popup host (pages/infoPopup.html) -------------------------------------------
   The dialog itself lives in the standalone page; this element is only its window. The dim +
   blur sit on the iframe element so the backdrop filters the parent app behind it -- the page
   inside stays transparent. */
.info-frame { position:fixed; inset:0; width:100%; height:100%; z-index:10040; border:none; background:rgba(10,10,14,0.5); backdrop-filter:blur(7px) saturate(1.12); -webkit-backdrop-filter:blur(7px) saturate(1.12); }
.info-frame[hidden] { display:none; }

/* Shared with .settings-dialog. */
@keyframes about-dialog-in { from { opacity:0; transform:translateY(4px) scale(0.95); } to { opacity:1; transform:translateY(0) scale(1); } }

@media (prefers-reduced-motion: reduce) {
  .settings-dialog { animation:none; }
}

/* --- Settings window (js/settings-window.js) -------------------------------------------------
   Color-picker/Information chrome (same surface, header, footer treatment) over a two-column
   body: a recessed category rail on the left, one pane per category on the right. The active
   rail row carries the accent stripe already used on .version-dialog. */
.settings-overlay { position:fixed; inset:0; z-index:10050; display:flex; align-items:center; justify-content:center; padding:16px; box-sizing:border-box; background:rgba(10,10,14,0.5); backdrop-filter:blur(7px) saturate(1.12); -webkit-backdrop-filter:blur(7px) saturate(1.12); }
.settings-overlay[hidden] { display:none; }
.settings-dialog { width:min(620px, calc(100vw - 32px)); max-height:calc(100dvh - 32px); display:flex; flex-direction:column; overflow:hidden; color:var(--text); background:var(--surface); border:1px solid var(--border-strong); border-radius:14px; box-shadow:0 24px 60px rgba(0,0,0,0.55), 0 0 0 1px rgba(0,0,0,0.3); animation:about-dialog-in 0.2s ease-out; }
.settings-dialog-head { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:8px 14px; flex-shrink:0; background:var(--bg-secondary); border-bottom:1px solid var(--border); }
.settings-dialog-title { display:flex; align-items:center; gap:7px; margin:0; color:var(--text); font-size:14px; font-weight:600; }
.settings-dialog-title .settings-title-icon { width:13px; height:13px; flex:0 0 13px; }
.settings-close-btn { padding:0 4px; color:var(--text-secondary); background:transparent; border:none; font-family:var(--font); font-size:18px; line-height:1; cursor:pointer; transition:color 0.15s; touch-action:manipulation; }
.settings-close-btn:hover, .settings-close-btn:focus-visible { color:var(--text); outline:none; }

.settings-dialog-body { flex:1 1 auto; min-height:320px; display:flex; overflow:hidden; }
.settings-nav { width:164px; flex:0 0 164px; box-sizing:border-box; display:flex; flex-direction:column; gap:2px; padding:12px 10px; overflow-y:auto; background:var(--bg); border-right:1px solid var(--border); }
.settings-nav-label { padding:0 8px 8px; color:var(--text-tertiary); font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:0.8px; }
.settings-nav-btn { position:relative; width:100%; box-sizing:border-box; padding:8px 10px 8px 12px; flex-shrink:0; text-align:left; color:var(--text-secondary); background:transparent; border:none; border-radius:7px; font-family:var(--font); font-size:12px; font-weight:600; letter-spacing:0.1px; cursor:pointer; transition:background 0.15s, color 0.15s; touch-action:manipulation; }
.settings-nav-btn:hover { color:var(--text); background:rgba(255,255,255,0.05); }
.settings-nav-btn:focus-visible { outline:2px solid var(--accent-hover); outline-offset:-2px; }
.settings-nav-btn.is-active { color:var(--text); background:var(--surface-raised); box-shadow:inset 0 1px 0 rgba(255,255,255,0.05); }
.settings-nav-btn.is-active::before { content:''; position:absolute; left:0; top:7px; bottom:7px; width:3px; border-radius:0 2px 2px 0; background:var(--accent); }

.settings-panes { flex:1; min-width:0; display:flex; }
.settings-pane { flex:1; min-width:0; box-sizing:border-box; display:flex; flex-direction:column; padding:16px 18px; overflow-y:auto; }
.settings-pane[hidden] { display:none; }
.settings-pane-head { flex-shrink:0; padding-bottom:12px; border-bottom:1px solid var(--border); }
.settings-pane-title { margin:0; color:var(--text); font-size:15px; font-weight:700; letter-spacing:-0.2px; }
.settings-pane-sub { margin:4px 0 0; color:var(--text-secondary); font-size:11.5px; line-height:1.45; }
.settings-pane-body { flex:1; min-height:0; display:flex; align-items:center; justify-content:center; }
.settings-empty { margin:0; color:var(--text-tertiary); font-size:11.5px; text-align:center; }

.settings-dialog-footer { display:flex; align-items:center; justify-content:flex-end; gap:8px; padding:12px 16px; flex-shrink:0; background:var(--bg-secondary); border-top:1px solid var(--border); }
.settings-action { min-width:88px; display:inline-flex; align-items:center; justify-content:center; box-sizing:border-box; padding:10px 18px; flex-shrink:0; font-family:var(--font); font-size:13px; font-weight:500; border:none; border-radius:10px; cursor:pointer; transition:background 0.15s, transform 0.15s, opacity 0.15s; touch-action:manipulation; }
.settings-action:active { transform:scale(0.97); opacity:0.7; }
.settings-action:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.settings-action-ghost { color:var(--text); background:rgba(255,255,255,0.08); }
.settings-action-ghost:hover { background:rgba(255,255,255,0.12); }
.settings-action-primary { color:#fff; background:var(--accent); }
.settings-action-primary:hover { background:var(--accent-hover); }

@media (max-width:520px) {
  .settings-nav { width:132px; flex-basis:132px; padding:10px 8px; }
  .settings-pane { padding:14px; }
}

@media (max-height:560px) {
  .settings-dialog-body { min-height:200px; }
}

.version-overlay { position:fixed; inset:0; z-index:10020; display:flex; justify-content:flex-end; align-items:flex-start; padding:52px 12px 12px; box-sizing:border-box; background:rgba(10,10,14,0.34); backdrop-filter:blur(8px) saturate(1.2); -webkit-backdrop-filter:blur(8px) saturate(1.2); }
.version-overlay[hidden] { display:none; }
.version-dialog { position:relative; width:min(380px, calc(100vw - 24px)); overflow:hidden; color:var(--text); background:linear-gradient(180deg, rgba(50,50,56,0.98), rgba(36,36,40,0.98)); border:1px solid var(--border-strong); border-radius:8px; box-shadow:0 18px 48px rgba(0,0,0,0.48), 0 0 0 1px rgba(0,0,0,0.28); }
.version-dialog::before { content:""; position:absolute; left:0; top:0; bottom:0; width:3px; background:var(--accent); }
.version-dialog-head { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:14px 14px 12px 16px; border-bottom:1px solid var(--border); }
.version-dialog-id { display:flex; align-items:center; gap:10px; min-width:0; }
.version-dialog-icon { width:34px; height:34px; display:flex; align-items:center; justify-content:center; color:var(--accent); background:var(--accent-dim); border:1px solid rgba(0,122,255,0.32); border-radius:6px; flex-shrink:0; }
.version-dialog-icon .icon-svg { width:18px; height:18px; }
.version-dialog-title-wrap { min-width:0; }
.version-kicker, .version-stamp-label, .version-detail span { display:block; color:var(--text-secondary); font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; }
.version-dialog-title { margin:2px 0 0; font-size:15px; font-weight:700; letter-spacing:0; }
.version-close-btn { width:28px; height:28px; display:flex; align-items:center; justify-content:center; padding:0; color:var(--text-secondary); background:transparent; border:none; border-radius:4px; cursor:pointer; transition:0.15s; touch-action:manipulation; flex-shrink:0; }
.version-close-btn:hover, .version-close-btn:focus-visible { color:var(--text); background:var(--bg-hover); outline:none; }
.version-close-btn .icon-svg { width:16px; height:16px; }
.version-dialog-body { padding:14px 16px 16px; }
.version-stamp { padding:11px 12px; background:rgba(0,0,0,0.18); border:1px solid var(--border); border-radius:6px; }
.version-stamp strong { display:block; margin-top:4px; font-family:monospace; font-size:16px; line-height:1.35; letter-spacing:0; color:var(--text); }
.version-detail-grid { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:10px; }
.version-detail { min-width:0; padding:9px 10px; background:var(--surface); border:1px solid var(--border); border-radius:6px; }
.version-detail strong { display:block; margin-top:3px; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-family:monospace; font-size:12px; font-weight:700; letter-spacing:0; color:var(--text); }

.layout-wrapper { display:flex; flex-direction:column; gap:10px; width:100%; flex:1; min-height:0; }
.io-grid { display:grid; grid-template-columns:minmax(0, 0.66fr) minmax(0, 1.5fr) minmax(0, 0.72fr); gap:10px; width:100%; flex:0.85; min-height:0; }
.panel { background:var(--bg-secondary); border:1px solid var(--border); border-radius:var(--radius); padding:12px; display:flex; flex-direction:column; gap:10px; flex:1; min-height:0; }
.panel-header-row { position:relative; display:flex; justify-content:space-between; align-items:center; flex-shrink:0; }
.canvas-header-row { min-height:28px; }
.panel-header { font-size:13px; font-weight:700; color:var(--text-secondary); text-transform:uppercase; letter-spacing:0.5px; margin:0; flex-shrink:0; }

/* Project name -- the open document's identity, sitting in the header row directly above the
   Properties panel. The 6px offset plus the group's 1px border and 6px padding puts the leading
   document glyph on the same 13px left edge as the PROPERTIES title and the X / Width labels below
   it, so the column reads as one rule. Absolutely positioned like the tool bar, so it adds no
   height to the row. Hidden until a document exists.

   Three classes of thing, told apart by their box rather than by size or brightness, because in
   this app everything pressable lives in a bordered box: the document glyph is bare and never
   reacts to the pointer (a marker), the name is the only bright element (the content), and the
   rename pencil is the only one in a box (the control). */
.project-name { position:absolute; left:6px; top:50%; transform:translateY(-50%); width:calc(var(--properties-panel-w) - 6px); display:flex; align-items:center; gap:3px; min-width:0; }
.project-name[hidden] { display:none; }

/* Identity group: glyph and name are one object, and double-clicking anywhere on it renames. */
.project-name-id { display:flex; align-items:center; gap:6px; min-width:0; flex:0 1 auto; box-sizing:border-box; padding:3px 6px; background:transparent; border:1px solid transparent; border-radius:4px; cursor:default; transition:background 0.15s ease; }
.project-name-id:hover { background:rgba(255,255,255,0.05); }
.project-name-id:focus { outline:none; }
.project-name-id:focus-visible { outline:1px dashed var(--text-secondary); outline-offset:2px; }
/* While renaming, the group takes the whole column so the field is comfortable to type in. */
.project-name.is-renaming .project-name-id { flex:1 1 auto; background:transparent; }
/* Passive marker: no box, no hit target, no hover response -- that, not its colour, is what
   separates it from the button beside it. Its 24-box glyph is narrow and tall, so 15px reads as a
   document rather than a tile, and its 1.5 stroke needs the secondary tone to stay legible at that
   size instead of smudging into the panel. */
.project-name-file { flex:0 0 auto; width:15px; height:15px; color:var(--text-secondary); pointer-events:none; }
.project-name-text { font:600 12px var(--font); color:var(--text); min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.project-name-text[hidden] { display:none; }
.project-name-text.rename-flash { animation:renameFlash 0.45s ease; }
/* Unsaved-changes dot: shown exactly when Save Project is enabled, so it never claims work is
   pending that a click on Save would not write. */
.project-name-dot { flex:0 0 auto; width:5px; height:5px; border-radius:50%; background:var(--accent); }
.project-name-dot[hidden] { display:none; }
/* Rename control. The resting hairline says "pressable" before any hover; approaching the name
   firms it up, and hovering the button itself completes it into the same surface + border treatment
   every tool button uses. Three steps, so the button is found without having to land on it first. */
.project-name-edit { flex:0 0 auto; display:flex; align-items:center; justify-content:center; width:22px; height:22px; padding:0; box-sizing:border-box; background:transparent; border:1px solid rgba(255,255,255,0.08); border-radius:4px; color:var(--text-secondary); cursor:pointer; transition:background 0.15s ease, border-color 0.15s ease, color 0.15s ease; touch-action:manipulation; }
.project-name:hover .project-name-edit { border-color:var(--border); }
.project-name-edit:hover { background:var(--surface); border-color:var(--border-strong); color:var(--text); }
.project-name-edit:active { background:var(--bg-hover); }
.project-name-edit:focus { outline:none; }
.project-name-edit:focus-visible { outline:1px dashed var(--text-secondary); outline-offset:2px; }
.project-name-edit .icon-svg { width:13px; height:13px; }
.project-name.is-renaming .project-name-edit { display:none; }
/* Matches the Layers rename field so renaming feels like one gesture everywhere in the app. */
.project-name-input { font:600 12px var(--font); color:var(--text); background:var(--surface-raised); border:1px solid var(--accent); border-radius:3px; padding:1px 5px; margin:-2px 0; width:100%; min-width:0; outline:none; box-shadow:0 0 0 1px var(--accent), 0 0 0 4px var(--accent-dim); cursor:text; user-select:text; -webkit-user-select:text; }

/* Canvas tool bar -- floats above the canvas, left edge aligned to the canvas left edge
   (properties panel width + 12px preview-container gap). Absolutely positioned so it adds
   no height to the header row and never disturbs the header layout. */
.quick-svg-presets { position:absolute; left:calc(100% - min(var(--right-dock-w), 55vw)); right:0; top:50%; transform:translateY(-50%); height:28px; display:flex; align-items:center; justify-content:center; gap:6px; overflow:hidden; }
.quick-svg-preset { width:34px; height:28px; display:flex; align-items:center; justify-content:center; padding:0; box-sizing:border-box; background:transparent; border:none; border-radius:4px; cursor:pointer; transition:opacity 0.15s ease, transform 0.15s ease; touch-action:manipulation; }
.quick-svg-preset:hover { opacity:0.86; transform:translateY(-1px); }
.quick-svg-preset:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
.quick-svg-preset > svg { display:block; width:28px; height:28px; pointer-events:none; }
.random-svg-btn { margin-left:13px; }
.canvas-toolbar { position:absolute; left:calc(var(--properties-panel-w) + 12px); top:50%; transform:translateY(-50%); display:flex; align-items:center; gap:6px; }
.canvas-toolbar-divider { width:1px; height:18px; margin:0 2px; background:var(--border); flex:0 0 auto; }
.canvas-tool-btn { display:flex; align-items:center; justify-content:center; width:28px; height:28px; padding:0; box-sizing:border-box; background:var(--surface); border:1px solid var(--border-strong); border-radius:4px; color:var(--text-secondary); cursor:pointer; transition:0.15s; touch-action:manipulation; }
.canvas-tool-btn:hover:not(:disabled) { background:var(--bg-hover); color:var(--text); }
.canvas-tool-btn.active { background:var(--accent-dim); border-color:var(--accent); color:var(--accent); }
.canvas-tool-btn:focus { outline:none; }
.canvas-tool-btn:focus-visible { outline:1px dashed var(--text-secondary); outline-offset:2px; }
.canvas-tool-btn:disabled { opacity:0.35; cursor:default; }
.canvas-tool-btn .icon-svg { width:17px; height:17px; }
.canvas-tool-text-btn { width:auto; padding:0 10px; font-family:var(--font); font-size:11px; font-weight:600; }
.left-header-row { min-height:28px; }
.dev-icon-preview-btn { display:flex; align-items:center; justify-content:center; width:28px; height:28px; padding:0; box-sizing:border-box; background:var(--surface); border:1px solid var(--border-strong); border-radius:4px; color:var(--text-secondary); cursor:pointer; transition:0.15s; touch-action:manipulation; }
.dev-icon-preview-btn:hover { background:var(--bg-hover); color:var(--text); }
.dev-icon-preview-btn.active { background:var(--accent-dim); border-color:var(--accent); color:var(--accent); }
.dev-icon-preview-btn:focus { outline:none; }
.dev-icon-preview-btn:focus-visible { outline:1px dashed var(--text-secondary); outline-offset:2px; }
.dev-icon-preview-slot { display:flex; align-items:center; justify-content:center; width:17px; height:17px; overflow:hidden; pointer-events:none; }
.dev-icon-preview-slot > svg { display:block; width:17px !important; height:17px !important; max-width:17px; max-height:17px; flex:0 0 auto; pointer-events:none; }
/* Undo / Redo history bar -- shares the tool bar's header row, right edge aligned to the canvas
   right edge (100% - the .panel-layers width - 12px preview-container gap), keeping it clear of
   both the left-anchored tool buttons and the pen mode bar over the layers panel. */
.history-bar { position:absolute; right:calc(min(var(--right-dock-w), 55vw) + 12px); top:50%; transform:translateY(-50%); display:flex; align-items:center; gap:6px; }
/* Pen tool mode bar -- lives in the app header, centered in the gap between the Snap and
   Info buttons. Visible only while the Pen tool is active; Draw / Add / Minus switch the
   pen between drawing, add-anchor, and delete-anchor. */
.pen-mode-bar { flex:1 1 auto; min-width:0; display:flex; align-items:center; justify-content:center; gap:4px; }
.pen-mode-bar[hidden] { display:none; }
.pen-mode-btn { display:flex; align-items:center; justify-content:center; height:28px; padding:0 10px; box-sizing:border-box; background:var(--surface); border:1px solid var(--border-strong); border-radius:4px; color:var(--text-secondary); font-family:var(--font); font-size:11px; font-weight:600; cursor:pointer; transition:0.15s; touch-action:manipulation; }
.pen-mode-btn:hover { background:var(--bg-hover); color:var(--text); }
.pen-mode-btn.active { background:var(--accent-dim); border-color:var(--accent); color:var(--accent); }
.opt-btn { background:var(--surface); color:var(--text-secondary); border:1px solid var(--border-strong); border-radius:4px; padding:5px 10px; font-size:11px; font-weight:600; cursor:pointer; transition:0.15s; text-align:center; display:inline-flex; align-items:center; justify-content:center; gap:4px; box-sizing:border-box; touch-action:manipulation; }
.opt-btn:hover { background:var(--bg-hover); color:var(--text); }
.opt-btn.active { background:var(--accent-dim); border-color:var(--accent); color:var(--accent); }
#btnCopyExport > span, #btnCopyPng > span { flex:1; text-align:left; white-space:nowrap; }
#btnCopyExport .copy-check-icon, #btnCopyPng .copy-check-icon { display:none; }
#btnCopyExport.btn-success .copy-check-icon, #btnCopyPng.btn-success .copy-check-icon { display:inline-block; }

.icon-svg { width:18px; height:18px; display:inline-block; flex-shrink:0; pointer-events:none; fill:currentColor; stroke:none; }
.controls { display:flex; gap:8px; align-items:center; flex-shrink:0; }

/* Condensed-mode one-line import field: collapsed to zero width until the I/O panels merge
   to a single row (.io-condensed, desktop media block), where it grows in between Paste and
   Clear. The -8px margin swallows its flex gap while collapsed. */
.import-mini-input { flex:0 1 0px; min-width:0; align-self:stretch; padding:0; margin-right:-8px; box-sizing:border-box; background:var(--surface); color:var(--text); border:1px solid transparent; border-radius:4px; font-family:monospace; font-size:11px; opacity:0; visibility:hidden; pointer-events:none; outline:none; }
/* Clear sits inline in the Code toolbar; when condensed the mini field's flex-grow owns the
   space between Paste and Clear. */
.import-clear-btn { margin-left:0; }

.textarea-wrap { position:relative; flex:1; min-height:0; display:flex; width:100%; border-radius:4px; }

textarea { 
  width:100%; flex:1; min-height:0; background:var(--surface); color:var(--text); border:1px solid var(--border); 
  border-radius:4px; padding:10px; font-family:monospace; font-size:12px; resize:none; 
  box-sizing:border-box; user-select:text; -webkit-user-select:text; touch-action:pan-y !important; 
  overscroll-behavior-y:contain; scroll-behavior:auto; will-change:scroll-position; outline:none; transition:border-color 0.2s, box-shadow 0.2s; 
  -ms-overflow-style:none; scrollbar-width:none; 
}
textarea::-webkit-scrollbar { display:none; width:0; height:0; }
textarea:focus { border-color:var(--border-strong); }

.preview-container { display:flex; gap:12px; width:100%; flex:1; min-height:0; }
.preview-box { flex:1; min-width:0; position:relative; overflow:hidden; overflow:clip; background:repeating-conic-gradient(#2a2a2e 0% 25%, #222226 0% 50%) 0 0/20px 20px; border:1px solid var(--border); border-radius:4px; display:flex; align-items:center; justify-content:center; color:var(--text-secondary); }
/* The artboard box is a screen-space overlay, not part of the zoomed SVG. JS projects
   the transformed SVG viewport into this absolute node, while the 2px CSS border stays
   in screen pixels and is offset so its centerline sits on the artboard edge. */
.artboard-overlay { position:absolute; z-index:2; box-sizing:border-box; border:2px solid #000; border-radius:0; background:transparent; pointer-events:none; }
.artboard-overlay[hidden] { display:none; }
.artboard-overlay.artboard-tool-active { z-index:4; border-color:var(--accent); box-shadow:0 0 0 1px rgba(0,0,0,0.65), 0 0 0 2px rgba(0,122,255,0.22); }
/* Active artboard tool: the frame interior catches pointerdown to reposition (move) the artboard;
   the handles (painted on top, own pointer-events) win at the edges/corners. */
.artboard-overlay.artboard-tool-active { pointer-events:auto; cursor:move; }
.artboard-handle { position:absolute; width:28px; height:8px; box-sizing:border-box; background:#fff; border:1.5px solid var(--accent); border-radius:2px; pointer-events:auto; touch-action:none; box-shadow:0 1px 4px rgba(0,0,0,0.55); }
.artboard-handle-n, .artboard-handle-s { left:50%; transform:translate(-50%, -50%); cursor:ns-resize; }
.artboard-handle-e, .artboard-handle-w { top:50%; width:8px; height:28px; transform:translate(-50%, -50%); cursor:ew-resize; }
.artboard-handle-n { top:0; }
.artboard-handle-e { left:100%; }
.artboard-handle-s { top:100%; }
.artboard-handle-w { left:0; }
/* Corner nubs: square, centred on each corner; diagonal resize cursors. */
.artboard-handle-nw, .artboard-handle-ne, .artboard-handle-se, .artboard-handle-sw { width:12px; height:12px; transform:translate(-50%, -50%); }
.artboard-handle-nw { top:0; left:0; cursor:nwse-resize; }
.artboard-handle-ne { top:0; left:100%; cursor:nesw-resize; }
.artboard-handle-se { top:100%; left:100%; cursor:nwse-resize; }
.artboard-handle-sw { top:100%; left:0; cursor:nesw-resize; }
.canvas-overlay { position:absolute; inset:0; z-index:3; display:block; width:100%; height:100%; overflow:hidden; pointer-events:none; }
.canvas-overlay[hidden] { display:none; }
.preview-box > svg:not(.icon-svg):not(.canvas-overlay) { color:var(--text-secondary); flex-shrink:0; background:rgba(0,0,0,0.15); overflow:visible; transform-origin:center center; }
.ruler-corner { position:absolute; top:0; left:0; width:var(--ruler-size); height:var(--ruler-size); z-index:13; box-sizing:border-box; background:var(--ruler-bg); border-right:1px solid var(--border); border-bottom:1px solid var(--border); pointer-events:auto; cursor:default !important; }
.ruler-corner[hidden] { display:none; }
.canvas-ruler { position:absolute; z-index:12; display:block; background:var(--ruler-bg); pointer-events:auto; touch-action:none; cursor:default !important; }
.canvas-ruler[hidden] { display:none; }
.canvas-ruler-h { top:0; left:var(--ruler-size); width:calc(100% - var(--ruler-size)); height:var(--ruler-size); border-bottom:1px solid var(--border); }
.canvas-ruler-v { top:var(--ruler-size); left:0; width:var(--ruler-size); height:calc(100% - var(--ruler-size)); border-right:1px solid var(--border); }
.guide-overlay { position:absolute; inset:0; z-index:8; display:block; width:100%; height:100%; overflow:hidden; pointer-events:none; }
.guide-overlay[hidden] { display:none; }
.preview-box.guide-hover-v, .preview-box.guide-hover-v * { cursor:ew-resize !important; }
.preview-box.guide-hover-h, .preview-box.guide-hover-h * { cursor:ns-resize !important; }

/* Hand tool active: left-drag pans the canvas; middle-drag temporarily uses this tool. */
.preview-box.hand-active, .preview-box.hand-active * { cursor:grab; }
.preview-box.hand-active .canvas-statusbar, .preview-box.hand-active .canvas-statusbar * { cursor:default; }
.preview-box.hand-active .canvas-statusbar button, .preview-box.hand-active .canvas-statusbar button * { cursor:pointer; }

/* Space held: temporary hand-pan armed from any tool (js/hand-tool.js). !important outranks the
   injected custom-cursor rules of whichever tool is active; the status bar keeps its cursors. */
.preview-box.space-pan, .preview-box.space-pan * { cursor:grab !important; }
.preview-box.space-pan .canvas-statusbar, .preview-box.space-pan .canvas-statusbar * { cursor:default !important; }
.preview-box.space-pan .canvas-statusbar button, .preview-box.space-pan .canvas-statusbar button * { cursor:pointer !important; }

/* Shape tools active (Rectangle / Ellipse / Line): click-drag draws a new shape. */
.preview-box.shape-active, .preview-box.shape-active * { cursor:crosshair; }

/* Type tool active: I-beam for placing/editing text; the status bar keeps its cursors. */
.preview-box.text-active, .preview-box.text-active * { cursor:text; }
.preview-box.text-active .canvas-statusbar, .preview-box.text-active .canvas-statusbar * { cursor:default; }
.preview-box.text-active .canvas-statusbar button, .preview-box.text-active .canvas-statusbar button * { cursor:pointer; }

/* Blob Brush / Eraser active: crosshair under the live size-circle overlay ring. */
.preview-box.blob-active, .preview-box.blob-active *, .preview-box.eraser-active, .preview-box.eraser-active * { cursor:crosshair; }

/* Direct Selection chrome: anchor squares + Bezier handle hit circles are the interactive
   bits above the otherwise click-through overlay. Anchors enlarge slightly on hover (Illustrator). */
.dsel-anchor { pointer-events:all; transform-box:fill-box; transform-origin:center; }
.preview-box.dsel-active .dsel-anchor:hover { transform:scale(1.33); }
.dsel-handle-hit { pointer-events:all; }

/* Selection bounding-box handles: interactive (the overlay itself is pointer-events:none) + Illustrator resize cursors. */
.sel-handle { pointer-events:all; }
.preview-box.sel-active .sel-handle-nwse, .preview-box.shape-active .sel-handle-nwse { cursor:nwse-resize; }
.preview-box.sel-active .sel-handle-nesw, .preview-box.shape-active .sel-handle-nesw { cursor:nesw-resize; }
.preview-box.sel-active .sel-handle-ns, .preview-box.shape-active .sel-handle-ns { cursor:ns-resize; }
.preview-box.sel-active .sel-handle-ew, .preview-box.shape-active .sel-handle-ew { cursor:ew-resize; }

/* Text-object transform chrome (Type / Selection / Direct Selection): a distinct blue box that
   reads unmistakably as text, not the green shape box. Geometry is set on the SVG nodes in JS;
   only the look lives here. Box = translucent blue fill + solid border; hover = dashed outline;
   corners = blue L-brackets; edges = white pills with a blue outline (like the square handles,
   rounded). */
.sel-text-box { fill:rgba(30,155,255,0.12); stroke:#1E9BFF; }
.sel-text-hover { fill:none; stroke:#1E9BFF; stroke-dasharray:4 3; }
.sel-text-bracket { fill:none; stroke:#1E9BFF; stroke-linecap:round; stroke-linejoin:round; }
.sel-text-pill { fill:#ffffff; stroke:#1E9BFF; }
.sel-text-hit { fill:transparent; }
/* The text handles carry the same resize cursors under every tool that shows the text box. */
.preview-box.text-active .sel-handle-nwse, .preview-box.dsel-active .sel-handle-nwse { cursor:nwse-resize; }
.preview-box.text-active .sel-handle-nesw, .preview-box.dsel-active .sel-handle-nesw { cursor:nesw-resize; }
.preview-box.text-active .sel-handle-ns, .preview-box.dsel-active .sel-handle-ns { cursor:ns-resize; }
.preview-box.text-active .sel-handle-ew, .preview-box.dsel-active .sel-handle-ew { cursor:ew-resize; }

/* While actively dragging a handle, the pointer is captured -- lock the matching resize cursor everywhere. */
body.sel-cur-nwse, body.sel-cur-nwse * { cursor:nwse-resize !important; }
body.sel-cur-nesw, body.sel-cur-nesw * { cursor:nesw-resize !important; }
body.sel-cur-ns, body.sel-cur-ns * { cursor:ns-resize !important; }
body.sel-cur-ew, body.sel-cur-ew * { cursor:ew-resize !important; }
body.ab-cur-ns, body.ab-cur-ns * { cursor:ns-resize !important; }
body.ab-cur-ew, body.ab-cur-ew * { cursor:ew-resize !important; }
body.ab-cur-nwse, body.ab-cur-nwse * { cursor:nwse-resize !important; }
body.ab-cur-nesw, body.ab-cur-nesw * { cursor:nesw-resize !important; }
body.ab-cur-move, body.ab-cur-move * { cursor:move !important; }

/* Canvas status bar -- thin frosted ledge across the bottom of the preview */
/* Save confirmation. Canvas chrome in the status-bar idiom, pinned to the top-left of the
   Canvas and pushed clear of the rulers whenever they are shown. The 2px rule depletes across
   the dwell so the toast reads as deliberately temporary. Keep the 2200ms below in step with
   SAVE_TOAST_MS in js/project-file.js. */
.canvas-toast { position:absolute; top:10px; left:10px; z-index:15; display:flex; align-items:center; gap:7px; padding:7px 12px 8px; box-sizing:border-box; overflow:hidden; color:var(--text); background:rgba(26,26,30,0.72); backdrop-filter:blur(12px) saturate(1.2); -webkit-backdrop-filter:blur(12px) saturate(1.2); border:1px solid var(--border); border-radius:7px; box-shadow:0 10px 26px rgba(0,0,0,0.42); font:600 12px var(--font); letter-spacing:0.2px; white-space:nowrap; pointer-events:none; opacity:0; transform:translateY(-6px); transition:opacity 0.3s ease, transform 0.3s ease; }
.canvas-toast[hidden] { display:none; }
.canvas-toast.is-shown { opacity:1; transform:translateY(0); transition:opacity 0.24s cubic-bezier(0.2, 0.8, 0.2, 1), transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1); }
.canvas-ruler-h:not([hidden]) ~ .canvas-toast { top:calc(var(--ruler-size) + 10px); left:calc(var(--ruler-size) + 10px); }
.canvas-toast .canvas-toast-icon { width:13px; height:13px; color:var(--success); }
.canvas-toast-timer { position:absolute; left:0; bottom:0; width:100%; height:2px; background:var(--success); opacity:0.5; transform-origin:left center; transform:scaleX(0); }
.canvas-toast.is-shown .canvas-toast-timer { animation:canvas-toast-timer 2200ms linear forwards; }
@keyframes canvas-toast-timer { from { transform:scaleX(1); } to { transform:scaleX(0); } }

.canvas-statusbar { position:absolute; left:0; right:0; bottom:0; height:26px; display:flex; align-items:center; z-index:14; background:rgba(26,26,30,0.72); backdrop-filter:blur(12px) saturate(1.2); -webkit-backdrop-filter:blur(12px) saturate(1.2); border-top:1px solid var(--border); animation:cs-rise 0.28s cubic-bezier(0.2, 0.8, 0.2, 1); }
.canvas-statusbar[hidden] { display:none; }
.cs-cluster { display:flex; align-items:center; gap:2px; padding-left:8px; }
.cs-artboard-dims { min-width:82px; padding:0 8px 0 0; color:var(--text-secondary); font:600 11px var(--font); font-variant-numeric:tabular-nums; white-space:nowrap; }
.cs-cursor-position { width:124px; flex:0 0 124px; box-sizing:border-box; overflow:hidden; padding:0 4px; color:var(--text-secondary); font:600 11px var(--font); font-variant-numeric:tabular-nums; white-space:pre; }
.cs-btn { width:22px; height:22px; display:flex; align-items:center; justify-content:center; padding:0; border:none; background:transparent; color:var(--text-secondary); border-radius:5px; cursor:pointer; transition:0.15s; touch-action:manipulation; }
.cs-btn:hover { background:var(--bg-hover); color:var(--text); }
.cs-btn .icon-svg { width:14px; height:14px; }
.cs-zoom { min-width:52px; text-align:center; font:600 11px var(--font); font-variant-numeric:tabular-nums; color:var(--text); background:transparent; border:none; border-radius:5px; padding:3px 6px; cursor:pointer; transition:0.15s; touch-action:manipulation; }
.cs-zoom:hover { background:var(--bg-hover); }
.cs-zoom-input { width:52px; box-sizing:border-box; text-align:center; font:600 11px var(--font); font-variant-numeric:tabular-nums; color:var(--text); background:var(--surface); border:1px solid var(--accent); border-radius:5px; padding:3px 4px; outline:none; box-shadow:0 0 0 2px var(--accent-dim); user-select:text; -webkit-user-select:text; }
.cs-divider { width:1px; height:16px; background:var(--border); margin:0 4px; }
.cs-snap-label { margin-left:auto; padding:0 10px; color:var(--snap-guide); font:600 11px var(--font); letter-spacing:0.3px; white-space:nowrap; }
.cs-snap-label[hidden] { display:none; }
.snap-overlay { z-index:9; }
@keyframes cs-rise { from { opacity:0; transform:translateY(100%); } to { opacity:1; transform:translateY(0); } }
@media (prefers-reduced-motion: reduce) {
  /* The spinner stays: it reports progress rather than decorating it. */
  .canvas-toast, .canvas-toast.is-shown { transform:none; transition:opacity 0.2s linear; }
  .canvas-toast.is-shown .canvas-toast-timer { animation:none; }
  .canvas-statusbar { animation:none; }
  .artboard-overlay { transition:none !important; }
  .preview-box > svg:not(.icon-svg):not(.canvas-overlay) { transition:none !important; }
}

.side-panel { background:var(--surface); border:1px solid var(--border); border-radius:4px; padding:12px; display:flex; flex-direction:column; gap:8px; box-sizing:border-box; min-height:0; }
.panel-properties { width:var(--properties-panel-w); flex-shrink:0; }

/* Right dock: the Stroke + Fill Panel stacked above the Layers panel in one fixed-width
   column right of the canvas. The dock owns the width the layers panel used to have;
   Stroke + Fill hugs its content and Layers flexes to fill the rest. */
.right-dock { display:flex; flex-direction:column; gap:12px; flex:0 0 var(--right-dock-w); width:var(--right-dock-w); max-width:55vw; min-width:0; min-height:0; }
.panel-paint { flex:0 0 auto; }
.panel-layers { position:relative; flex:1; min-height:0; }
.layers-size-toggle { appearance:none; display:flex; align-items:center; justify-content:center; width:24px; height:24px; padding:0; border:none; border-radius:6px; background:transparent; color:var(--text-secondary); cursor:pointer; transition:color 0.15s ease; touch-action:manipulation; -webkit-tap-highlight-color:transparent; }
.layers-size-toggle:hover { background:transparent; color:var(--text); }
.layers-size-toggle:focus-visible { color:var(--text); background:transparent; outline:none; box-shadow:0 0 0 2px rgba(255,255,255,0.16); }
.layers-size-toggle .icon-svg { width:18px; height:18px; }
/* The glyph is swapped wholesale on every density change, so a fresh node always carries the class:
   it fades up instead of hard-cutting while the stack behind it resizes. */
.layers-size-toggle .icon-svg.is-swapped { animation:lpSizeIconIn 0.24s cubic-bezier(0.2, 0.8, 0.2, 1); }
/* Stroke + Fill preset-mode toggle (RGB / Custom). Word icons are 24px tall with variable
   width, so the icon keeps its aspect (width:auto) and the button hugs it, right-aligned. */
.ap-preset-toggle { appearance:none; display:flex; align-items:center; justify-content:center; height:18px; padding:0 2px; border:none; border-radius:6px; background:transparent; color:var(--text-secondary); cursor:pointer; transition:color 0.15s ease; touch-action:manipulation; -webkit-tap-highlight-color:transparent; flex-shrink:0; }
.ap-preset-toggle:hover { color:var(--text); }
.ap-preset-toggle:focus-visible { color:var(--text); outline:none; box-shadow:0 0 0 2px rgba(255,255,255,0.16); }
.ap-preset-toggle .icon-svg { width:auto; height:16px; }
.panel-paint .panel-title { white-space:nowrap; }   /* keep "Stroke + fill" on one row beside the toggle */
@keyframes lpSizeIconIn { from { opacity:0; transform:scale(0.82); } to { opacity:1; transform:scale(1); } }

/* Stroke + Fill rows share one column grid (label | swatch | none | hex | presets) so the
   Fill and Stroke controls align as a single instrument strip; the Weight row hangs its
   field from the swatch column, per the layout sketch. */
.ap-rows { display:flex; flex-direction:column; gap:8px; padding-top:2px; }
.ap-row { display:grid; grid-template-columns:44px 26px 18px auto auto; align-items:center; column-gap:8px; }
.ap-label { font-size:10px; font-weight:600; color:var(--text-secondary); text-transform:uppercase; letter-spacing:0.5px; -webkit-user-select:none; user-select:none; }
.ap-hex { justify-self:start; width:64px; }
.ap-weight-row .ap-weight-mount { grid-column:2 / 6; display:flex; align-items:center; }

/* Weight slider: one track, two fill logics. Fixed fills from the left edge (position in an
   absolute 0..artboard range); percent fills outward from the centre detent (distance from
   neutral). --ws-a/--ws-b are the fill's percentage ends and --ws-pos is the cap centre, all
   written from js/layers.js as one style pass per frame. clamp() keeps the 7px cap fully inside
   the groove without relying on typed multiplication inside calc(). */
.ap-weight-slider { position:relative; flex:1; min-width:0; height:24px; margin-left:8px; cursor:pointer; touch-action:none; -webkit-user-select:none; user-select:none; --ws-pos:0%; --ws-a:0%; --ws-b:0%; }
.ap-weight-slider:focus { outline:none; }
.ap-ws-groove { position:absolute; left:0; right:0; top:50%; height:4px; margin-top:-2px; border-radius:2px; background:var(--bg-secondary); box-shadow:inset 0 1px 2px rgba(0,0,0,0.55), inset 0 0 0 1px rgba(0,0,0,0.28), 0 1px 0 rgba(255,255,255,0.045); }
.ap-ws-fill { position:absolute; top:0; bottom:0; left:clamp(3.5px, var(--ws-a), calc(100% - 3.5px)); right:clamp(3.5px, calc(100% - var(--ws-b)), calc(100% - 3.5px)); border-radius:2px; background:var(--text-secondary); transition:background 0.15s ease; }
.ap-ws-detent { position:absolute; left:50%; top:-3px; bottom:-3px; width:1px; background:rgba(255,255,255,0.2); }
/* The cap reads as a milled fader head: vertical pill, top light rim, single centre groove. That
   groove sits exactly on .ap-ws-detent at neutral, marking the no-change centre. */
.ap-ws-cap { position:absolute; top:50%; left:clamp(3.5px, var(--ws-pos), calc(100% - 3.5px)); width:7px; height:15px; margin:-7.5px 0 0 -3.5px; box-sizing:border-box; border:1px solid rgba(255,255,255,0.16); border-radius:3px; background:linear-gradient(180deg, #4a4a52 0%, #3a3a42 52%, #313138 100%); box-shadow:0 1px 2px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.12); transition:border-color 0.15s ease; }
.ap-ws-cap::after { content:''; position:absolute; left:50%; top:3px; bottom:3px; width:1px; margin-left:-0.5px; background:rgba(0,0,0,0.5); box-shadow:1px 0 0 rgba(255,255,255,0.07); }
.ap-weight-slider:hover .ap-ws-fill, .ap-weight-slider.is-dragging .ap-ws-fill { background:var(--text); }
.ap-weight-slider:hover .ap-ws-cap, .ap-weight-slider.is-dragging .ap-ws-cap { border-color:rgba(255,255,255,0.28); }
.ap-weight-slider:focus-visible .ap-ws-cap { border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-dim), 0 1px 2px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.12); }
.ap-weight-slider.is-springing .ap-ws-cap { transition:left 0.19s cubic-bezier(0.22, 1, 0.36, 1); }
.ap-weight-slider.is-springing .ap-ws-fill { transition:left 0.19s cubic-bezier(0.22, 1, 0.36, 1), right 0.19s cubic-bezier(0.22, 1, 0.36, 1); }
/* Compact linked no-color icon, visually grouped with the color launch swatch. */
.ap-none-btn { width:18px; height:26px; box-sizing:border-box; margin-left:-4px; padding:0; display:flex; align-items:center; justify-content:center; background:transparent; border:none; cursor:pointer; opacity:0.65; transition:opacity 0.15s ease; touch-action:manipulation; -webkit-tap-highlight-color:transparent; }
.ap-none-btn .icon-svg { width:12px; height:12px; display:block; }
.ap-none-btn:hover { opacity:1; }
.ap-none-btn:focus, .ap-none-btn:focus-visible { outline:none; }
/* Swatch paint states the Stroke + Fill Panel adds to .picker-wrap: none (white + red slash)
   and mixed (multi-selection values differ -> '?'). */
.picker-wrap.lp-none::before { content:''; position:absolute; inset:2px; background:#fff; }
.picker-wrap-stroke.lp-none::before { background:transparent; border:4px solid #fff; box-sizing:border-box; }
.picker-wrap.lp-none::after { content:''; position:absolute; inset:2px; background:linear-gradient(to top right, transparent calc(50% - 1px), #ff3b30 calc(50% - 1px), #ff3b30 calc(50% + 1px), transparent calc(50% + 1px)); }
.picker-wrap.lp-mixed::before { content:'?'; font:700 13px var(--font); color:var(--text-secondary); }
/* No document loaded (is-disabled), or a selection with nothing paintable in it --
   raster layers only (is-inert): the Stroke + Fill Panel body greys out. */
.panel-paint.is-disabled .ap-rows, .ap-rows.is-inert { opacity:0.45; pointer-events:none; }

.panel-header-flex { box-sizing:border-box; height:var(--panel-header-h); display:flex; justify-content:space-between; align-items:center; gap:8px; border-bottom:1px solid var(--border); padding-bottom:6px; margin-bottom:4px; flex-shrink:0; }
.panel-title { margin:0; font-size:11px; color:var(--text-secondary); text-transform:uppercase; letter-spacing:0.5px; font-weight:700; }
.panel-properties .panel-title { box-sizing:border-box; height:var(--panel-header-h); position:relative; border-bottom:1px solid var(--border); padding:0 0 6px 0; margin-bottom:4px; display:flex; justify-content:space-between; align-items:center; flex-shrink:0; }

/* Properties readout: compact geometry controls with true input boxes. Width/Height share
   the top row with the constrain link between them; X/Y sit below with inline labels. */
.props-empty { margin:2px 0 0; font-size:11px; line-height:1.5; color:var(--text-secondary); text-align:center; }
.props-empty[hidden] { display:none; }
.props-grid { display:grid; grid-template-columns:12px minmax(0, 1fr) 20px 12px minmax(0, 1fr); align-items:center; column-gap:5px; row-gap:7px;
  grid-template-areas:"wl wl . hl hl" "wf wf lk hf hf" "xl xf . yl yf" "so so so so rp" "tr tr tr tr tr" "al al al al al" "pf pf pf pf pf" "sk sk sk sk sk"; }
.props-grid[hidden] { display:none; }
.props-grid > *:nth-child(1) { grid-area:xl; } .props-grid > *:nth-child(2) { grid-area:xf; }
.props-grid > *:nth-child(3) { grid-area:yl; } .props-grid > *:nth-child(4) { grid-area:yf; }
.props-grid > *:nth-child(5) { grid-area:wl; } .props-grid > *:nth-child(6) { grid-area:wf; }
.props-grid > *:nth-child(7) { grid-area:hl; } .props-grid > *:nth-child(8) { grid-area:hf; }
.props-grid > *:nth-child(9) { grid-area:lk; }
.props-grid > *:nth-child(10) { grid-area:so; }
.props-grid > *:nth-child(11) { grid-area:tr; }
.props-grid > *:nth-child(12) { grid-area:al; }
.props-grid > *:nth-child(13) { grid-area:pf; }
.props-grid > *:nth-child(14) { grid-area:sk; }
.props-grid > *:nth-child(15) { grid-area:rp; }
.props-grid > *:nth-child(1), .props-grid > *:nth-child(2), .props-grid > *:nth-child(3), .props-grid > *:nth-child(4) { margin-top:3px; }
.prop-label { font-size:10px; line-height:1; font-weight:700; color:var(--text-secondary); cursor:ew-resize; touch-action:none; -webkit-user-select:none; user-select:none; transition:color 0.12s; }
.props-grid > .prop-label:nth-child(1), .props-grid > .prop-label:nth-child(3) { align-self:center; justify-self:start; font-size:12px; color:var(--text-secondary); }
.props-grid > .prop-label:nth-child(5), .props-grid > .prop-label:nth-child(7) { align-self:end; justify-self:start; padding-left:2px; }
.prop-label:hover { color:var(--text); }
.props-grid.is-empty .prop-label { color:var(--text-tertiary); cursor:default; }
.props-grid.is-empty .prop-label:hover { color:var(--text-tertiary); }
/* Anchor mode (Direct Selection): X/Y edit the selected anchor point; W/H and transforms grey out. */
.props-grid.is-anchor .prop-label[for="propWidth"], .props-grid.is-anchor .prop-label[for="propHeight"] { color:var(--text-tertiary); cursor:default; }
.props-grid.is-anchor .prop-label[for="propWidth"]:hover, .props-grid.is-anchor .prop-label[for="propHeight"]:hover { color:var(--text-tertiary); }
.props-grid.is-guide .prop-label { color:var(--text-tertiary); cursor:default; }
.props-grid.is-guide .prop-label:hover { color:var(--text-tertiary); }
.props-grid.is-guide.is-guide-v .prop-label[for="propX"], .props-grid.is-guide.is-guide-h .prop-label[for="propY"] { color:var(--text-secondary); cursor:ew-resize; }
.props-grid.is-guide.is-guide-v .prop-label[for="propX"]:hover, .props-grid.is-guide.is-guide-h .prop-label[for="propY"]:hover { color:var(--text); }
.prop-field { height:24px; display:flex; align-items:center; justify-content:flex-end; gap:4px; min-width:0; box-sizing:border-box; padding:0 6px; background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; box-shadow:inset 0 1px 0 rgba(255,255,255,0.04); transition:background 0.12s, border-color 0.12s, box-shadow 0.12s, opacity 0.12s; }
.prop-field:hover { background:var(--bg-secondary); border-color:rgba(255,255,255,0.22); }
.prop-field:focus-within { background:var(--bg-secondary); border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-dim), inset 0 1px 0 rgba(255,255,255,0.05); }
.props-grid.is-empty .prop-field { opacity:0.55; background:rgba(255,255,255,0.035); border-color:var(--border); }
.props-grid.is-anchor > *:nth-child(6), .props-grid.is-anchor > *:nth-child(8) { opacity:0.55; background:rgba(255,255,255,0.035); border-color:var(--border); }
.props-grid.is-guide > *:nth-child(2), .props-grid.is-guide > *:nth-child(4), .props-grid.is-guide > *:nth-child(6), .props-grid.is-guide > *:nth-child(8) { opacity:0.55; background:rgba(255,255,255,0.035); border-color:var(--border); }
.props-grid.is-guide.is-guide-v > *:nth-child(2), .props-grid.is-guide.is-guide-h > *:nth-child(4) { opacity:1; background:var(--surface-raised); border-color:var(--border-strong); }
.prop-value { flex:1 1 auto; width:100%; height:100%; min-width:0; box-sizing:border-box; text-align:right; font-family:monospace; font-size:11.5px; font-weight:600; font-variant-numeric:tabular-nums; color:var(--text); background:transparent; border:none; padding:0; outline:none; cursor:text; -webkit-user-select:text; user-select:text; }
.prop-value:focus { outline:none; }
.prop-value:disabled { color:var(--text-secondary); cursor:default; -webkit-user-select:none; user-select:none; }
.props-grid.is-empty .prop-value:disabled { color:var(--text-tertiary); }
.prop-unit { flex:none; font-size:10px; color:var(--text-tertiary); }
.props-link { align-self:end; justify-self:center; width:20px; height:24px; display:flex; align-items:center; justify-content:center; padding:0; color:var(--text-secondary); background:transparent; border:1px solid transparent; border-radius:4px; box-shadow:none; cursor:pointer; transition:0.15s; }
.props-link:hover:not(:disabled) { background:transparent; color:var(--text); }
.props-link.active { color:var(--accent); background:var(--accent-dim); border-color:rgba(0,122,255,0.38); box-shadow:0 0 0 1px rgba(0,122,255,0.18); }
.props-grid.is-empty .props-link.active { color:var(--text-tertiary); background:transparent; border-color:transparent; box-shadow:none; }
.props-grid.is-anchor .props-link.active { color:var(--text-tertiary); background:transparent; border-color:transparent; box-shadow:none; }
.props-grid.is-guide .props-link.active { color:var(--text-tertiary); background:transparent; border-color:transparent; box-shadow:none; }
.props-link:disabled { opacity:0.4; cursor:default; }
.props-link .icon-svg { width:14px; height:14px; }
/* Illustrator-style scale options under Height. Global modes, so they stay enabled in the empty state. */
.props-scale-opts { display:flex; flex-direction:column; gap:5px; padding-top:5px; align-self:start; justify-self:start; }
.props-scale-opts.is-disabled { opacity:0.38; pointer-events:none; }
/* "Scale contents with artboard": only relevant to the Artboard tool, so it appears solely in
   artboard mode. The extra .props-grid specificity beats the later `.cb-label { display:flex }`. */
.props-grid .props-ab-only { display:none; }
.props-grid.is-artboard .props-ab-only { display:flex; }
/* In artboard mode, Scale strokes/effects + Scale corners only matter when Scale contents is on;
   otherwise they're unnecessary, so grey them out (the Scale-contents checkbox itself stays live). */
.props-scale-opts.contents-locked .cb-label:not(.props-ab-only) { opacity:0.38; pointer-events:none; }
/* Illustrator-style 9-point reference grid: pick the anchor for X/Y, scale, rotate, and flip. Global mode, enabled with no selection. */
.props-refpoint { position:relative; display:grid; grid-template-columns:repeat(3, 1fr); grid-template-rows:repeat(3, 1fr); width:44px; height:44px; box-sizing:border-box; align-self:center; justify-self:center; }
.props-refpoint::before { content:''; position:absolute; left:50%; top:50%; width:29px; height:29px; transform:translate(-50%, -50%); border:1px solid var(--border-strong); box-sizing:border-box; pointer-events:none; }
.props-refpoint::after { content:''; position:absolute; left:50%; top:50%; width:29px; height:29px; transform:translate(-50%, -50%); pointer-events:none;
  background:linear-gradient(var(--border-strong), var(--border-strong)) center/1px 100% no-repeat, linear-gradient(var(--border-strong), var(--border-strong)) center/100% 1px no-repeat; }
.props-rp-dot { position:relative; z-index:1; display:flex; align-items:center; justify-content:center; padding:0; background:transparent; border:none; cursor:pointer; -webkit-appearance:none; appearance:none; touch-action:manipulation; }
.props-rp-dot::before { content:''; width:5px; height:5px; border-radius:1px; background:var(--surface); box-shadow:0 0 0 1px var(--text-tertiary); transition:background 0.12s, box-shadow 0.12s, width 0.12s, height 0.12s; }
.props-rp-dot:hover::before { box-shadow:0 0 0 1px var(--text); }
.props-rp-dot.active::before { width:7px; height:7px; background:var(--accent); box-shadow:0 0 0 1px var(--accent); }
.props-refpoint.is-disabled { opacity:0.38; pointer-events:none; }
.props-transform { width:100%; display:grid; grid-template-columns:1fr 1fr; align-items:center; align-self:stretch; justify-self:start; padding-top:3px; }
.props-flip-group { display:grid; grid-template-columns:repeat(2, 32px); gap:5px; justify-self:center; }
.props-align { width:100%; display:flex; align-items:center; gap:2px; padding-top:8px; margin-top:2px; border-top:1px solid var(--border); align-self:stretch; justify-self:start; }
.props-align-btn { flex:1 1 0; }
.props-align-divider { flex:0 0 auto; align-self:center; width:1px; height:18px; margin:0 5px; background:var(--border-strong); }
/* Pathfinder row (four shape modes + Stroke Outline / Compound Path): sits under the align row
   behind the same horizontal-rule treatment. */
.props-pathfinder { width:100%; display:flex; flex-wrap:wrap; align-items:center; gap:2px; padding-top:8px; margin-top:2px; border-top:1px solid var(--border); align-self:stretch; justify-self:start; }
.props-pf-btn { flex:1 0 calc(25% - 1.5px); }
.props-path-action-btn { flex:1 0 calc(50% - 1px); min-width:0; height:26px; margin-top:3px; padding:0 5px; box-sizing:border-box; color:var(--text-secondary); background:var(--surface-raised); border:1px solid var(--border); border-radius:4px; font:600 9.5px var(--font); letter-spacing:0.1px; white-space:nowrap; cursor:pointer; transition:background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s; touch-action:manipulation; }
.props-path-action-btn:hover:not(:disabled) { color:var(--text); background:var(--bg-hover); border-color:var(--border-strong); }
.props-path-action-btn:focus-visible { outline:none; border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-dim); }
.props-path-action-btn:active:not(:disabled) { color:var(--accent); background:var(--accent-dim); border-color:rgba(0,122,255,0.38); }
.props-path-action-btn:disabled { opacity:0.38; cursor:default; }
.props-grid.is-empty .props-path-action-btn:disabled { color:var(--text-tertiary); }
.props-align-btn, .props-transform-btn, .props-pf-btn, .props-stroke-btn { height:28px; min-width:0; display:flex; align-items:center; justify-content:center; padding:0; color:var(--text-secondary); background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; cursor:pointer; transition:background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s; touch-action:manipulation; }
.props-align-btn:hover:not(:disabled), .props-transform-btn:hover:not(:disabled), .props-pf-btn:hover:not(:disabled), .props-stroke-btn:hover:not(:disabled) { color:var(--text); background:var(--bg-hover); border-color:rgba(255,255,255,0.22); }
.props-align-btn:focus-visible, .props-transform-btn:focus-visible, .props-pf-btn:focus-visible, .props-stroke-btn:focus-visible { outline:none; border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-dim); }
.props-align-btn:active:not(:disabled), .props-transform-btn:active:not(:disabled), .props-pf-btn:active:not(:disabled), .props-stroke-btn:active:not(:disabled) { color:var(--accent); background:var(--accent-dim); border-color:rgba(0,122,255,0.38); }
.props-align-btn:disabled, .props-transform-btn:disabled, .props-pf-btn:disabled, .props-stroke-btn:disabled { opacity:0.38; cursor:default; }
.props-grid.is-empty .props-align-btn:disabled, .props-grid.is-empty .props-transform-btn:disabled, .props-grid.is-empty .props-pf-btn:disabled, .props-grid.is-empty .props-stroke-btn:disabled { color:var(--text-tertiary); }
.props-align-btn .icon-svg, .props-transform-btn .icon-svg { width:17px; height:17px; }
.props-pf-btn .icon-svg { width:18px; height:18px; }
/* Flip buttons sit directly on the panel background -- no box; hover/active read through icon colour only. */
.props-align-btn, .props-transform-btn, .props-pf-btn, .props-stroke-btn { background:transparent; border-color:transparent; }
.props-align-btn:hover:not(:disabled), .props-transform-btn:hover:not(:disabled), .props-pf-btn:hover:not(:disabled), .props-stroke-btn:hover:not(:disabled) { background:transparent; border-color:transparent; }
.props-align-btn:active:not(:disabled), .props-transform-btn:active:not(:disabled), .props-pf-btn:active:not(:disabled), .props-stroke-btn:active:not(:disabled) { background:transparent; border-color:transparent; }
/* Stroke options rows (Align / Cap / Corner): three labeled rows under the Pathfinder row, same
   horizontal-rule treatment. The pressed (active) button shows the selection's current value
   (js/properties.js); it must survive the flat overrides above, hence the hover pairing. */
.props-stroke-opts { width:100%; display:flex; flex-direction:column; gap:2px; padding-top:8px; margin-top:2px; border-top:1px solid var(--border); align-self:stretch; justify-self:start; }
.props-stroke-row { display:flex; align-items:center; gap:2px; }
.props-stroke-label { flex:0 0 38px; font-size:10px; line-height:1; font-weight:700; color:var(--text-secondary); -webkit-user-select:none; user-select:none; }
.props-grid.is-empty .props-stroke-label { color:var(--text-tertiary); }
.props-stroke-btn { flex:1 1 0; }
.props-stroke-btn .icon-svg { width:18px; height:18px; }
.props-stroke-btn.active, .props-stroke-btn.active:hover:not(:disabled) { color:var(--accent); background:var(--accent-dim); border-color:rgba(0,122,255,0.38); }

/* Brush Options (Paintbrush / Blob Brush / Eraser tool options, js/brush-tools.js): sits below
   the props grid, visible only while a brush tool is active. Reuses the prop-field components;
   the fidelity slider thumb takes the canvas-handle language (white dot, accent ring). */
.props-brush { width:100%; display:flex; flex-direction:column; gap:6px; padding-top:8px; margin-top:8px; border-top:1px solid var(--border); box-sizing:border-box; }
.props-brush[hidden] { display:none; }
.props-brush-eyebrow { font-size:9px; line-height:1; font-weight:700; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-tertiary); -webkit-user-select:none; user-select:none; }
.props-brush-row { display:flex; align-items:center; gap:6px; min-width:0; }
.props-brush-row[hidden] { display:none; }
.props-brush-label { flex:0 0 38px; font-size:10px; line-height:1; font-weight:700; color:var(--text-secondary); -webkit-user-select:none; user-select:none; }
.props-brush-field { flex:1 1 auto; }
.props-brush-slider { flex:1 1 auto; min-width:0; height:16px; margin:0; background:transparent; appearance:none; -webkit-appearance:none; cursor:pointer; }
.props-brush-slider:focus-visible { outline:none; }
.props-brush-slider::-webkit-slider-runnable-track { height:3px; border-radius:2px; background:rgba(255,255,255,0.14); }
.props-brush-slider::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:11px; height:11px; margin-top:-4px; border-radius:50%; background:#fff; border:1.5px solid var(--accent); box-sizing:border-box; box-shadow:0 1px 3px rgba(0,0,0,0.5); transition:box-shadow 0.12s; }
.props-brush-slider:focus-visible::-webkit-slider-thumb { box-shadow:0 0 0 3px var(--accent-dim), 0 1px 3px rgba(0,0,0,0.5); }
.props-brush-slider::-moz-range-track { height:3px; border-radius:2px; background:rgba(255,255,255,0.14); }
.props-brush-slider::-moz-range-thumb { width:8px; height:8px; border-radius:50%; background:#fff; border:1.5px solid var(--accent); box-sizing:border-box; box-shadow:0 1px 3px rgba(0,0,0,0.5); }
.props-brush-slider:focus-visible::-moz-range-thumb { box-shadow:0 0 0 3px var(--accent-dim), 0 1px 3px rgba(0,0,0,0.5); }
.props-brush-scale { display:flex; justify-content:space-between; padding-left:44px; margin-top:-3px; font-size:9px; line-height:1; color:var(--text-tertiary); -webkit-user-select:none; user-select:none; }
.props-brush-scale[hidden] { display:none; }

/* Live Corners (js/live-corners.js): "Corners" Radius block below the props grid (visible only
   when the selection has roundable corners) + the canvas corner widgets in the tool overlays. */
.props-corner { width:100%; display:flex; flex-direction:column; gap:6px; padding-top:8px; margin-top:8px; border-top:1px solid var(--border); box-sizing:border-box; }
.props-corner[hidden] { display:none; }
.props-corner-eyebrow { font-size:9px; line-height:1; font-weight:700; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-tertiary); -webkit-user-select:none; user-select:none; }
.props-corner-row { display:flex; align-items:center; gap:6px; min-width:0; }
.props-corner-label { flex:0 0 38px; font-size:10px; line-height:1; font-weight:700; color:var(--text-secondary); cursor:ew-resize; touch-action:none; -webkit-user-select:none; user-select:none; }
.props-corner-field { flex:1 1 auto; }

/* Type tool: Properties "Text" section (js/text-tool.js) + the in-place canvas editor. */
.props-text { width:100%; display:flex; flex-direction:column; gap:6px; padding-top:8px; margin-top:8px; border-top:1px solid var(--border); box-sizing:border-box; }
.props-text[hidden] { display:none; }
.props-text-eyebrow { font-size:9px; line-height:1; font-weight:700; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-tertiary); -webkit-user-select:none; user-select:none; }
.props-text-row { display:flex; align-items:center; gap:6px; min-width:0; }
.props-text-label { flex:0 0 38px; font-size:10px; line-height:1; font-weight:700; color:var(--text-secondary); -webkit-user-select:none; user-select:none; }
.props-text-size-label { cursor:ew-resize; touch-action:none; }
.props-text-field { flex:1 1 auto; min-width:0; }
.props-text-family { width:100%; height:28px; display:flex; align-items:center; justify-content:space-between; gap:6px; padding:0 8px; font-size:11px; color:var(--text); background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; cursor:pointer; min-width:0; transition:background 0.15s, border-color 0.15s; }
.props-text-family:hover { background:var(--bg-hover); border-color:rgba(255,255,255,0.22); }
.props-text-family:focus-visible { outline:none; border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-dim); }
.props-text-family-label { flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; text-align:left; }
.props-text-family-chevron { flex:0 0 auto; width:10px; height:6px; color:var(--text-tertiary); }
.props-text-styles { display:flex; gap:4px; }
.props-text-style-btn { width:26px; height:28px; display:flex; align-items:center; justify-content:center; padding:0; font-size:12px; color:var(--text-secondary); background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; cursor:pointer; transition:background 0.15s, border-color 0.15s, color 0.15s; }
.props-text-style-btn:hover { color:var(--text); background:var(--bg-hover); border-color:rgba(255,255,255,0.22); }
.props-text-style-btn.active, .props-text-style-btn.active:hover { color:var(--accent); background:var(--accent-dim); border-color:rgba(0,122,255,0.38); }
.props-text-style-btn:disabled, .props-text-style-btn.is-unavailable, .props-text-style-btn:disabled:hover, .props-text-style-btn.is-unavailable:hover { opacity:0.35; cursor:default; color:var(--text-secondary); background:var(--surface-raised); border-color:var(--border-strong); }
.props-text-bold { font-weight:800; }
.props-text-italic { font-style:italic; font-family:Georgia, 'Times New Roman', serif; }
.props-text-align-btn { flex:1 1 0; height:28px; display:flex; align-items:center; justify-content:center; padding:0; color:var(--text-secondary); background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; cursor:pointer; transition:background 0.15s, border-color 0.15s, color 0.15s; }
.props-text-align-btn:hover { color:var(--text); background:var(--bg-hover); border-color:rgba(255,255,255,0.22); }
.props-text-align-btn.active, .props-text-align-btn.active:hover { color:var(--accent); background:var(--accent-dim); border-color:rgba(0,122,255,0.38); }
.props-text-align-btn .icon-svg { width:16px; height:16px; }
.text-font-dd .stroke-dd-item { text-align:left; font-size:12px; }
/* In-place Type editor: screen-space textarea over the anchor, above the canvas overlays (3)
   and below the status bar (14). line-height must stay 1.2 (TEXT_LINE_EM, js/text-tool.js). */
.text-tool-editor { position:absolute; z-index:4; margin:0; border:none; background:transparent; resize:none; overflow:hidden; white-space:pre; line-height:1.2; outline:1px dashed rgba(0,122,255,0.55); outline-offset:2px; caret-color:var(--accent); pointer-events:auto; box-sizing:border-box; }
.text-tool-editor[hidden] { display:none; }
.text-tool-editor:focus { outline:1px dashed rgba(0,122,255,0.55); }
.lc-widget { cursor:default; }
.props-rotate-field { justify-self:center; width:82px; height:24px; display:flex; align-items:center; gap:0; box-sizing:border-box; padding:0; overflow:hidden; color:var(--text-secondary); background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; transition:background 0.15s, border-color 0.15s, box-shadow 0.15s; }
.props-rotate-field:focus-within { background:var(--bg-secondary); border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-dim); }
.props-angle-icon { width:13px; height:13px; flex-shrink:0; margin:0 1px 0 4px; color:var(--text-secondary); pointer-events:auto; cursor:ew-resize; touch-action:none; transition:color 0.12s; }
.props-angle-icon:hover { color:var(--text); }
.props-grid.is-empty .props-angle-icon, .props-grid.is-artboard .props-angle-icon, .props-grid.is-anchor .props-angle-icon { pointer-events:none; cursor:default; }
.props-grid.is-guide .props-angle-icon { pointer-events:none; cursor:default; }
.props-grid.is-anchor .props-rotate-field, .props-grid.is-artboard .props-rotate-field, .props-grid.is-guide .props-rotate-field { opacity:0.48; }
.prop-rotate-value { flex:1 1 auto; min-width:0; box-sizing:border-box; text-align:right; font-family:monospace; font-size:11px; font-weight:600; font-variant-numeric:tabular-nums; color:var(--text); background:transparent; border:none; padding:0; outline:none; cursor:text; -webkit-user-select:text; user-select:text; }
.prop-rotate-value:disabled { color:var(--text-secondary); cursor:default; -webkit-user-select:none; user-select:none; }
.props-rotate-field .prop-unit { font-size:13px; line-height:1; flex-shrink:0; padding:0 1px 0 0; }
.props-rotate-dd-btn { display:flex; align-items:center; justify-content:center; width:14px; height:100%; flex-shrink:0; box-sizing:border-box; padding:0; border:none; border-left:1px solid var(--border-strong); border-radius:0; color:var(--text-tertiary); background:transparent; cursor:pointer; transition:color 0.1s, background 0.1s; }
.props-rotate-dd-btn:hover:not(:disabled) { color:var(--text); background:var(--bg-hover); }
.props-rotate-dd-btn:disabled { cursor:default; }
.props-rotate-dd-btn svg { width:9px; height:6px; display:block; }
.props-grid.is-empty .props-rotate-field { opacity:0.48; }
.props-grid.is-empty .props-rotate-field, .props-grid.is-empty .props-angle-icon, .props-grid.is-empty .prop-rotate-value:disabled { color:var(--text-tertiary); }

/* Properties content scrolls within the panel when the workspace is short, matching the
   layers panel: the -12px/+12px margin/padding lets the custom track sit at the panel edge. */
.props-wrap { position:relative; flex:1; min-height:0; display:flex; }
.props-scroll { flex:1; overflow-y:auto; overflow-x:clip; -webkit-overflow-scrolling:touch; overscroll-behavior-y:contain; display:flex; flex-direction:column; gap:8px; margin:0 -12px; padding:0 12px; min-height:0; -ms-overflow-style:none; scrollbar-width:none; }
.props-scroll::-webkit-scrollbar { display:none; width:0; height:0; }

.layers-wrap { position:relative; flex:1; min-height:0; display:flex; }
.layers-list { flex:1; overflow-y:auto; overflow-x:clip; -webkit-overflow-scrolling:touch; touch-action:pan-y !important; overscroll-behavior-y:contain; scroll-behavior:auto; will-change:scroll-position; display:flex; flex-direction:column; gap:5px; margin:0 -12px; padding:0 12px; min-height:0; -ms-overflow-style:none; scrollbar-width:none; }
.layers-list::-webkit-scrollbar { display:none; width:0; height:0; }
.layers-marquee { position:absolute; z-index:9; pointer-events:none; box-sizing:border-box; border:1px solid rgba(64,156,255,0.95); background:rgba(0,122,255,0.14); box-shadow:0 0 0 1px rgba(0,0,0,0.2), inset 0 0 0 1px rgba(255,255,255,0.08); }
body.is-marquee-selecting-layers, body.is-marquee-selecting-layers * { cursor:crosshair !important; user-select:none !important; -webkit-user-select:none !important; }

.custom-scroll-track { position:absolute; top:2px; bottom:2px; right:-12px; width:12px; pointer-events:none; z-index:10; display:flex; justify-content:center; }
.custom-scroll-track::before, .custom-scroll-track::after { content:""; position:absolute; left:50%; width:8px; height:7px; background:var(--text-tertiary); border-radius:2px; opacity:0; clip-path:polygon(50% 0, 100% 100%, 0 100%); transition:opacity 0.18s cubic-bezier(0.4, 0.0, 0.2, 1), background-color 0.18s cubic-bezier(0.4, 0.0, 0.2, 1); pointer-events:none; }
.custom-scroll-track::before { top:0; transform:translateX(-50%); }
.custom-scroll-track::after { bottom:0; transform:translateX(-50%) rotate(180deg); }
.custom-scroll-track.is-scrollable::before, .custom-scroll-track.is-scrollable::after { opacity:0.55; }
.custom-scroll-track.is-hovered::before, .custom-scroll-track.is-hovered::after, .custom-scroll-track.is-active::before, .custom-scroll-track.is-active::after { opacity:0.82; background:var(--text-secondary); }
.custom-scroll-track.is-scrollable .custom-scroll-thumb { opacity:0.26; }
.custom-scroll-track:hover .custom-scroll-thumb, .custom-scroll-track.is-hovered .custom-scroll-thumb, .custom-scroll-track.is-active .custom-scroll-thumb { opacity:0.58; background:var(--text); box-shadow:0 2px 8px rgba(0,0,0,0.35); transition:opacity 0.15s cubic-bezier(0.4, 0.0, 0.2, 1), background-color 0.15s cubic-bezier(0.4, 0.0, 0.2, 1), box-shadow 0.15s cubic-bezier(0.4, 0.0, 0.2, 1); }
.custom-scroll-thumb { width:6px; margin:0; border-radius:99px; background:var(--text-secondary); opacity:0; transition:opacity 0.4s cubic-bezier(0.4, 0.0, 0.2, 1), background-color 0.18s cubic-bezier(0.4, 0.0, 0.2, 1), box-shadow 0.18s cubic-bezier(0.4, 0.0, 0.2, 1); will-change:transform, opacity; pointer-events:auto; cursor:default; touch-action:none; }
.custom-scroll-thumb:hover { opacity:0.75 !important; }
.custom-scroll-thumb:active { opacity:1 !important; }

.layer-item { position:relative; display:flex; flex-direction:column; gap:0; padding:0; background:var(--bg-secondary); border:1px solid var(--border); border-radius:6px; font-size:12px; flex-shrink:0; width:100%; box-sizing:border-box; box-shadow:0 1px 3px rgba(0,0,0,0.1); overflow:hidden; transition:border-color 0.16s ease, box-shadow 0.16s ease, background 0.16s ease; }
.layer-item:not(.is-selected):not(.is-management-selected):hover { border-color:var(--border-strong); box-shadow:0 1px 3px rgba(0,0,0,0.14), inset 0 1px 0 rgba(255,255,255,0.035); }

/* --- Layer selection: restrained accent (Figma / Sketch) --- */
/* Accent border + a unified blue tint: a very faint wash across the whole card
   body, with the title row a touch stronger. The border encloses one cohesive
   tinted region instead of a bright header over a dark body. */
/* Hidden/locked rows select through the separate management set, but they LOOK the same as any
   other selected row: hiding dims a row (.is-layer-hidden) and locking changes only the lock icon,
   so neither may drag a grey/dashed "state" treatment onto the card. A collapsed group containing
   selected artwork receives only the blue inset indicator, not the full selected-row wash. */
.layer-item.is-selected, .layer-item.is-management-selected { border-color:rgba(0,122,255,0.5); background:linear-gradient(rgba(0,122,255,0.07), rgba(0,122,255,0.07)), var(--bg-secondary); }
.layer-item.is-selected .layer-title-row, .layer-item.is-management-selected .layer-title-row { background:rgba(0,122,255,0.12); }
.layer-item.is-selected .layer-title, .layer-item.is-management-selected .layer-title { color:var(--text); text-shadow:0 1px 2px rgba(0,0,0,0.5); }
.layer-item.has-selected-descendant:not(.is-selected) { border-color:rgba(0,122,255,0.32); box-shadow:inset 3px 0 0 rgba(0,122,255,0.72), 0 1px 3px rgba(0,0,0,0.12); }

/* Layers panel bottom toolbar: a full-width strip pinned below the layers list, mirroring
   the header's divider (border + gap) so header and footer read as one frame. The layers-wrap
   above it is flex:1, so this stays flush to the panel bottom. Icons sit bare on the strip --
   no button box -- and grow on hover into a rounded wash. Import/Paste/Duplicate cluster left
   with the app accent; the destructive trash is pushed to the far right and keeps its red wash. */
.layers-toolbar { display:flex; align-items:center; gap:4px; flex-shrink:0; border-top:1px solid var(--border); padding-top:6px; margin-top:2px; }
.layers-toolbar .layer-duplicate-btn { margin-left:auto; }
.layer-import-btn, .layer-paste-btn, .layer-add-bg-btn, .layer-duplicate-btn { display:flex; align-items:center; justify-content:center; width:24px; height:24px; padding:0; border:none; background:transparent; color:var(--text-secondary); border-radius:6px; cursor:pointer; transition:color 0.15s ease, background 0.15s ease, opacity 0.15s ease; touch-action:manipulation; -webkit-tap-highlight-color:transparent; }
.layer-import-btn:hover:not(:disabled), .layer-paste-btn:hover:not(:disabled), .layer-add-bg-btn:hover:not(:disabled), .layer-duplicate-btn:hover:not(:disabled) { color:var(--accent); background:var(--accent-dim); }
.layer-import-btn:focus-visible, .layer-paste-btn:focus-visible, .layer-add-bg-btn:focus-visible, .layer-duplicate-btn:focus-visible { color:var(--accent); background:var(--accent-dim); outline:none; box-shadow:0 0 0 2px rgba(0,122,255,0.4); }
.layer-import-btn:disabled, .layer-paste-btn:disabled, .layer-add-bg-btn:disabled, .layer-duplicate-btn:disabled { opacity:0.35; cursor:default; }
.layer-import-btn[hidden], .layer-paste-btn[hidden], .layer-add-bg-btn[hidden], .layer-duplicate-btn[hidden] { display:none; }
.layer-import-btn .icon-svg, .layer-paste-btn .icon-svg, .layer-add-bg-btn .icon-svg, .layer-duplicate-btn .icon-svg { width:18px; height:18px; }
.layer-delete-btn { display:flex; align-items:center; justify-content:center; width:24px; height:24px; padding:0; border:none; background:transparent; color:var(--text-secondary); border-radius:6px; cursor:pointer; transition:color 0.15s ease, background 0.15s ease, opacity 0.15s ease; touch-action:manipulation; -webkit-tap-highlight-color:transparent; }
.layer-delete-btn:hover:not(:disabled) { color:#FF3B30; background:rgba(255,59,48,0.12); }
.layer-delete-btn:focus-visible { color:#FF3B30; background:rgba(255,59,48,0.12); outline:none; box-shadow:0 0 0 2px rgba(255,59,48,0.4); }
.layer-delete-btn:disabled { opacity:0.35; cursor:default; }
.layer-delete-btn[hidden] { display:none; }
.layer-delete-btn .icon-svg { width:18px; height:18px; }

/* Delete: collapse the card to nothing; the negative margin absorbs the .layers-list gap so
   the cards below slide up by exactly one slot. Insert (duplicate) runs the same in reverse,
   growing a fresh card from nothing so the cards below slide down. Same curve as the twirl collapse. */
.layer-item.is-deleting, .layer-item.is-inserting { transition:height 0.3s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.22s ease, margin 0.3s cubic-bezier(0.2, 0.8, 0.2, 1); pointer-events:none; overflow:hidden; will-change:height, opacity; }

/* Group twirl: the child run unrolls from under its group row and rolls back up into it. Height
   carries the space (the negative margin absorbs the .layers-list gap, same as the delete/insert
   cards); the 6px lift + fade carry the direction, so the children read as coming out from under
   the parent rather than fading in on the spot. JS stamps the per-row cascade into transition-delay.
   Rolling up is the quicker, accelerating half and goes inert -- it is on its way out. */
.layer-item.is-unrolling { transition:height 0.24s cubic-bezier(0.2, 0.8, 0.2, 1), margin 0.24s cubic-bezier(0.2, 0.8, 0.2, 1), transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.18s ease-out; overflow:hidden; will-change:height, opacity, transform; }
.layer-item.is-rollingup { transition:height 0.2s cubic-bezier(0.45, 0, 0.85, 0.4), margin 0.2s cubic-bezier(0.45, 0, 0.85, 0.4), transform 0.2s cubic-bezier(0.45, 0, 0.85, 0.4), opacity 0.16s ease-in; pointer-events:none; overflow:hidden; will-change:height, opacity, transform; }

@media (prefers-reduced-motion: reduce) {
  .layer-title-row, .layer-twirl, .layer-import-btn, .layer-paste-btn, .layer-add-bg-btn, .layer-duplicate-btn, .layer-item.is-deleting, .layer-item.is-inserting, .layer-item.is-unrolling, .layer-item.is-rollingup { transition:none; }
  .panel-layers.is-resizing .layer-item, .panel-layers.is-resizing .layer-title-row, .panel-layers.is-resizing .layer-thumb, .panel-layers.is-resizing .layer-title, .panel-layers.is-resizing .layer-toggle, .panel-layers.is-resizing .layer-twirl, .panel-layers.is-resizing .icon-svg { transition:none; }
  .layers-size-toggle .icon-svg.is-swapped { animation:none; }
  .project-name-id, .project-name-edit { transition:none; }
  .project-name-text.rename-flash { animation:none; }
  .ap-weight-slider.is-springing .ap-ws-cap, .ap-weight-slider.is-springing .ap-ws-fill { transition:none; }
}

/* One compact row per layer: twirl | thumbnail | name | lock | eye. The 72px right padding clears
   the absolutely-pinned lock + eye; the whole row is the drag/select surface. Nesting is indented
   on the card itself (see Groups below), so the row keeps one flat padding at every depth. */
.layer-title-row { display:flex; align-items:center; gap:8px; position:relative; background:var(--bg); border-radius:6px; padding:6px 72px 6px 7px; width:100%; min-height:48px; box-sizing:border-box; cursor:default; transition:background 0.16s ease; }
.layer-item:not(.is-selected):not(.is-management-selected):hover .layer-title-row { background:linear-gradient(rgba(255,255,255,0.035), rgba(255,255,255,0.035)), var(--bg); }
.layer-title-input { cursor:text; }

/* --- Layer drag-to-reorder (z-order) --- */
.layers-list.is-reordering { cursor:grabbing; }
.layers-list.is-reordering .layer-item:not(.is-drag-source) { will-change:transform; }
body.is-reordering-layers, body.is-reordering-layers * { cursor:grabbing !important; user-select:none !important; -webkit-user-select:none !important; }
/* Lifted card while dragging: transform + transition are driven inline from JS. */
.layer-item.is-drag-source { z-index:50; border-color:rgba(0,122,255,0.5); background:linear-gradient(rgba(0,122,255,0.07), rgba(0,122,255,0.07)), var(--bg-secondary); box-shadow:0 2px 4px rgba(0,0,0,0.25), 0 16px 26px -12px rgba(0,0,0,0.55); cursor:grabbing; will-change:transform; }
.layer-item.is-drag-source .layer-title-row { background:rgba(0,122,255,0.12); cursor:grabbing; }
/* Cards sliding to open/close the gap. */
.layer-item.is-drag-shift { transition:transform 0.2s cubic-bezier(0.2, 0, 0, 1); pointer-events:none; }
.layer-title { flex:1; font-weight:600; color:var(--text); font-size:11px; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.layer-title-input { font:600 11px var(--font); color:var(--text); background:var(--surface-raised); border:1px solid var(--accent); border-radius:3px; padding:1px 5px; margin:-2px 0; max-width:220px; width:100%; outline:none; box-shadow:0 0 0 1px var(--accent), 0 0 0 4px var(--accent-dim); user-select:text; -webkit-user-select:text; transition:box-shadow 0.15s ease; }
.layer-title.rename-flash { animation:renameFlash 0.45s ease; }
@keyframes renameFlash { 0% { color:var(--accent); } 100% { color:var(--text); } }

/* Layer thumbnail: live shape-only mini-preview (raster layers use an <img>, vector layers
   an inline <svg>) on a checkerboard mat. The eye at the far right hides the WHOLE layer
   (canvas + export); hidden rows dim but stay selectable so they can still be edited. */
.layer-thumb { width:34px; height:34px; flex:0 0 34px; display:flex; align-items:center; justify-content:center; overflow:hidden; box-sizing:border-box; background:repeating-conic-gradient(#3a3a40 0% 25%, #29292f 0% 50%) 0 0/10px 10px; border:1px solid var(--border-strong); border-radius:4px; box-shadow:inset 0 0 0 1px rgba(0,0,0,0.22); pointer-events:none; }
.layer-thumb-img, .layer-thumb-svg { display:block; width:100%; height:100%; object-fit:contain; }
.layer-thumb.is-text-thumb { background:var(--surface-raised); }
.layer-thumb.is-text-thumb .icon-svg { width:64%; height:64%; color:var(--text-secondary); }
.layer-eye { position:absolute; right:10px; top:50%; transform:translateY(-50%); }
.layer-eye:hover, .layer-eye:active { background:none; }
.layer-eye .icon-svg { transition:color 0.12s ease, opacity 0.12s ease, filter 0.12s ease; }
.layer-eye:hover .icon-svg { color:var(--text); filter:drop-shadow(0 0 4px rgba(242,242,247,0.65)); }
.layer-eye.hidden-state .icon-svg { opacity:0.38; }
.layer-eye.hidden-state:hover .icon-svg { opacity:0.62; }
/* A hidden row reads as switched off, not merely thumbnail-dimmed: the card surface sinks and
   flattens, the title drops to tertiary, and the twirl + lock recede with it, so the row separates
   clearly from its visible neighbours. The eye keeps its own lighter dim (above) so it stays
   legible enough to click the layer back on. The surface half is skipped while the row is selected
   -- the accent state has to read through -- and hover feedback is restored at higher specificity. */
.layer-item.is-layer-hidden .layer-thumb { opacity:0.34; filter:grayscale(100%); }
.layer-item.is-layer-hidden .layer-title { color:var(--text-tertiary); }
.layer-item.is-layer-hidden .layer-twirl, .layer-item.is-layer-hidden .layer-lock .icon-svg { opacity:0.4; }
.layer-item.is-layer-hidden:not(.is-selected):not(.is-management-selected) { background:var(--bg); border-color:rgba(255,255,255,0.05); box-shadow:none; }
.layer-item.is-layer-hidden:not(.is-selected):not(.is-management-selected) .layer-title-row { background:rgba(0,0,0,0.28); }
.layer-item.is-layer-hidden:not(.is-selected):not(.is-management-selected):hover { border-color:var(--border); box-shadow:0 1px 3px rgba(0,0,0,0.14); }
.layer-item.is-layer-hidden:not(.is-selected):not(.is-management-selected):hover .layer-title-row { background:linear-gradient(rgba(255,255,255,0.03), rgba(255,255,255,0.03)), rgba(0,0,0,0.28); }

/* Lock sits just left of the eye; both hide/unhide and lock/unlock stay live regardless of
   each other. Locked cards remain selectable and reorderable in the panel. */
.layer-lock { position:absolute; right:40px; top:50%; transform:translateY(-50%); }
.layer-lock:hover, .layer-lock:active { background:none; }
.layer-lock .icon-svg { transition:color 0.12s ease; }
.layer-lock:hover .icon-svg { color:var(--text); }
.layer-item.is-locked .layer-title-row { cursor:default; }

.layer-toggle { cursor:pointer; display:flex; align-items:center; justify-content:center; color:var(--text-secondary); padding:4px; width:26px; height:26px; box-sizing:border-box; transition:0.1s; border-radius:4px; touch-action:manipulation; flex-shrink:0; }
.layer-toggle:hover { color:var(--text); background:transparent; }

/* --- Groups: twirl + nesting (docs/layers-panel.md) --- */
/* Every row reserves the twirl column so thumbnails stay aligned within a level; only group rows
   draw the triangle, which rotates a quarter turn when the group is open. */
/* Negative side margins absorb most of the row's 8px flex gap, leaving a little breathing room on
   each side of the triangle; the column runs slightly wider than one --layer-depth step. */
/* The triangle turns with a slight overshoot -- it is the element under the cursor, so it carries
   the mechanism's character; everything else in the panel stays on the plain settle curve. */
.layer-twirl { flex:0 0 18px; width:18px; height:21px; display:flex; align-items:center; justify-content:center; color:var(--text-secondary); cursor:pointer; margin-left:-4px; margin-right:-4px; transition:color 0.15s ease, transform 0.22s cubic-bezier(0.34, 1.25, 0.64, 1); }
.layer-twirl.is-spacer { cursor:default; pointer-events:none; }
.layer-twirl:not(.is-spacer):hover { color:var(--text); }
.layer-twirl.is-open { transform:rotate(90deg); }
.layer-twirl .icon-svg { width:16.5px; height:16.5px; }

/* Nesting: the whole card steps in one 14px indent per level -- no guide rules. --layer-depth is
   set from JS on group children; depth 0 leaves the card flush with the list. The width shrinks by
   the same amount so an indented card still ends at the list's right edge. */
.layer-item { margin-left:calc(var(--layer-depth, 0) * 14px); width:calc(100% - var(--layer-depth, 0) * 14px); }

/* Hidden/locked cascade from an enclosing group: the row already dims through .is-layer-hidden /
   .is-locked; its OWN eye/lock go inert because the group owns that state. */
.layer-item.is-ancestor-hidden .layer-eye, .layer-item.is-ancestor-locked .layer-lock { opacity:0.3; pointer-events:none; }

/* Compact density keeps the existing layer card design, but brings its controls onto one
   tighter rhythm. Large mode is the untouched default above. */
.panel-layers.is-small .layer-title-row { gap:5px; min-height:30px; padding:3px 62px 3px 4px; }
.panel-layers.is-small .layer-item { margin-left:calc(var(--layer-depth, 0) * 11px); width:calc(100% - var(--layer-depth, 0) * 11px); }
.panel-layers.is-small .layer-twirl { flex-basis:15px; width:15px; height:16.5px; margin-left:-3px; margin-right:-3px; }
.panel-layers.is-small .layer-twirl .icon-svg { width:13.5px; height:13.5px; }
.panel-layers.is-small .layer-thumb { width:22px; height:22px; flex-basis:22px; border-radius:3px; }
.panel-layers.is-small .layer-title { font-size:10px; }
.panel-layers.is-small .layer-title-input { font-size:10px; padding:1px 4px; }
.panel-layers.is-small .layer-toggle { width:22px; height:22px; padding:3px; }
.panel-layers.is-small .layer-toggle .icon-svg { width:14px; height:14px; }
.panel-layers.is-small .layer-eye { right:7px; }
.panel-layers.is-small .layer-lock { right:32px; }

/* Density change (small <-> large): the whole stack resizes on one shared curve, each row a few ms
   behind the one above it, so the list reads as a single body compressing rather than N rows
   snapping independently. --lp-rz bundles duration + curve + that row's stagger and inherits from
   the card down to every part it has to reach; --lp-resize-delay is stamped per row from JS.
   Everything is scoped to .is-resizing, which is on ONLY for the length of the change: the reorder
   drag inline-drives transform/width on these same cards, and a standing width transition would
   fight its horizontal depth preview -- and hover/scroll keep their transition-free fast paths. */
.panel-layers.is-resizing .layer-item { --lp-rz:0.26s cubic-bezier(0.2, 0.8, 0.2, 1) var(--lp-resize-delay, 0ms); transition:margin-left var(--lp-rz), width var(--lp-rz), border-color 0.16s ease, box-shadow 0.16s ease, background 0.16s ease; }
.panel-layers.is-resizing .layer-title-row { transition:min-height var(--lp-rz), padding var(--lp-rz), gap var(--lp-rz), background 0.16s ease; }
.panel-layers.is-resizing .layer-thumb { transition:width var(--lp-rz), height var(--lp-rz), flex-basis var(--lp-rz), border-radius var(--lp-rz); }
.panel-layers.is-resizing .layer-title { transition:font-size var(--lp-rz); }
.panel-layers.is-resizing .layer-toggle { transition:width var(--lp-rz), height var(--lp-rz), padding var(--lp-rz), right var(--lp-rz); }
.panel-layers.is-resizing .layer-twirl { transition:width var(--lp-rz), height var(--lp-rz), flex-basis var(--lp-rz), margin var(--lp-rz), color 0.15s ease, transform 0.22s cubic-bezier(0.34, 1.25, 0.64, 1); }
.panel-layers.is-resizing .layer-toggle .icon-svg, .panel-layers.is-resizing .layer-twirl .icon-svg { transition:width var(--lp-rz), height var(--lp-rz); }

/* Illustrator-style fill/stroke launch swatch: sharp swatch in a 2px #1a1a1e mat with a slightly-rounded --border-strong outer frame */
.picker-wrap { position:relative; width:26px; height:26px; flex:0 0 auto; box-sizing:border-box; display:flex; align-items:center; justify-content:center; background:var(--bg); border:1px solid var(--border-strong); border-radius:2px; cursor:pointer; touch-action:manipulation; transition:border-color 0.15s ease; }
.picker-wrap:hover { border-color:var(--accent); }
.picker-wrap-stroke { background:transparent; }
.lp-swatch { width:20px; height:20px; box-sizing:border-box; border-radius:0; flex:0 0 auto; }
.lp-swatch.lp-swatch-stroke { background:transparent; border:4px solid #000; box-shadow:inset 0 0 0 2px #1a1a1e, 0 0 0 2px #1a1a1e; }
.lp-swatch-svg { width:20px; height:20px; display:block; flex:0 0 auto; }
.picker-wrap-stroke .lp-swatch-svg { box-shadow:0 0 0 2px #1a1a1e; }

.app-input-grey { color: var(--text-tertiary) !important; }
.app-input-grey::selection { background: transparent; color: var(--text-tertiary); }

.cp-input-group { display:flex; align-items:center; background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; padding:3px 6px; gap:4px; transition:0.15s; box-sizing:border-box; justify-content:space-between; flex-shrink:0; height:24px; }
.cp-unit { color:var(--text-tertiary); font-weight:600; font-size:10px; flex-shrink:0; }

.cp-input-group.hex-target { gap:2px; }
.cp-hex-input { background:transparent; border:none; color:var(--text); font-family:monospace; font-size:11px; width:40px; outline:none; text-transform:uppercase; user-select:text; -webkit-user-select:text; touch-action:manipulation; padding:0; text-align:left; caret-color:transparent; }
.cp-size-input { background:transparent; border:none; color:var(--text); font-family:monospace; font-size:11px; width:38px; outline:none; user-select:text; -webkit-user-select:text; touch-action:manipulation; padding:0; text-align:center; }
.cp-size-input::-webkit-outer-spin-button, .cp-size-input::-webkit-inner-spin-button { -webkit-appearance:none; margin:0; }

.preset-group { display:grid; grid-template-columns:repeat(4, 12px); gap:6px; align-items:center; flex-shrink:0; }
.preset-swatch { width:12px; height:12px; border-radius:50%; cursor:pointer; transition:0.1s; box-shadow:inset 0 0 0 1px rgba(0,0,0,0.3), 0 0 0 1px var(--border-strong); touch-action:manipulation; flex-shrink:0; }
.preset-swatch:hover { transform:scale(1.15); box-shadow:inset 0 0 0 1px rgba(0,0,0,0.3), 0 0 0 1px var(--text-secondary); }
/* Local preset mode: a two-row strip that also takes over the dropped hex field's slot, so it
   spans the hex+presets grid columns (4/6) at 138px = 8 columns (16 swatches, 2 rows of 8).
   More colors overflow and are revealed by wheel-driven scrollLeft (js). No scrollbar, no resize.
   overflow:hidden clips both axes, so 2px vertical padding keeps the swatch ring/hover off the
   clip edge; row-gap drops 6px->2px to hold the cell at the same 30px height (24+2+4).
   justify-content:start packs the columns tight -- without it the grid's default (stretch) grows
   the implicit auto columns to fill 138px, spacing out the swatches when there are only a few. */
.preset-group.is-local { grid-column:4 / 6; grid-auto-flow:column; grid-template-columns:none; grid-template-rows:repeat(2, 12px); column-gap:6px; row-gap:2px; justify-content:start; width:138px; padding:2px 0; overflow:hidden; }
.panel-paint.presets-local .ap-hex { display:none; }   /* Local drops the hex field; presets fill it */

/* Illustrator-style stroke width field (stepper + value + pt + preset dropdown) */
.cp-stroke-field { padding:0; gap:0; overflow:hidden; height:24px; justify-content:flex-start; width:100px; }
.cp-stroke-field .cp-size-input { width:40px; text-align:center; padding:0 2px; }
.cp-stroke-field .cp-size-input::-webkit-outer-spin-button, .cp-stroke-field .cp-size-input::-webkit-inner-spin-button { -webkit-appearance:none; margin:0; }
.cp-stroke-field .cp-size-input { -moz-appearance:textfield; }
.cp-stroke-field .cp-unit { padding:0 5px 0 1px; }

.cp-stepper { display:flex; flex-direction:column; width:15px; height:100%; border-right:1px solid var(--border-strong); flex-shrink:0; }
.cp-step-btn { flex:1; display:flex; align-items:center; justify-content:center; color:var(--text-tertiary); cursor:pointer; transition:0.1s; min-height:0; }
.cp-step-btn:first-child { border-bottom:1px solid var(--border-strong); }
.cp-step-btn:hover { color:var(--text); background:var(--bg-hover); }
.cp-step-btn svg { width:8px; height:6px; display:block; }

.cp-stroke-dd-btn { display:flex; align-items:center; justify-content:center; width:18px; height:100%; border-left:1px solid var(--border-strong); color:var(--text-tertiary); cursor:pointer; transition:0.1s; flex-shrink:0; }
.cp-stroke-dd-btn:hover { color:var(--text); background:var(--bg-hover); }
.cp-stroke-dd-btn svg { width:9px; height:6px; display:block; }

.stroke-dropdown { position:fixed; display:none; background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:6px; z-index:9999; box-shadow:0 8px 24px rgba(0,0,0,0.4), 0 0 0 1px rgba(0,0,0,0.2); max-height:280px; overflow-y:auto; padding:4px 0; }
.stroke-dropdown::-webkit-scrollbar { width:6px; }
.stroke-dropdown::-webkit-scrollbar-thumb { background:var(--border-strong); border-radius:3px; }
.stroke-dd-item { padding:5px 14px; font-size:11px; font-family:monospace; color:var(--text); cursor:pointer; transition:0.1s; white-space:nowrap; text-align:center; }
.stroke-dd-item:hover { background:var(--accent); color:#fff; }

.row-divider { width:1px; height:16px; background:var(--border-strong); margin:0 2px; flex-shrink:0; }

.slider-trigger { display:flex; align-items:center; justify-content:center; width:24px; height:24px; border-radius:4px; color:var(--text-tertiary); cursor:pointer; transition:0.15s; touch-action:manipulation; flex-shrink:0; }
.slider-trigger:hover { color:var(--text); background:var(--bg-hover); }
.slider-trigger.is-active { color:var(--accent); background:var(--accent-dim); }

.slider-popup { position:fixed; background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:6px; z-index:9999; display:none; align-items:center; justify-content:center; box-shadow:0 8px 24px rgba(0,0,0,0.4), 0 0 0 1px rgba(0,0,0,0.2); }
.slider-popup.vertical { width:34px; height:140px; }
.slider-popup.horizontal { width:140px; height:34px; padding: 0 10px; box-sizing: border-box; }
.slider-popup input[type=range] { margin:0; -webkit-appearance:none; background:transparent; outline:none; cursor:pointer; touch-action:none; }
.slider-popup.vertical input[type=range] { width:120px; height:12px; transform:rotate(-90deg); }
.slider-popup.horizontal input[type=range] { width:100%; height:12px; }
.slider-popup input[type=range]::-webkit-slider-runnable-track { width:100%; height:4px; border-radius:2px; background:rgba(255,255,255,0.2); }
.slider-popup input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; width:16px; height:16px; border-radius:50%; background:#fff; margin-top:-6px; box-shadow:0 1px 3px rgba(0,0,0,0.5); border:1px solid rgba(0,0,0,0.1); }

.btn-success { background-color:var(--success) !important; color:#fff !important; border-color:var(--success) !important; }
.btn-blue { background-color:var(--accent) !important; color:#fff !important; border-color:var(--accent) !important; }
.btn-yellow { background-color:#ffcc00 !important; color:#1a1a1e !important; border-color:#ffcc00 !important; }

.ring-blue { border-color:var(--accent) !important; box-shadow:0 0 0 1px var(--accent) !important; }
.ring-yellow { border-color:#ffcc00 !important; box-shadow:0 0 0 1px #ffcc00 !important; }
.ring-green { border-color:var(--success) !important; box-shadow:0 0 0 1px var(--success) !important; }
input[type="file"] { display:none; }

.panel-svg > .controls { flex-wrap: wrap; row-gap: 8px; }

.cb-label { display: flex; align-items: center; gap: 5px; font-size: 10px; font-weight: 600; color: var(--text-secondary); cursor: pointer; transition: 0.15s; white-space: nowrap; }
.cb-label:hover { color: var(--text); }
.cb-label input { display: none; }
.cb-custom { width: 12px; height: 12px; border-radius: 3px; border: 1px solid var(--border-strong); display: inline-block; position: relative; box-sizing: border-box; background: var(--surface-raised); transition: 0.15s; flex-shrink: 0; }
.cb-label input:checked + .cb-custom { border-color: var(--accent); background: var(--accent); }
.cb-label input:checked + .cb-custom::after { content: ''; position: absolute; top: 0px; left: 3px; width: 3px; height: 7px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg); }

/* =========================================
   Code Workbench (bottom half: SVG panel + tool tabs)
   ========================================= */
/* --- SVG panel --- */
.panel-svg { position:relative; }
.panel-svg > .panel-header { display:flex; align-items:center; }
.cw-header-row { display:flex; align-items:center; justify-content:space-between; gap:10px; }
.cw-status { display:inline-flex; align-items:center; gap:6px; color:var(--text-secondary); font-size:10px; font-weight:650; letter-spacing:0.2px; }
.cw-status-dot { width:7px; height:7px; border-radius:50%; background:var(--success); box-shadow:0 0 0 3px color-mix(in srgb, var(--success) 14%, transparent); }
.cw-status[data-status='checking'] .cw-status-dot { background:#d5a541; box-shadow:0 0 0 3px rgba(213,165,65,0.15); animation:cwStatusPulse 0.9s ease-in-out infinite alternate; }
.cw-status[data-status='error'] { color:#ef8a87; }
.cw-status[data-status='error'] .cw-status-dot { background:#e25b56; box-shadow:0 0 0 3px rgba(226,91,86,0.15); }
@keyframes cwStatusPulse { to { opacity:0.45; } }

/* --- SVG panel: toolbar extras --- */
.cw-icon-btn { width:30px; height:30px; padding:0; flex:0 0 30px; }
.cw-icon-btn .icon-svg { width:14px; height:14px; }
.opt-btn:disabled { opacity:0.4; cursor:default; }
.opt-btn:disabled:hover { background:var(--surface); color:var(--text-secondary); }

/* --- SVG panel: editor (line-number gutter + textarea share one bordered field) --- */
.cw-editor-wrap { contain:layout paint; background:var(--surface); border:1px solid var(--border); overflow:hidden; transition:border-color 0.2s, box-shadow 0.2s; }
.cw-editor-wrap:focus-within { border-color:var(--border-strong); }
.cw-editor-wrap > textarea { border:none; border-radius:0; background:transparent; padding:10px 10px 10px 8px; line-height:1.55; }
/* Feedback rings target #outputStr; re-host them on the wrap so they surround the gutter too. */
.cw-editor-wrap:has(> .ring-blue) { border-color:var(--accent); box-shadow:0 0 0 1px var(--accent); }
.cw-editor-wrap:has(> .ring-yellow) { border-color:#ffcc00; box-shadow:0 0 0 1px #ffcc00; }
.cw-editor-wrap:has(> .ring-green) { border-color:var(--success); box-shadow:0 0 0 1px var(--success); }
.cw-editor-wrap > textarea.ring-blue, .cw-editor-wrap > textarea.ring-yellow, .cw-editor-wrap > textarea.ring-green { border:none !important; box-shadow:none !important; }
/* Horizontal-only native scrollbar for the no-wrap editor (vertical stays on the custom track). */
#outputStr::-webkit-scrollbar { display:block; width:0; height:9px; }
#outputStr::-webkit-scrollbar-track { background:transparent; }
#outputStr::-webkit-scrollbar-thumb { background:rgba(255,255,255,0.16); border-radius:99px; }
#outputStr::-webkit-scrollbar-thumb:hover { background:rgba(255,255,255,0.26); }
.cw-gutter { position:relative; flex:0 0 auto; min-width:36px; overflow:hidden; background:rgba(0,0,0,0.12); border-right:1px solid var(--border); user-select:none; }
.cw-gutter-inner { position:relative; padding:10px 8px 10px 4px; font-family:monospace; font-size:12px; line-height:1.55; text-align:right; color:var(--text-tertiary); white-space:pre; }
.cw-gutter-inner > .cw-gutter-marker { position:absolute; left:3px; top:calc(10px + var(--cw-line) * 1.55em + 0.775em); width:4px; height:4px; margin-top:-2px; border-radius:50%; }
.cw-gutter-inner > .cw-gutter-error { background:#e25b56; }
.cw-gutter-inner > .cw-gutter-warning { background:#d5a541; }
.cw-gutter-inner > .cw-gutter-information { background:var(--accent); }
.cw-editor-wrap.cw-no-gutter .cw-gutter { display:none; }
.cw-editor-wrap.cw-blocked { border-color:#e25b56; box-shadow:0 0 0 2px rgba(226,91,86,0.2); animation:cwBlocked 0.24s ease-in-out 2 alternate; }
@keyframes cwBlocked { to { transform:translateX(2px); } }
/* Hidden raw-source store -- the import pipeline's #inputStr lives here, out of view. */
.cw-import-store { display:none; }

/* --- SVG panel: compact diagnostics rail --- */
.cw-diagnostics { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:6px; align-items:center; min-height:28px; border:1px solid var(--border); border-top:0; background:rgba(0,0,0,0.1); }
.cw-diagnostics-toggle { min-width:0; height:27px; display:flex; align-items:center; gap:9px; padding:0 9px; color:var(--text-secondary); background:transparent; border:0; font:600 9.5px var(--font); cursor:pointer; }
.cw-diagnostics-toggle:hover { color:var(--text); }
.cw-diagnostics-label { color:var(--text); letter-spacing:0.25px; }
.cw-diagnostic-count { display:inline-flex; gap:3px; align-items:center; white-space:nowrap; }
.cw-diagnostic-count.is-error { color:#ef8a87; }
.cw-diagnostic-count.is-warning { color:#d9b15b; }
.cw-diagnostic-count.is-information { color:#72a8e8; }
.cw-diagnostics-chevron { margin-left:auto; transform:rotate(180deg); transition:transform 0.15s; }
.cw-diagnostics-toggle[aria-expanded='true'] .cw-diagnostics-chevron { transform:rotate(0); }
.cw-revert-btn { height:22px; margin-right:5px; padding:0 8px; border:1px solid rgba(226,91,86,0.5); border-radius:4px; color:#f0a09d; background:rgba(226,91,86,0.08); font:600 9.5px var(--font); cursor:pointer; }
.cw-revert-btn:hover { color:#fff; background:rgba(226,91,86,0.2); }
.cw-diagnostics-list { grid-column:1 / -1; max-height:112px; overflow:auto; padding:4px; border-top:1px solid var(--border); }
.cw-diagnostic { width:100%; display:block; padding:5px 7px; color:var(--text-secondary); background:transparent; border:0; border-radius:3px; text-align:left; font:10px/1.35 var(--font); cursor:pointer; }
.cw-diagnostic:hover, .cw-diagnostic:focus-visible { color:var(--text); background:var(--bg-hover); outline:none; }
.cw-diagnostic-error { border-left:2px solid #e25b56; }
.cw-diagnostic-warning { border-left:2px solid #d5a541; }
.cw-diagnostic-information { border-left:2px solid var(--accent); }

/* --- SVG panel: settings popover --- */
.cw-pop { position:absolute; z-index:60; min-width:236px; padding:10px 12px 12px; box-sizing:border-box; background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:8px; box-shadow:0 12px 32px rgba(0,0,0,0.45), 0 0 0 1px rgba(0,0,0,0.25); }
.cw-pop[hidden] { display:none; }
.cw-pop-title { margin:2px 0 6px; font-size:9.5px; font-weight:700; letter-spacing:0.7px; text-transform:uppercase; color:var(--text-secondary); }
.cw-pop-check { padding:4px 2px; }
.cw-pop-check input:disabled + .cb-custom { opacity:0.4; }

/* --- Left (blank) + Export panels --- */
.panel-left, .panel-export { min-width:0; }
.wb-body-wrap { position:relative; flex:1; min-height:0; display:flex; }
.wb-body { flex:1; min-width:0; display:flex; flex-direction:column; gap:12px; padding:2px 2px 4px; overflow-y:auto; -ms-overflow-style:none; scrollbar-width:none; }
.wb-body::-webkit-scrollbar { display:none; width:0; height:0; }
.wb-group { display:flex; flex-direction:column; gap:8px; flex-shrink:0; }
.wb-group-title { display:flex; align-items:center; gap:6px; font-size:9.5px; font-weight:700; letter-spacing:0.7px; text-transform:uppercase; color:var(--text-secondary); }
.wb-group-title .icon-svg { width:12px; height:12px; opacity:0.8; }

/* Export panel (Phase 9) -- the finalize station. The EXPORT title + readiness state and the
   Export .svg / Copy SVG / Preview actions sit ABOVE a bordered "finalize card" that mirrors the
   SVG panel editor's frame (.cw-editor-wrap). Inside the card the two-column settings /
   categorized-options organization is fixed; a container query only widens the gutter on a roomier panel. The
   preflight footer spans both columns and opens Preview directly on Report. Nothing here
   serializes SVG: every value is a projection of Project settings or the Phase 8 candidate. */
/* The format choice is session-only. Real radios styled as the color picker's Solid/Gradient
   segmented switch; the -6px block margins let the 24px bar overhang into the panel gap instead of
   growing the title's line box, so the header keeps its height. Each controller projects its own readiness without sharing settings,
   candidates, or filename state. */
.exp-header-row { justify-content:flex-start; gap:10px; }
.exp-format-switch { min-width:0; height:24px; margin:-6px auto -6px 0; padding:2px; box-sizing:border-box; display:flex; align-items:stretch; gap:2px; border:1px solid var(--border-strong); border-radius:7px; background:var(--bg); box-shadow:inset 0 1px 2px rgba(0,0,0,0.3); }
.exp-format-switch .exp-sr { position:absolute; }
.exp-format-option { position:relative; display:inline-flex; align-items:center; justify-content:center; min-width:42px; padding:0 10px; box-sizing:border-box; border-radius:4px; color:var(--text-secondary); font-size:10.5px; line-height:1; font-weight:700; letter-spacing:0.3px; cursor:pointer; transition:color 0.15s, background 0.15s, box-shadow 0.15s; }
.exp-format-option:hover { color:var(--text); background:rgba(255,255,255,0.04); }
.exp-format-option input { position:absolute; width:1px; height:1px; margin:0; padding:0; opacity:0; pointer-events:none; }
/* Lighter than --surface-raised so the selected segment reads clearly against both the recessed
   bar and the --bg-secondary panel around it. */
.exp-format-option:has(input:checked) { background:#4a4a52; color:var(--text); box-shadow:0 1px 3px rgba(0,0,0,0.35), inset 0 0 0 1px rgba(255,255,255,0.08), inset 0 1px 0 rgba(255,255,255,0.1); }
.exp-format-option:has(input:focus-visible) { outline:2px solid var(--accent-hover); outline-offset:1px; }
.exp-radio-dot { position:relative; width:12px; height:12px; flex:0 0 12px; box-sizing:border-box; border:1px solid var(--border-strong); border-radius:50%; background:var(--surface-raised); box-shadow:inset 0 1px 0 rgba(255,255,255,0.05); transition:border-color 0.15s, background 0.15s, box-shadow 0.15s; }
.exp-radio input:checked + .exp-radio-dot { border-color:var(--accent); background:var(--accent-dim); }
.exp-radio input:checked + .exp-radio-dot::after { content:''; position:absolute; inset:3px; border-radius:50%; background:var(--accent); }
.exp-radio input:focus-visible + .exp-radio-dot { outline:2px solid var(--accent-hover); outline-offset:2px; }
.exp-png-status-text { display:none; }
.exp-ico-status-text { display:none; }

/* The three actions keep their intrinsic labels and wrap to a second row on a narrow desktop
   window, exactly like the SVG panel's lifecycle strip -- a squashed label would wrap mid-word
   and move the one-row floor every condensed offset is measured against. */
.panel-export > .controls { flex-wrap:wrap; row-gap:8px; }
.panel-export > .controls > .opt-btn { flex-shrink:0; white-space:nowrap; }
.export-primary-btn { background:var(--accent); border-color:var(--accent); color:#fff; }
.export-primary-btn:hover:not(:disabled) { background:var(--accent-hover); border-color:var(--accent-hover); color:#fff; }
.export-primary-btn .icon-svg { color:#fff; }
.export-primary-btn:disabled:hover { background:var(--accent); border-color:var(--accent); color:#fff; }

/* Readiness state reuses the Code panel's status pill so both panels read as one dock. */
.exp-status[data-status='warning'] { color:#d9b15b; }
.exp-status[data-status='warning'] .cw-status-dot { background:#d5a541; box-shadow:0 0 0 3px rgba(213,165,65,0.15); }
.exp-status[data-status='blocked'] { color:#ef8a87; }
.exp-status[data-status='blocked'] .cw-status-dot { background:#e25b56; box-shadow:0 0 0 3px rgba(226,91,86,0.15); }
.exp-status[data-status='empty'] { color:var(--text-tertiary); }
.exp-status[data-status='empty'] .cw-status-dot { background:var(--text-tertiary); box-shadow:none; }

/* Bordered card wrapping the body -- same frame treatment as the SVG panel editor. */
.panel-export .wb-body-wrap { background:var(--surface); border:1px solid var(--border); border-radius:4px; container-type:inline-size; }
.exp-body { gap:0; padding:0; }
.exp-card { min-height:100%; flex:1 0 auto; box-sizing:border-box; display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); grid-template-rows:auto minmax(0,1fr) auto auto; align-items:start; gap:0 14px; padding:12px; }
.panel-export .exp-mode-png { display:none; }
.panel-export:has(#exportFormatPng:checked) .exp-mode-svg { display:none; }
.panel-export:has(#exportFormatPng:checked) .controls > .exp-mode-png { display:flex; }
.panel-export:has(#exportFormatPng:checked) .exp-png-card { display:grid; }
.panel-export:has(#exportFormatPng:checked) .exp-svg-status-text { display:none; }
.panel-export:has(#exportFormatPng:checked) .exp-png-status-text { display:inline; }
/* ICO mode reveals only the ICO action/status/card and hides both SVG and PNG surfaces.
   The card carries .exp-mode-ico (hidden by default) and is re-shown as a grid here; PNG surfaces
   stay hidden by their own default rule, so no extra hide rule for them is needed. */
.panel-export .exp-mode-ico { display:none; }
.panel-export:has(#exportFormatIco:checked) .exp-mode-svg { display:none; }
.panel-export:has(#exportFormatIco:checked) .controls > .exp-mode-ico { display:flex; }
.panel-export:has(#exportFormatIco:checked) .ico-export-card { display:grid; }
.panel-export:has(#exportFormatIco:checked) .exp-svg-status-text { display:none; }
.panel-export:has(#exportFormatIco:checked) .exp-ico-status-text { display:inline; }
.exp-zone { min-width:0; grid-row:1; display:flex; flex-direction:column; gap:7px; }
.exp-zone-options { border-left:1px solid var(--border); padding-left:12px; }
.exp-zone-options .wb-group { gap:6px; }
.exp-zone-options .wb-group-title { font-size:9px; line-height:1; letter-spacing:0.08em; color:var(--text-tertiary); }

.exp-field { min-width:0; display:flex; flex-direction:column; gap:4px; }
.exp-field-label { font-size:10px; line-height:1; font-weight:700; color:var(--text-secondary); cursor:default; -webkit-user-select:none; user-select:none; }
/* The top four settings use one compact label/control row and a shared label column,
   so their dropdowns and inputs begin at the same horizontal position. */
.exp-field-inline { display:grid; grid-template-columns:86px minmax(0,max-content); align-items:center; justify-content:start; column-gap:8px; }
.exp-field-inline .exp-field-label { white-space:nowrap; }
.exp-field-inline .exp-select-wrap { width:max-content; max-width:100%; }
.exp-field-inline .exp-select { width:auto; max-width:100%; }
.exp-field-padding .exp-input-wrap { width:72px; }
/* Export Area is a short radio list (Artboard / Ink bounds / Selected layers) rather than a dropdown, so
   every choice is visible at once; in the SVG panel its label tops the list in the shared label column. */
.exp-field-area { align-items:start; }
.exp-field-area > .exp-field-label { padding-top:2px; }
.exp-radio-list { display:flex; flex-direction:column; align-items:flex-start; gap:6px; min-width:0; }
.exp-radio { position:relative; display:flex; align-items:center; gap:6px; max-width:100%; font-size:10px; line-height:1.35; font-weight:600; color:var(--text-secondary); white-space:nowrap; cursor:pointer; -webkit-user-select:none; user-select:none; transition:color 0.15s; }
.exp-radio:hover { color:var(--text); }
.exp-radio input { position:absolute; width:1px; height:1px; margin:0; padding:0; opacity:0; pointer-events:none; }
.exp-radio:has(input:checked) { color:var(--text); }
.exp-radio:has(input:disabled) { color:var(--text-tertiary); cursor:default; }
.exp-radio input:disabled + .exp-radio-dot { opacity:0.45; }
.exp-field-precision .exp-input-wrap { width:44px; }
.exp-scaling-section { width:100%; box-sizing:border-box; margin-top:2px; padding-top:8px; border-top:1px solid var(--border); }
.exp-scale-toggle { width:max-content; max-width:100%; justify-content:flex-start; align-self:flex-start; }
.exp-field-row { display:grid; grid-template-columns:minmax(0,1fr); gap:8px; }
.exp-zone-output .exp-field-row .exp-input-wrap { width:84px; }

@container (min-width:340px) {
  .exp-card { gap:0 20px; }
  .exp-zone-options { padding-left:12px; }
  .exp-field-row { grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
}

.exp-select-wrap { position:relative; display:block; min-width:0; }
.exp-select { width:100%; height:24px; box-sizing:border-box; appearance:none; -webkit-appearance:none; padding:0 20px 0 6px; color:var(--text); background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; box-shadow:inset 0 1px 0 rgba(255,255,255,0.04); font:600 11px var(--font); cursor:pointer; outline:none; transition:background 0.12s, border-color 0.12s, box-shadow 0.12s; }
.exp-select:hover:not(:disabled) { border-color:rgba(255,255,255,0.22); background:var(--bg-secondary); }
.exp-select:focus-visible { background:var(--bg-secondary); border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-dim), inset 0 1px 0 rgba(255,255,255,0.05); }
.exp-select option { color:var(--text); background:var(--surface-raised); }
.exp-select option:disabled { color:var(--text-tertiary); }
.exp-select-wrap::after { content:''; position:absolute; right:7px; top:50%; width:5px; height:5px; margin-top:-4px; border-right:1.5px solid var(--text-tertiary); border-bottom:1.5px solid var(--text-tertiary); transform:rotate(45deg); pointer-events:none; }

.exp-input-wrap { display:flex; align-items:center; gap:4px; height:24px; padding:0 6px; box-sizing:border-box; background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; box-shadow:inset 0 1px 0 rgba(255,255,255,0.04); transition:background 0.12s, border-color 0.12s, box-shadow 0.12s; }
.exp-input-wrap:hover { background:var(--bg-secondary); border-color:rgba(255,255,255,0.22); }
.exp-input-wrap:focus-within { background:var(--bg-secondary); border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-dim), inset 0 1px 0 rgba(255,255,255,0.05); }
.exp-input { flex:1 1 auto; min-width:0; width:100%; background:transparent; border:none; outline:none; color:var(--text); font:600 11.5px monospace; font-variant-numeric:tabular-nums; text-align:right; padding:0; }
.exp-input::placeholder { color:var(--text-tertiary); font-weight:500; }
.exp-input::-webkit-outer-spin-button, .exp-input::-webkit-inner-spin-button { -webkit-appearance:none; margin:0; }
.exp-input[type=number] { -moz-appearance:textfield; }
.exp-input-text { font:600 11px var(--font); text-align:left; }
.exp-unit { flex:0 0 auto; font-size:10px; font-weight:400; color:var(--text-tertiary); pointer-events:none; }
/* A dependency-disabled field stays readable and keeps its native disabled semantics; the reason
   is always written out in .exp-note, never hidden behind hover only. */
.exp-field.is-disabled .exp-field-label { color:var(--text-tertiary); }
.exp-field.is-disabled .exp-input-wrap { opacity:0.6; }
.exp-input:disabled { cursor:not-allowed; }

.exp-note { margin:0; font-size:9.5px; line-height:1.4; color:var(--text-tertiary); }
.exp-note[hidden] { display:none; }
/* Names a control for assistive technology without an aria-label, which would otherwise suppress
   the readings the preflight footer exists to report. */
.exp-sr { position:absolute; width:1px; height:1px; margin:-1px; padding:0; overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0; }

/* Same checkbox art as the rest of the app, but the input stays in the accessibility tree and
   focusable instead of display:none, so every option is reachable and shows a focus ring. */
.exp-check-list { display:flex; flex-direction:column; gap:5px; padding-left:12px; }
.exp-check { position:relative; align-items:flex-start; padding:0 1px; white-space:normal; line-height:1.35; }
.exp-check > .cb-custom { margin-top:1px; }
.exp-check input { display:block; position:absolute; width:1px; height:1px; margin:0; padding:0; opacity:0; pointer-events:none; }
.exp-check input:focus-visible + .cb-custom { outline:2px solid var(--accent-hover); outline-offset:2px; }
.exp-check input:disabled + .cb-custom { opacity:0.4; }
.exp-check:has(input:disabled) { color:var(--text-tertiary); cursor:default; }
.exp-prefix-slot { height:24px; box-sizing:border-box; padding:0 1px; }
.exp-prefix-input-wrap { width:100%; }
.exp-prefix-input-wrap[hidden] { display:none; }

.exp-preflight { grid-column:1 / -1; grid-row:4; width:100%; box-sizing:border-box; margin-top:10px; display:flex; flex-direction:column; gap:7px; padding:8px 9px; text-align:left; color:var(--text-secondary); background:rgba(0,0,0,0.14); border:1px solid var(--border); border-radius:4px; font-family:var(--font); cursor:pointer; transition:background 0.15s, border-color 0.15s; }
.exp-preflight:hover:not(:disabled) { background:rgba(0,0,0,0.22); border-color:var(--border-strong); }
.exp-preflight:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.exp-preflight:disabled { opacity:0.5; cursor:default; }
.exp-preflight-head { display:flex; align-items:center; justify-content:space-between; gap:8px; }
.exp-preflight-state { min-width:0; display:inline-flex; align-items:center; gap:6px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:10px; font-weight:650; color:var(--text); }
.exp-preflight[data-state='warning'] .exp-preflight-state { color:#d9b15b; }
.exp-preflight[data-state='warning'] .cw-status-dot { background:#d5a541; box-shadow:0 0 0 3px rgba(213,165,65,0.15); }
.exp-preflight[data-state='blocked'] .exp-preflight-state { color:#ef8a87; }
.exp-preflight[data-state='blocked'] .cw-status-dot { background:#e25b56; box-shadow:0 0 0 3px rgba(226,91,86,0.15); }
.exp-preflight[data-state='checking'] .cw-status-dot { background:#d5a541; box-shadow:0 0 0 3px rgba(213,165,65,0.15); }
/* Measurements from the previous settled candidate stay readable while a newer one is prepared,
   but they are dimmed so they are never mistaken for the current result. */
.exp-preflight[data-state='checking'] .exp-preflight-grid, .exp-preflight[data-state='checking'] .exp-preflight-size { opacity:0.45; }
.exp-preflight[data-state='empty'] .cw-status-dot { background:var(--text-tertiary); box-shadow:none; }
.exp-preflight-size { flex:0 0 auto; font:600 10px monospace; font-variant-numeric:tabular-nums; color:var(--text-secondary); }
.exp-preflight-grid { display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:6px; }
.exp-preflight-item { min-width:0; display:flex; flex-direction:column; gap:2px; }
.exp-preflight-item > span { font-size:8.5px; font-weight:700; letter-spacing:0.6px; text-transform:uppercase; color:var(--text-tertiary); }
.exp-preflight-item > strong { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font:600 10.5px monospace; font-variant-numeric:tabular-nums; color:var(--text); }

.exp-message { grid-column:1 / -1; grid-row:3; margin:8px 0 0; font-size:10px; line-height:1.4; color:var(--text-secondary); overflow-wrap:anywhere; }
.exp-message[hidden] { display:none; }
.exp-message[data-tone='error'] { color:#ef8a87; }
.exp-message[data-tone='ok'] { color:var(--success); }

/* PNG Export -- the finalize-card language shared with SVG and ICO: a settings rail exactly as wide as
   its widest control (five-digit sizes never truncate), the zoomable preview taking the rest behind a
   divider, and a one-line Output footer across both. The row never shrinks below either column's real
   minimum; the preview viewer flexes to whatever height is left. */
.exp-png-card { min-height:100%; flex:1 0 auto; box-sizing:border-box; grid-template-columns:max-content minmax(0,1fr); grid-template-rows:minmax(auto,1fr) auto; align-items:stretch; gap:12px 14px; padding:12px; }
.exp-png-settings { min-width:0; grid-column:1; grid-row:1; display:flex; flex-direction:column; gap:10px; }
.exp-png-area { display:flex; flex-direction:column; gap:7px; }
.exp-png-layers-check { width:max-content; max-width:100%; margin-top:2px; }
.exp-png-divider { height:1px; flex:0 0 1px; background:var(--border); }

/* Width / Height side by side, each sized for five digits (the 16,384 px limit). The link glyph between
   them and the caption say the ratio is locked, like the Properties panel's Width / Height row. */
.exp-png-size { display:flex; flex-direction:column; }
.exp-png-size-grid { display:grid; grid-template-columns:auto 14px auto; align-items:center; gap:4px; }
.exp-png-size-grid > .exp-field-label { grid-area:1 / 1; }
.exp-png-size-grid > .exp-png-height-label { grid-area:1 / 3; }
.exp-png-dim { width:66px; }
.exp-png-dim-w { grid-area:2 / 1; }
.exp-png-dim-h { grid-area:2 / 3; }
.exp-png-link { grid-area:2 / 2; width:13px; height:13px; justify-self:center; color:var(--text-tertiary); }
.exp-png-ratio-note { margin-top:5px; }
.exp-png-size.is-disabled .exp-field-label { color:var(--text-tertiary); }
.exp-png-size.is-disabled .exp-png-dim { opacity:0.6; }
/* Scale chips multiply the area's natural size; the one matching the current size reads pressed. */
.exp-png-scale { display:flex; gap:4px; margin-top:8px; }
.exp-png-scale-btn { min-width:24px; height:18px; padding:0 5px; box-sizing:border-box; font:600 10px/16px monospace; font-variant-numeric:tabular-nums; color:var(--text-secondary); background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; cursor:pointer; transition:color 0.12s, background 0.12s, border-color 0.12s; touch-action:manipulation; }
.exp-png-scale-btn:hover:not(:disabled) { color:var(--text); background:var(--bg-hover); border-color:rgba(255,255,255,0.22); }
.exp-png-scale-btn[aria-pressed='true'], .exp-png-scale-btn[aria-pressed='true']:hover:not(:disabled) { color:var(--accent); background:var(--accent-dim); border-color:rgba(0,122,255,0.38); }
.exp-png-scale-btn:focus-visible { outline:2px solid var(--accent-hover); outline-offset:1px; }
.exp-png-scale-btn:disabled { opacity:0.4; cursor:default; }
.exp-png-crisp-check { width:max-content; max-width:100%; }
.exp-png-message:not([hidden]) { margin-top:auto; }
.exp-png-preflight { grid-column:1 / -1; grid-row:2; width:100%; box-sizing:border-box; display:flex; align-items:center; justify-content:space-between; gap:10px; min-width:0; padding:8px; color:var(--text-secondary); background:rgba(0,0,0,0.14); border:1px solid var(--border); border-radius:4px; }
.exp-png-preflight-label { flex:0 0 auto; font-size:8.5px; font-weight:700; letter-spacing:0.6px; text-transform:uppercase; color:var(--text-tertiary); }
.exp-png-preflight strong { min-width:0; text-align:right; font:600 10px/1.4 monospace; font-variant-numeric:tabular-nums; color:var(--text); overflow-wrap:anywhere; }

/* Right -- a mini viewer: the stage draws only what is on screen into one canvas (smooth up to 100%,
   real export pixels above it), with the canvas status bar's zoom controls docked beneath. */
.exp-png-preview { min-width:0; grid-column:2; grid-row:1; display:flex; flex-direction:column; gap:8px; padding-left:14px; border-left:1px solid var(--border); }
.exp-png-preview-head { min-width:0; min-height:18px; display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:4px 8px; }
.exp-png-columns { display:flex; align-items:center; gap:6px; min-width:0; font-size:9.5px; font-weight:600; color:var(--text-tertiary); }
.exp-png-columns[hidden] { display:none; }
.exp-png-columns-slider { width:60px; height:16px; margin:0; background:transparent; appearance:none; -webkit-appearance:none; cursor:pointer; }
.exp-png-columns-slider:focus-visible { outline:none; }
.exp-png-columns-slider::-webkit-slider-runnable-track { height:3px; border-radius:2px; background:rgba(255,255,255,0.14); }
.exp-png-columns-slider::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:11px; height:11px; margin-top:-4px; border-radius:50%; background:#fff; border:1.5px solid var(--accent); box-sizing:border-box; box-shadow:0 1px 3px rgba(0,0,0,0.5); transition:box-shadow 0.12s; }
.exp-png-columns-slider:focus-visible::-webkit-slider-thumb { box-shadow:0 0 0 3px var(--accent-dim), 0 1px 3px rgba(0,0,0,0.5); }
.exp-png-columns-slider::-moz-range-track { height:3px; border-radius:2px; background:rgba(255,255,255,0.14); }
.exp-png-columns-slider::-moz-range-thumb { width:11px; height:11px; border-radius:50%; background:#fff; border:1.5px solid var(--accent); box-sizing:border-box; }
.exp-png-columns-value { min-width:7px; font:600 10px/1 monospace; color:var(--text); text-align:right; }

.exp-png-viewer { flex:1 1 auto; min-height:150px; display:flex; flex-direction:column; overflow:hidden; background:rgba(0,0,0,0.18); border:1px solid var(--border); border-radius:5px; container:png-viewer / inline-size; }
/* Size containment keeps the drawn frame out of the stage's intrinsic size, so it never holds it open. */
.exp-png-preview-stage { position:relative; flex:1 1 auto; min-height:110px; display:flex; align-items:center; justify-content:center; overflow:hidden; contain:size layout paint; touch-action:none; }
.exp-png-preview-stage[data-pan='true'] { cursor:grab; }
.exp-png-preview-stage[data-panning='true'] { cursor:grabbing; }
.exp-png-view-canvas { position:absolute; inset:0; width:100%; height:100%; display:block; transition:opacity 0.15s ease; -webkit-user-drag:none; user-select:none; }
.exp-png-view-canvas[hidden] { display:none; }
.exp-png-preview-stage[data-state='checking'] .exp-png-view-canvas { opacity:0.45; }
.exp-png-preview-empty { position:relative; margin:0; max-width:150px; padding:0 8px; color:var(--text-tertiary); font-size:9.5px; line-height:1.45; text-align:center; }
.exp-png-preview-empty[hidden] { display:none; }
.exp-png-toolbar { flex:0 0 auto; height:26px; display:flex; align-items:center; gap:2px; padding:0 4px; box-sizing:border-box; background:rgba(26,26,30,0.72); border-top:1px solid var(--border); }
.exp-png-toolbar[hidden] { display:none; }
.exp-png-toolbar-gap { flex:1 1 auto; }
.exp-png-toolbar .cs-zoom { min-width:46px; }
.exp-png-toolbar .cs-zoom-input { width:46px; }
.exp-png-toolbar .cs-zoom-input[hidden] { display:none; }
.exp-png-actual-btn { width:auto; min-width:26px; padding:0 5px; font:600 10px/1 monospace; }
.exp-png-toolbar .cs-btn:disabled, .exp-png-toolbar .cs-zoom:disabled { opacity:0.4; background:transparent; cursor:default; }
.exp-png-toolbar .cs-btn:focus-visible, .exp-png-toolbar .cs-zoom:focus-visible { outline:2px solid var(--accent-hover); outline-offset:-1px; }
/* A narrow viewer keeps the essentials: the wheel still zooms, so the step buttons go first. */
@container png-viewer (max-width:150px) { #pngZoomOut, #pngZoomIn { display:none; } }
@container png-viewer (max-width:110px) { #pngZoomValue, #pngZoomInput { display:none; } }

/* Layers mode -- a grid of cards (columns from the slider) scrolling under the app's custom
   scrollbar; each card shows the file name the ZIP will use and its pixel size. */
.exp-png-layer-wrap { position:absolute; inset:0; }
.exp-png-layer-wrap[hidden] { display:none; }
.exp-png-layer-previews { position:absolute; inset:0; box-sizing:border-box; padding:8px 16px 8px 8px; overflow-y:auto; overflow-x:hidden; overscroll-behavior:contain; -ms-overflow-style:none; scrollbar-width:none; display:grid; grid-template-columns:repeat(var(--png-columns,3), minmax(0,1fr)); align-content:start; gap:10px 8px; }
.exp-png-layer-previews::-webkit-scrollbar { display:none; width:0; height:0; }
.exp-png-layer-wrap > .custom-scroll-track { top:4px; bottom:4px; right:2px; }
.exp-png-layer-card { min-width:0; display:flex; flex-direction:column; gap:4px; content-visibility:auto; contain-intrinsic-size:auto 120px; }
.exp-png-layer-art { position:relative; width:100%; aspect-ratio:var(--png-cell-ratio,1); display:flex; align-items:center; justify-content:center; box-sizing:border-box; padding:4px; overflow:hidden; background:rgba(255,255,255,0.025); border:1px solid var(--border); border-radius:4px; }
.exp-png-layer-image { display:block; max-width:100%; max-height:100%; background:repeating-conic-gradient(#34343a 0% 25%, #29292f 0% 50%) 0 0/8px 8px; outline:1px solid rgba(255,255,255,0.1); transition:opacity 0.15s ease; -webkit-user-drag:none; user-select:none; }
.exp-png-layer-image[data-fit='width'] { width:100%; height:auto; }
.exp-png-layer-image[data-fit='height'] { width:auto; height:100%; }
.exp-png-layer-image[hidden] { display:none; }
.exp-png-layer-card[aria-busy='true'] .exp-png-layer-image { opacity:0.35; }
.exp-png-layer-placeholder { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; margin:0; padding:6px; box-sizing:border-box; color:var(--text-tertiary); font-size:9px; line-height:1.35; text-align:center; }
.exp-png-layer-placeholder[hidden] { display:none; }
.exp-png-layer-name { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text-secondary); font-size:9.5px; line-height:1.2; font-weight:650; }
.exp-png-layer-size { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font:600 9px/1 monospace; font-variant-numeric:tabular-nums; color:var(--text-tertiary); }

/* =========================================
   ICO Export panel (js/ico-export.js)
   ========================================= */
/* The same finalize-card language as SVG and PNG: a size rail exactly as wide as its widest row
   (so no value ever truncates), the exact-pixel preview taking the remaining width, and PNG's
   one-line Output footer spanning both. The card fills the body and never shrinks below the
   preview column's real minimum (header, smallest well, chips, mode control); within that, only
   the size list scrolls and the preview well takes whatever height is left. */
.ico-export-card { flex:1 1 auto; box-sizing:border-box; grid-template-columns:max-content minmax(0,1fr); grid-template-rows:minmax(auto,1fr) auto auto; align-items:stretch; gap:0 14px; padding:12px; }

/* Left -- size rail. Every line (Select all, sizes, Add size) is one 19px .ico-row, so the
   checkbox column, numbers, units and tags share edges. The number slot is 4ch wide and right
   aligned, which keeps "px" in one column and leaves room for a 4-digit value. */
/* height:0 + min-height:100% keeps the rail out of the row's intrinsic height (the preview column
   alone sets the card's minimum) while still filling the row once it is sized. */
.ico-sizes { min-width:0; height:0; min-height:100%; grid-column:1; grid-row:1; display:flex; flex-direction:column; }
.ico-row { position:relative; display:flex; align-items:center; height:19px; padding:0 5px; box-sizing:border-box; border-radius:4px; font:600 10px/1 var(--font); color:var(--text-secondary); white-space:nowrap; cursor:pointer; -webkit-user-select:none; user-select:none; transition:background 0.12s, color 0.12s; }
.ico-row:hover { color:var(--text); background:rgba(255,255,255,0.04); }
.ico-row > input { position:absolute; top:0; left:0; width:1px; height:1px; margin:0; padding:0; opacity:0; pointer-events:none; }
.ico-row > .cb-custom { margin-right:8px; }
.ico-row > input:checked + .cb-custom { border-color:var(--accent); background:var(--accent); }
.ico-row > input:checked + .cb-custom::after { content:''; position:absolute; top:0; left:3px; width:3px; height:7px; border:solid #fff; border-width:0 2px 2px 0; transform:rotate(45deg); }
.ico-row > input:focus-visible + .cb-custom { outline:2px solid var(--accent-hover); outline-offset:2px; }
.ico-select-all { flex:0 0 auto; margin-bottom:4px; }
.ico-select-all::after { content:''; position:absolute; left:5px; right:0; bottom:-3px; height:1px; background:var(--border); pointer-events:none; }

/* The list scrolls inside its own wrap with the app's custom scrollbar (the Properties panel's):
   the track sits in a 12px gutter between the rows and the column edge; the native bar is hidden. */
.ico-size-scroll { position:relative; flex:0 1 auto; min-height:38px; display:flex; flex-direction:column; padding-right:12px; }
.ico-size-scroll > .custom-scroll-track { top:3px; bottom:1px; right:0; }
.ico-size-list { flex:0 1 auto; min-height:0; margin:0; padding:2px 0 0; list-style:none; overflow-y:auto; overscroll-behavior:contain; -ms-overflow-style:none; scrollbar-width:none; }
.ico-size-list::-webkit-scrollbar { display:none; width:0; height:0; }
.ico-size-row { position:relative; }
.ico-size-num { width:4ch; text-align:right; font:600 11px/1 monospace; font-variant-numeric:tabular-nums; color:var(--text); }
.ico-size-unit { margin-left:3px; font-size:9.5px; font-weight:500; color:var(--text-tertiary); }
.ico-size-enc { margin-left:auto; padding-left:14px; font:600 8.5px/1 monospace; letter-spacing:0.06em; color:var(--text-tertiary); transition:opacity 0.12s; }
/* An excluded size stays legible but recedes, so the included set reads at a glance. */
.ico-size-row:not(:has(.ico-size-check:checked)) .ico-size-num { color:var(--text-secondary); font-weight:500; }
.ico-size-row:not(:has(.ico-size-check:checked)) .ico-size-enc { opacity:0.6; }
/* Custom rows trade their storage tag for a remove button while pointed at or focused; the tag
   column already reserves the space, so nothing shifts. */
.ico-size-remove { position:absolute; top:2px; right:3px; width:15px; height:15px; display:flex; align-items:center; justify-content:center; padding:0; color:var(--text-tertiary); background:transparent; border:0; border-radius:3px; font:500 13px/1 var(--font); cursor:pointer; opacity:0; transition:opacity 0.12s, color 0.12s, background 0.12s; }
.ico-size-row.is-custom:hover .ico-size-remove, .ico-size-remove:focus-visible { opacity:1; }
.ico-size-row.is-custom:hover .ico-size-enc, .ico-size-row.is-custom:has(.ico-size-remove:focus-visible) .ico-size-enc { opacity:0; }
.ico-size-remove:hover { color:#ef8a87; background:rgba(226,91,86,0.12); }
.ico-size-remove:focus-visible { outline:2px solid var(--accent-hover); outline-offset:0; }
/* A size that was just added (or re-selected by typing it) pulses once where it landed. */
.ico-size-row.is-new > .ico-row { animation:ico-row-in 0.9s ease-out 1; }
@keyframes ico-row-in { from { background:rgba(0,122,255,0.24); } to { background:transparent; } }

/* Add size -- a dashed box under the list: a checkbox-sized plus box, then the label. Opening it
   swaps the label for a px field and an Add button in the same box, which turns solid accent.
   Both states share one grid cell (the closed one is only made invisible), so the column is
   always wide enough for the open state and opening never shifts the divider. The plus box sits
   on the checkbox column and the typed digits end on the number column's edge. */
.ico-add { flex:0 0 auto; display:grid; margin-top:5px; border:1px dashed var(--border-strong); border-radius:5px; transition:border-color 0.12s, background 0.12s; }
.ico-add:hover { border-color:rgba(255,255,255,0.28); background:rgba(255,255,255,0.03); }
.ico-add:has(.ico-add-field:not([hidden])) { border-style:solid; border-color:var(--accent); background:var(--bg-secondary); }
.ico-add-btn, .ico-add-field { grid-area:1 / 1; display:flex; align-items:center; min-width:0; height:24px; padding:0 4px; box-sizing:border-box; font:600 10px/1 var(--font); white-space:nowrap; }
.ico-add-btn[hidden], .ico-add-field[hidden] { visibility:hidden; }
.ico-add-btn { width:100%; border:0; border-radius:4px; background:transparent; color:var(--text-secondary); text-align:left; cursor:pointer; transition:color 0.12s; }
.ico-add:hover .ico-add-btn { color:var(--text); }
.ico-add-btn:focus-visible { outline:2px solid var(--accent-hover); outline-offset:1px; }
/* The same box as .cb-custom, carrying a plus; whole-pixel bars stay crisp at 1x. */
.ico-add-plus { position:relative; width:12px; height:12px; flex:0 0 12px; margin-right:8px; box-sizing:border-box; border:1px solid var(--border-strong); border-radius:3px; background:var(--surface-raised); color:var(--text-secondary); transition:border-color 0.12s, background 0.12s, color 0.12s; }
.ico-add-plus::before, .ico-add-plus::after { content:''; position:absolute; background:currentColor; border-radius:1px; }
.ico-add-plus::before { left:2px; top:4px; width:6px; height:2px; }
.ico-add-plus::after { left:4px; top:2px; width:2px; height:6px; }
.ico-add:hover .ico-add-plus { border-color:rgba(255,255,255,0.28); color:var(--text); }
.ico-add-field .ico-add-plus, .ico-add:hover .ico-add-field .ico-add-plus { color:#fff; border-color:var(--accent); background:var(--accent); }
.ico-add-input-wrap { height:18px; margin:0 6px 0 -6px; padding:0 5px; gap:3px; }
/* The open box is already accent-framed, so the field keeps its accent border but drops the glow. */
.ico-add-input-wrap:focus-within { box-shadow:none; }
.ico-add-input-wrap .exp-input { flex:0 0 4ch; width:4ch; font-size:11px; }
.ico-add-input-wrap .exp-input::placeholder { font:500 8.5px var(--font); }
.ico-add-input-wrap .exp-unit { font-size:9.5px; font-weight:500; }
.ico-add-field[data-invalid='true'] .ico-add-input-wrap { border-color:#e25b56; box-shadow:0 0 0 2px rgba(226,91,86,0.18); }
.ico-add-commit { flex:0 0 auto; margin-left:auto; height:18px; padding:0 8px; font:600 9.5px/1 var(--font); color:var(--accent); background:var(--accent-dim); border:1px solid rgba(0,122,255,0.38); border-radius:4px; cursor:pointer; transition:color 0.12s, background 0.12s, border-color 0.12s, opacity 0.12s; touch-action:manipulation; }
.ico-add-commit:hover:not(:disabled) { color:#fff; background:var(--accent); border-color:var(--accent); }
.ico-add-commit:focus-visible { outline:2px solid var(--accent-hover); outline-offset:1px; }
.ico-add-commit:disabled { opacity:0.45; cursor:default; }

/* Right -- preview. The well matches PNG's preview stage; the frame inside it is drawn at a
   whole number of screen pixels per icon pixel, so small sizes show their true pixel grid. */
.ico-preview { min-width:0; grid-column:2; grid-row:1; display:flex; flex-direction:column; gap:8px; padding-left:14px; border-left:1px solid var(--border); container:ico-preview / inline-size; }
.ico-preview-head { flex:0 0 auto; display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:4px 8px; }
.ico-zoom { flex:0 0 auto; display:flex; margin:0; padding:0; border:1px solid var(--border-strong); border-radius:4px; background:var(--surface-raised); overflow:hidden; }
.ico-zoom-option { position:relative; display:block; cursor:pointer; }
.ico-zoom-option + .ico-zoom-option { border-left:1px solid var(--border-strong); }
.ico-zoom-option input { position:absolute; width:1px; height:1px; margin:0; padding:0; opacity:0; pointer-events:none; }
.ico-zoom-option span { display:block; min-width:20px; height:16px; padding:0 5px; box-sizing:border-box; font:600 9.5px/16px monospace; font-variant-numeric:tabular-nums; text-align:center; color:var(--text-tertiary); transition:color 0.12s, background 0.12s; }
.ico-zoom-option:hover span { color:var(--text); }
.ico-zoom-option input:checked + span { color:var(--accent); background:var(--accent-dim); }
.ico-zoom-option input:focus-visible + span { outline:2px solid var(--accent-hover); outline-offset:-2px; }

/* Size containment keeps the drawn canvas out of the well's intrinsic size; otherwise the frame
   sized to fit the well would also hold the well open and it could never shrink. */
.ico-preview-stage { position:relative; flex:1 1 auto; min-width:0; min-height:72px; display:flex; align-items:center; justify-content:center; box-sizing:border-box; padding:8px; overflow:hidden; contain:size layout paint; background:rgba(0,0,0,0.18); border:1px solid var(--border); border-radius:5px; }
.ico-preview-canvas { display:block; flex:0 0 auto; image-rendering:pixelated; background:repeating-conic-gradient(#34343a 0% 25%, #29292f 0% 50%) 0 0/8px 8px; outline:1px solid rgba(255,255,255,0.12); box-shadow:0 5px 16px rgba(0,0,0,0.3); transition:opacity 0.15s ease; -webkit-user-drag:none; user-select:none; }
.ico-preview-canvas[data-smooth='true'] { image-rendering:auto; }
.ico-preview-canvas[hidden] { display:none; }
/* A replacement frame keeps the prior exact pixels visible but dimmed while it prepares. */
.ico-preview-stage[data-state='checking'] .ico-preview-canvas { opacity:0.45; }
.ico-preview-empty { margin:0; max-width:150px; color:var(--text-tertiary); font-size:9.5px; line-height:1.45; text-align:center; }
.ico-preview-empty[hidden] { display:none; }

/* One chip per included size, largest first like the list; a native radio group, so arrow keys
   step through them. */
.ico-chips { flex:0 0 auto; display:flex; flex-wrap:wrap; gap:4px; margin:0; padding:0; border:0; min-width:0; }
.ico-chips[hidden] { display:none; }
.ico-chip { position:relative; display:block; cursor:pointer; }
.ico-chip input { position:absolute; width:1px; height:1px; margin:0; padding:0; opacity:0; pointer-events:none; }
.ico-chip span { display:block; min-width:24px; height:18px; padding:0 5px; box-sizing:border-box; font:600 10px/16px monospace; font-variant-numeric:tabular-nums; text-align:center; color:var(--text-secondary); background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; transition:color 0.12s, background 0.12s, border-color 0.12s; }
.ico-chip:hover span { color:var(--text); background:var(--bg-hover); border-color:rgba(255,255,255,0.22); }
.ico-chip input:checked + span { color:var(--accent); background:var(--accent-dim); border-color:rgba(0,122,255,0.38); }
.ico-chip input:focus-visible + span { outline:2px solid var(--accent-hover); outline-offset:1px; }

/* Non-square Artboard -- one segmented row; each option's glyph shows what happens to a wide
   Artboard. Hidden while the Artboard is square, where all three modes are identical. */
.ico-fit { flex:0 0 auto; display:block; min-width:0; margin:0; padding:0; border:0; }
.ico-fit[hidden] { display:none; }
.ico-fit > legend { padding:0; margin-bottom:6px; }
.ico-seg { display:flex; min-width:0; }
.ico-seg-option { position:relative; flex:1 1 0; min-width:0; height:24px; display:flex; align-items:center; justify-content:center; gap:5px; padding:0 6px; box-sizing:border-box; color:var(--text-secondary); background:var(--surface-raised); border:1px solid var(--border-strong); font:600 10px/1 var(--font); white-space:nowrap; cursor:pointer; transition:color 0.12s, background 0.12s, border-color 0.12s; }
.ico-seg-option + .ico-seg-option { margin-left:-1px; }
.ico-seg-option:first-child { border-radius:4px 0 0 4px; }
.ico-seg-option:last-child { border-radius:0 4px 4px 0; }
.ico-seg-option:hover { z-index:1; color:var(--text); background:var(--bg-hover); border-color:rgba(255,255,255,0.22); }
.ico-seg-option input { position:absolute; width:1px; height:1px; margin:0; padding:0; opacity:0; pointer-events:none; }
.ico-seg-option .icon-svg { width:14px; height:14px; flex:0 0 14px; }
.ico-seg-option span { min-width:0; overflow:hidden; text-overflow:ellipsis; }
.ico-seg-option:has(input:checked) { z-index:2; color:var(--accent); background:var(--accent-dim); border-color:rgba(0,122,255,0.38); }
.ico-seg-option:has(input:focus-visible) { z-index:3; outline:2px solid var(--accent-hover); outline-offset:1px; }
/* A narrow preview column keeps the glyphs and moves the words to the tooltip and screen readers. */
@container ico-preview (max-width:170px) {
  .ico-seg-option { padding:0 4px; }
  .ico-seg-option span { position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); white-space:nowrap; }
}

/* Footer -- PNG's one-line Output summary. Preparation progress and Cancel / Retry take the
   summary's place in the same line, so the card never changes height. */
.ico-message { grid-column:1 / -1; grid-row:2; margin:8px 0 0; font-size:10px; line-height:1.4; color:var(--text-secondary); overflow-wrap:anywhere; }
.ico-message[hidden] { display:none; }
.ico-message[data-tone='error'] { color:#ef8a87; }
.ico-message[data-tone='ok'] { color:var(--success); }
.ico-preflight { grid-column:1 / -1; grid-row:3; width:100%; min-width:0; box-sizing:border-box; margin-top:10px; display:flex; align-items:center; gap:10px; min-height:32px; padding:6px 8px; color:var(--text-secondary); background:rgba(0,0,0,0.14); border:1px solid var(--border); border-radius:4px; }
.ico-preflight-label { flex:0 0 auto; margin-right:auto; font-size:8.5px; font-weight:700; letter-spacing:0.6px; text-transform:uppercase; color:var(--text-tertiary); }
.ico-preflight-summary { min-width:0; text-align:right; font:600 10px/1.4 monospace; font-variant-numeric:tabular-nums; color:var(--text); overflow-wrap:anywhere; }
.ico-preflight-summary[hidden] { display:none; }
.ico-preflight[data-state='warning'] .ico-preflight-summary { color:#d9b15b; }
.ico-preflight-progress { flex:1 1 auto; min-width:0; display:flex; align-items:center; gap:8px; }
.ico-preflight-progress[hidden] { display:none; }
.ico-progress-bar { flex:1 1 auto; min-width:24px; height:4px; border-radius:3px; background:rgba(255,255,255,0.08); overflow:hidden; }
.ico-progress-fill { display:block; height:100%; width:0%; border-radius:3px; background:var(--accent); transition:width 0.2s ease; }
.ico-progress-label { flex:0 1 auto; min-width:0; font-size:9.5px; font-weight:600; line-height:1.35; color:var(--text-secondary); }
/* A blocked preparation drops the bar and lets its reason use the line. */
.ico-preflight[data-state='blocked'] .ico-progress-bar { display:none; }
.ico-preflight[data-state='blocked'] .ico-progress-label { flex:1 1 auto; text-align:right; color:#ef8a87; overflow-wrap:anywhere; }
.ico-preflight[data-cancelled='true'] .ico-progress-label { color:var(--text-secondary); }
.ico-preflight-btn { flex:0 0 auto; height:20px; padding:0 8px; font:600 9.5px var(--font); color:var(--text-secondary); background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; cursor:pointer; transition:0.13s; touch-action:manipulation; }
.ico-preflight-btn:hover { color:var(--text); background:var(--bg-hover); }
.ico-preflight-btn:focus-visible { outline:2px solid var(--accent-hover); outline-offset:1px; }
.ico-preflight-btn[hidden] { display:none; }


/* =========================================
   SVG Preview modal (js/export-preview.js)
   ========================================= */
/* Same dialog chrome as the Settings window over three read-only views of the exact Phase 8
   candidate. Every appearance control here is Preview-only test state. */
.expv-overlay { position:fixed; inset:0; z-index:10060; display:flex; align-items:center; justify-content:center; padding:16px; box-sizing:border-box; background:rgba(10,10,14,0.5); backdrop-filter:blur(7px) saturate(1.12); -webkit-backdrop-filter:blur(7px) saturate(1.12); }
.expv-overlay[hidden] { display:none; }
.expv-dialog { width:min(960px, calc(100vw - 32px)); height:min(660px, calc(100dvh - 32px)); display:flex; flex-direction:column; overflow:hidden; color:var(--text); background:var(--surface); border:1px solid var(--border-strong); border-radius:14px; box-shadow:0 24px 60px rgba(0,0,0,0.55), 0 0 0 1px rgba(0,0,0,0.3); animation:about-dialog-in 0.2s ease-out; }
.expv-head { display:flex; align-items:center; gap:12px; padding:8px 12px 8px 14px; flex-shrink:0; background:var(--bg-secondary); border-bottom:1px solid var(--border); }
.expv-title { margin:0; flex:0 0 auto; color:var(--text); font-size:14px; font-weight:600; }
.expv-tabs { display:flex; gap:2px; margin-left:auto; padding:2px; background:var(--bg); border:1px solid var(--border); border-radius:7px; }
.expv-tab { padding:4px 12px; color:var(--text-secondary); background:transparent; border:none; border-radius:5px; font:600 11px var(--font); cursor:pointer; transition:background 0.15s, color 0.15s; touch-action:manipulation; }
.expv-tab:hover { color:var(--text); }
.expv-tab.is-active { color:var(--text); background:var(--surface-raised); box-shadow:inset 0 1px 0 rgba(255,255,255,0.05); }
.expv-tab:focus-visible { outline:2px solid var(--accent-hover); outline-offset:-1px; }
.expv-close { width:28px; height:28px; flex:0 0 auto; display:flex; align-items:center; justify-content:center; padding:0; color:var(--text-secondary); background:transparent; border:none; border-radius:4px; font-family:var(--font); font-size:18px; line-height:1; cursor:pointer; transition:0.15s; touch-action:manipulation; }
.expv-close:hover { color:var(--text); background:var(--bg-hover); }
.expv-close:focus-visible { color:var(--text); outline:2px solid var(--accent-hover); outline-offset:-2px; }

.expv-body { flex:1; min-height:0; display:flex; }
.expv-view { flex:1; min-width:0; min-height:0; display:flex; flex-direction:column; overflow:hidden; padding:14px 16px; box-sizing:border-box; }
.expv-view[hidden] { display:none; }
/* The Code and Report scrollers are the focusable elements in their views, so keyboard users can
   scroll long output. The Visual view's own controls carry its focus. */
.expv-code:focus-visible, .expv-report:focus-visible { outline:2px solid var(--accent-hover); outline-offset:-2px; }

.expv-visual { flex:1; min-height:0; display:grid; grid-template-columns:minmax(0,1fr) 260px; gap:16px; align-items:stretch; overflow:auto; }
.expv-stage-col { min-width:0; display:flex; flex-direction:column; gap:8px; }
.expv-modes { display:flex; flex-wrap:wrap; gap:4px; }
.expv-mode { padding:4px 10px; color:var(--text-secondary); background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:4px; font:600 10px var(--font); cursor:pointer; transition:0.15s; touch-action:manipulation; }
.expv-mode:hover { color:var(--text); background:var(--bg-hover); }
.expv-mode.is-active { color:var(--accent); background:var(--accent-dim); border-color:var(--accent); }
.expv-mode:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.expv-stage { position:relative; flex:1; min-height:200px; display:flex; align-items:center; justify-content:center; padding:16px; box-sizing:border-box; overflow:hidden; border:1px solid var(--border); border-radius:8px; }
.expv-stage[data-bg='checker'] { background:repeating-conic-gradient(#26262b 0% 25%, #1f1f24 0% 50%) 0 0/14px 14px; }
.expv-stage[data-bg='light'] { background:#ffffff; }
.expv-stage[data-bg='dark'] { background:#0d0d0f; }
.expv-stage[data-bg='current'] { background:var(--surface-raised); }
.expv-art { width:100%; height:100%; display:flex; align-items:center; justify-content:center; }
/* Each preview root is a shadow host, so its SVG is sized inline in js/export-preview.js. */
.expv-art-host { min-width:0; min-height:0; width:100%; height:100%; display:flex; align-items:center; justify-content:center; }
.expv-size-host { display:flex; align-items:center; justify-content:center; }
.expv-empty { position:absolute; margin:0; color:var(--text-tertiary); font-size:11px; }
.expv-empty[hidden] { display:none; }
.expv-stage-note { margin:0; min-height:14px; font-size:10px; line-height:1.4; color:var(--text-tertiary); }

.expv-side { min-width:0; display:flex; flex-direction:column; gap:14px; }
.expv-group { display:flex; flex-direction:column; gap:8px; }
.expv-group[hidden] { display:none; }
.expv-sizes { display:flex; flex-wrap:wrap; align-items:flex-end; gap:8px; }
.expv-size { display:flex; flex-direction:column; align-items:center; gap:4px; }
.expv-size-box { display:flex; align-items:center; justify-content:center; padding:3px; border:1px solid var(--border); border-radius:4px; }
.expv-sizes[data-bg='checker'] .expv-size-box { background:repeating-conic-gradient(#26262b 0% 25%, #1f1f24 0% 50%) 0 0/8px 8px; }
.expv-sizes[data-bg='light'] .expv-size-box { background:#ffffff; }
.expv-sizes[data-bg='dark'] .expv-size-box { background:#0d0d0f; }
.expv-sizes[data-bg='current'] .expv-size-box { background:var(--surface-raised); }
.expv-size-label { font:600 9px monospace; color:var(--text-tertiary); }
.expv-swatches { display:flex; gap:6px; }
.expv-swatch { width:26px; height:26px; padding:0; border:1px solid var(--border-strong); border-radius:5px; cursor:pointer; transition:0.15s; touch-action:manipulation; }
.expv-swatch.is-active { border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-dim); }
.expv-swatch:disabled { opacity:0.35; cursor:default; }
.expv-swatch:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.expv-side-note { margin:0; font-size:9.5px; line-height:1.45; color:var(--text-tertiary); }

.expv-code { flex:1; min-height:0; margin:0; padding:12px; box-sizing:border-box; overflow:auto; color:var(--text); background:var(--bg); border:1px solid var(--border); border-radius:8px; font:12px/1.5 monospace; white-space:pre; tab-size:2; user-select:text; -webkit-user-select:text; }
.expv-code[data-empty='true'] { color:var(--text-tertiary); white-space:pre-wrap; font-family:var(--font); font-size:11.5px; }

.expv-report { flex:1; min-height:0; display:flex; flex-direction:column; gap:14px; overflow:auto; }
.expv-report-section { display:flex; flex-direction:column; gap:6px; }
.expv-report-dl { margin:0; display:flex; flex-direction:column; overflow:hidden; border:1px solid var(--border); border-radius:6px; }
.expv-report-row { display:grid; grid-template-columns:minmax(0,190px) minmax(0,1fr); gap:12px; padding:6px 10px; background:var(--surface); }
.expv-report-row:nth-child(odd) { background:rgba(0,0,0,0.12); }
.expv-report-row dt { margin:0; font-size:10.5px; font-weight:700; color:var(--text-secondary); }
.expv-report-row dd { margin:0; min-width:0; font-size:10.5px; line-height:1.45; color:var(--text); overflow-wrap:anywhere; }
.expv-diag-list { margin:0; padding:0; list-style:none; display:flex; flex-direction:column; gap:4px; }
.expv-diag-list li { display:grid; grid-template-columns:auto minmax(0,1fr); gap:8px; padding:6px 9px; background:rgba(0,0,0,0.12); border-left:2px solid var(--border-strong); border-radius:0 4px 4px 0; }
.expv-diag-list.is-error li { border-left-color:#e25b56; }
.expv-diag-list.is-warning li { border-left-color:#d5a541; }
.expv-diag-list.is-information li { border-left-color:var(--accent); }
.expv-diag-code { padding-top:1px; font:700 9.5px monospace; color:var(--text-tertiary); }
.expv-diag-text { min-width:0; font-size:10.5px; line-height:1.45; color:var(--text); overflow-wrap:anywhere; }
.expv-report-empty { margin:0; font-size:10.5px; color:var(--text-tertiary); }

.expv-foot { display:flex; align-items:center; gap:8px; padding:10px 14px; flex-shrink:0; background:var(--bg-secondary); border-top:1px solid var(--border); }
.expv-foot-state { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:11px; font-weight:600; color:var(--text-secondary); }
.expv-foot-state[data-state='warning'] { color:#d9b15b; }
.expv-foot-state[data-state='blocked'] { color:#ef8a87; }
.expv-foot-message { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:10.5px; color:var(--text-secondary); }
.expv-foot-message[hidden] { display:none; }
.expv-foot-message[data-tone='error'] { color:#ef8a87; }
.expv-foot-message[data-tone='ok'] { color:var(--success); }
.expv-foot > .expv-btn:first-of-type { margin-left:auto; }
.expv-btn { min-width:96px; flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center; padding:8px 16px; box-sizing:border-box; font:500 12.5px var(--font); border:none; border-radius:9px; cursor:pointer; transition:background 0.15s, transform 0.15s, opacity 0.15s; touch-action:manipulation; }
.expv-btn:active:not(:disabled) { transform:scale(0.97); opacity:0.7; }
.expv-btn:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.expv-btn:disabled { opacity:0.4; cursor:default; }
.expv-btn-ghost { color:var(--text); background:rgba(255,255,255,0.08); }
.expv-btn-ghost:hover:not(:disabled) { background:rgba(255,255,255,0.12); }
.expv-btn-primary { color:#fff; background:var(--accent); }
.expv-btn-primary:hover:not(:disabled) { background:var(--accent-hover); }

@media (max-width:900px) {
  .expv-visual { grid-template-columns:minmax(0,1fr); }
  .expv-dialog { height:calc(100dvh - 32px); }
}

@media (max-height:640px) {
  .expv-dialog { height:calc(100dvh - 24px); }
  .expv-stage { min-height:130px; }
}

/* =========================================
   Workspace Resizer (top group <-> bottom group)
   ========================================= */
/* The 10px line between the SVG-Preview group and the Import/Export group is a
   draggable handle. The wrapper gap drops to 0 and this 10px resizer supplies the
   exact same spacing, so the visible gap never grows. A faint grip pill sits in it;
   an invisible ::before enlarges the grab zone a few px without affecting layout. */
.panel-resizer { display:none; }
.ws-grip { width:36px; height:3px; border-radius:99px; background:var(--border-strong); opacity:0.5; transition:opacity 0.15s ease, background-color 0.15s ease, width 0.2s cubic-bezier(0.2, 0, 0, 1); pointer-events:none; }
.panel-resizer:hover .ws-grip, .panel-resizer.is-active .ws-grip { opacity:1; background:var(--text-tertiary); width:52px; }
.panel-resizer::before { content:""; position:absolute; left:0; right:0; top:-5px; bottom:-5px; }

@media (min-width: 1025px) {
  .layout-wrapper { gap:0; }                 /* the 10px now comes from the resizer */
  /* Top group shrinks completely so only the separate app header remains. Bottom group
     shrinks only until the top of the Import/Export text fields would hide -- i.e. the
     header + controls strip stays;
     that floor is measured live in ui-common.js and written inline as the dock's min-height
     (the split likewise lands inline on each group's flex-grow; the --ws-top/--ws-bottom vars
     below only carry the before-paint restore from index.html).
     overflow:hidden lets the collapsing body clip cleanly instead of spilling past the divider. */
  .layout-wrapper > .panel {
    flex-grow:var(--ws-top, 1); flex-shrink:1; flex-basis:0;
    min-height:0; overflow:hidden; box-sizing:border-box;
    transition:flex-grow 0.3s cubic-bezier(0.2, 0, 0, 1);
  }
  html.ws-top-collapsed .layout-wrapper > .panel { display:none; }
  .io-grid {
    flex-grow:var(--ws-bottom, 0.85); flex-shrink:1; flex-basis:0;
    min-height:120px;
    transition:flex-grow 0.3s cubic-bezier(0.2, 0, 0, 1);
  }
  .io-grid > .panel { overflow:hidden; }
  .panel-resizer { display:flex; flex:0 0 10px; position:relative; align-items:center; justify-content:center; cursor:ns-resize; touch-action:none; }
  /* During an active drag (and fit probes / window re-pins), kill the flex-grow ease so panels track
     the pointer 1:1. Its own class name on purpose: toggling a shared one such as .is-resizing (also
     used by the Layers panel) re-matches every layer row and icon in the workspace (~10ms). */
  .layout-wrapper.ws-hold-ease > .panel, .layout-wrapper.ws-hold-ease > .io-grid { transition:none; }
  /* Double-click fit probes dock heights synchronously and restores everything before paint.
     Both groups become fixed flex-bases that ui-common.js sets per probe (the top holds its
     height, so only the dock re-lays out), and .io-measuring holds the condense choreography
     while a condensed dock is opened for measuring, so every read is settled geometry.
     !important beats the inline split/floor ui-common.js writes on the groups. */
  .layout-wrapper.is-measuring > .panel, .layout-wrapper.is-measuring > .io-grid { flex-grow:0 !important; flex-shrink:0; min-height:0 !important; }
  .io-grid.io-measuring * { transition:none !important; }

  /* Condensed I/O panels -- ui-common.js puts .io-condensed on .io-grid when the divider is
     dragged below the two-row floor: the controls strip rides up into the header row (the
     header nudges down so both center on one line) and each panel condenses to a single row.
     Offsets are measured from the live layout and supplied as --io-* vars on each panel.
     Choreography: condensing shifts sideways first, then up; expanding drops down first,
     then shifts back. The base rules below hold the expand-direction timings. */
  .io-grid > .panel > .panel-header, .io-grid > .panel > .panel-header-row {
    transition: transform 0.32s cubic-bezier(0.2, 0, 0, 1);
  }
  .io-grid > .panel > .controls {
    transition: transform 0.32s cubic-bezier(0.2, 0, 0, 1), padding 0.24s cubic-bezier(0.2, 0, 0, 1) 0.08s;
  }
  .io-grid .textarea-wrap { transition: opacity 0.2s ease 0.15s; }
  /* The settings gear collapses away in condensed mode. */
  .io-grid > .panel-svg > .controls > .cw-icon-btn { max-width: 140px; overflow: hidden; transition: max-width 0.24s cubic-bezier(0.2, 0, 0, 1), opacity 0.15s ease, margin-left 0.24s cubic-bezier(0.2, 0, 0, 1), padding 0.24s cubic-bezier(0.2, 0, 0, 1), border-width 0.24s cubic-bezier(0.2, 0, 0, 1); }

  .io-grid.io-condensed > .panel > .panel-header, .io-grid.io-condensed > .panel > .panel-header-row {
    transform: translateY(var(--io-row-dy, 0px));
    transition-delay: 0.08s;
  }
  .io-grid.io-condensed > .panel > .controls {
    transform: translateY(var(--io-ctl-dy, 0px));
    padding-left: var(--io-ctl-pl, 0px);
    transition: transform 0.32s cubic-bezier(0.2, 0, 0, 1) 0.08s, padding 0.24s cubic-bezier(0.2, 0, 0, 1);
    /* The strip rides over the header row; let its padded gutter pass clicks through to the label. */
    pointer-events: none;
  }
  .io-grid.io-condensed > .panel > .controls > * { pointer-events: auto; }
  .io-grid.io-condensed .panel-svg > .controls, .io-grid.io-condensed .panel-export > .controls { flex-wrap: nowrap; }
  .io-grid.io-condensed .exp-format-switch { display:none; }
  /* Buttons in a merged row keep their intrinsic size. A squashed one would wrap its label, grow
     the row, and move the floor the whole condense machinery is measured against -- so a row that
     runs out of width overflows into the panel's clip instead. (The mini import field is still
     free to shrink; it is what absorbs the slack.) */
  .io-grid.io-condensed > .panel > .controls > .opt-btn { flex-shrink: 0; white-space: nowrap; }
  /* One-row dock: all three columns keep their expanded widths, so nothing travels sideways and
     the merge reads as a single vertical motion. Code and Export merge their controls into their
     header rows (the generic machinery above); the left panel has no controls strip and no body,
     so only its label rides down on the shared --io-row-dy measured in ui-common.js. */
  .io-grid .wb-body-wrap { transition: opacity 0.2s ease 0.15s; }
  .io-grid.io-condensed .wb-body-wrap { opacity: 0; pointer-events: none; transition: opacity 0.12s ease; }

  /* Condensed Export panel (Phase 9): the merged row is exactly EXPORT | Export .svg | Copy SVG.
     No option checkbox, preflight, or Preview control is promoted into it -- the settings card
     fades out with the generic .wb-body-wrap rule above and Preview collapses like the Code gear,
     so export options keep exactly one home. */
  .io-grid > .panel-export > .controls > .exp-preview-btn { max-width: 160px; overflow: hidden; transition: max-width 0.24s cubic-bezier(0.2, 0, 0, 1), opacity 0.15s ease, margin-left 0.24s cubic-bezier(0.2, 0, 0, 1), padding 0.24s cubic-bezier(0.2, 0, 0, 1), border-width 0.24s cubic-bezier(0.2, 0, 0, 1); }
  .io-grid.io-condensed > .panel-export > .controls > .exp-preview-btn { max-width: 0; opacity: 0; padding: 0; margin-left: -8px; border-width: 0; }
  .io-grid .import-mini-input {
    transition: flex-grow 0.24s cubic-bezier(0.2, 0, 0, 1), margin-right 0.24s cubic-bezier(0.2, 0, 0, 1), padding 0.24s cubic-bezier(0.2, 0, 0, 1), opacity 0.12s ease, border-color 0.12s ease, visibility 0s linear 0.32s;
  }
  .io-grid.io-condensed .import-mini-input {
    flex-grow: 1; opacity: 1; visibility: visible; padding: 0 8px; margin-right: 0; border-color: var(--border);
    transition: flex-grow 0.24s cubic-bezier(0.2, 0, 0, 1), margin-right 0.24s cubic-bezier(0.2, 0, 0, 1), padding 0.24s cubic-bezier(0.2, 0, 0, 1), opacity 0.15s ease 0.1s, border-color 0.15s ease 0.1s, visibility 0s;
  }
  .io-grid.io-condensed .import-mini-input:focus { border-color: var(--border-strong); }
  .io-grid.io-condensed .import-clear-btn { margin-left: 0; }
  .io-grid.io-condensed > .panel-svg > .controls > .cw-icon-btn { max-width: 0; opacity: 0; padding: 0; margin-left: -8px; border-width: 0; }
  .io-grid.io-condensed .cw-status, .io-grid.io-condensed .cw-diagnostics { display:none; }
  .io-grid.io-condensed .textarea-wrap { opacity: 0; pointer-events: none; transition: opacity 0.12s ease; }
}

@media (prefers-reduced-motion: reduce) {
  .layout-wrapper > .panel, .io-grid,
  .io-grid > .panel > .panel-header, .io-grid > .panel > .panel-header-row,
  .io-grid > .panel > .controls, .io-grid .textarea-wrap,
  .io-grid > .panel-svg > .controls > .cw-icon-btn, .io-grid .wb-body-wrap, .io-grid .import-mini-input,
  .cw-status-dot, .cw-diagnostics-chevron, .cw-editor-wrap,
  .io-grid > .panel-export > .controls > .exp-preview-btn, .exp-png-view-canvas, .exp-png-layer-image,
  .ico-preview-canvas, .ico-progress-fill { transition:none; }
  .ico-size-row.is-new > .ico-row { animation:none; }
  .expv-dialog { animation:none; }
}

/* =========================================
   Responsive Layout Adjustments
   ========================================= */
@media (max-width: 1024px) {
  html, body {
    height: auto;
    overflow-y: auto;
    overscroll-behavior-y: auto;
    touch-action: auto;
  }
  .layout-wrapper, .io-grid, .panel {
    min-height: auto;
    flex: none;
  }
  /* Stacked: ignore the desktop split/floor ui-common.js keeps inline on the two groups. */
  .layout-wrapper > .panel, .layout-wrapper > .io-grid { flex-grow:0 !important; min-height:auto !important; }
  .io-grid {
    grid-template-columns: 1fr;
  }
  .preview-container {
    flex-direction: column;
  }
  /* The properties panel stacks full-width here, so the canvas no longer starts at 192px;
     let the tool bar flow inline within the header row instead. */
  .quick-svg-presets { position:static; transform:none; left:auto; right:auto; width:auto; flex:0 0 auto; }
  .canvas-toolbar { position:static; transform:none; left:auto; }
  /* Stacked layout: the name flows inline ahead of the tool bar instead of holding the
     properties column, which is now full width. */
  .project-name { position:static; transform:none; left:auto; width:auto; max-width:200px; margin-right:10px; flex:0 0 auto; }
  .history-bar { position:static; transform:none; right:auto; }
  .app-header { min-height:96px; }
  .app-header h2 { top:0; transform:translateX(-50%); }
  .app-header .new-artboard-actions { top:32px; }
  .header-left-controls { left:auto; right:0; top:32px; transform:translateY(-50%); }
  .header-right-cluster { display:contents; }
  .header-action-controls { position:absolute; right:0; top:0; transform:none; }
  .header-guide-controls { position:absolute; left:50%; top:80px; transform:translate(-50%, -50%); width:auto; justify-content:center; }
  .pen-mode-bar { position:absolute; left:0; top:80px; transform:translateY(-50%); flex:0 0 auto; justify-content:flex-start; }
  .panel-properties {
    width: 100%;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
  }
  .panel-properties .panel-title {
    width: 100%;
    border: none;
    padding-bottom: 0;
    margin-bottom: 0;
  }
  .panel-properties .props-wrap,
  .panel-properties .props-empty,
  .panel-properties .props-grid {
    width: 100%;
  }
  /* Stacked full-width panel grows with content; no inner scroll needed here. */
  .panel-properties .props-scroll { margin:0; padding:0; overflow:visible; }
  .preview-box {
    width: 100%;
    min-height: 350px;
  }
  .right-dock {
    width: 100%;
    max-width: 100%;
    flex: none;
  }
  .panel-layers {
    min-height: 300px;
    max-height: 500px;
  }
}

@media (max-width: 1120px) and (min-width: 1025px) {
  .app-header { min-height:96px; }
  .app-header h2 { top:0; transform:translateX(-50%); }
  .app-header .new-artboard-actions { top:32px; }
  .header-left-controls { left:auto; right:0; top:32px; transform:translateY(-50%); }
  .header-right-cluster { display:contents; }
  .header-action-controls { position:absolute; right:0; top:0; transform:none; }
  .header-guide-controls { position:absolute; left:50%; top:80px; transform:translate(-50%, -50%); width:auto; justify-content:center; }
  .pen-mode-bar { position:absolute; left:0; top:80px; transform:translateY(-50%); flex:0 0 auto; justify-content:flex-start; }
}

/* ---- New Artboard button + dialog ---------------------------------------- */
/* Standout accent-gradient app-header button, plus a create-artboard dialog
   whose header/footer mirror the color-picker
   modal (var(--bg-secondary) bars + bordered edges). The signature element is the
   live proportional preview rect (.na-preview). */

.new-artboard-actions { display:flex; align-items:center; gap:6px; flex-shrink:0; }
.new-artboard-btn { display:inline-flex; align-items:center; gap:6px; height:28px; padding:0 12px 0 9px; box-sizing:border-box; flex-shrink:0; font-family:var(--font); font-size:12px; font-weight:600; letter-spacing:0.2px; color:#fff; background:linear-gradient(180deg, var(--accent-hover), var(--accent)); border:1px solid rgba(0,0,0,0.25); border-radius:6px; cursor:pointer; transition:filter 0.15s, box-shadow 0.15s; box-shadow:0 1px 3px rgba(0,0,0,0.35), 0 0 0 1px rgba(0,122,255,0.25), inset 0 1px 0 rgba(255,255,255,0.18); touch-action:manipulation; }
.new-artboard-btn:hover { filter:brightness(1.08); box-shadow:0 2px 9px rgba(0,122,255,0.4), 0 0 0 1px rgba(0,122,255,0.45), inset 0 1px 0 rgba(255,255,255,0.22); }
.new-artboard-btn:active { filter:brightness(0.95); }
.new-artboard-btn:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.new-artboard-btn .icon-svg { width:14px; height:14px; }
.header-plain-btn { display:inline-flex; align-items:center; gap:6px; height:28px; padding:0 12px 0 9px; box-sizing:border-box; flex-shrink:0; font-family:var(--font); font-size:12px; font-weight:600; letter-spacing:0.2px; color:var(--text); background:var(--surface); border:1px solid var(--border-strong); border-radius:6px; cursor:pointer; transition:background 0.15s, border-color 0.15s, color 0.15s; box-shadow:inset 0 1px 0 rgba(255,255,255,0.05); touch-action:manipulation; }
.header-plain-btn:hover { color:var(--text); background:var(--bg-hover); }
.header-plain-btn:active { background:var(--bg-hover); }
.header-plain-btn:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.header-plain-btn .icon-svg { width:14px; height:14px; }
.header-plain-btn.is-hover-suppressed:hover { color:var(--text); background:var(--surface); }
.header-plain-btn:disabled { color:var(--text-secondary); background:var(--surface); border-color:var(--border); cursor:default; opacity:0.45; }
.header-plain-btn:disabled:hover { color:var(--text-secondary); background:var(--surface); }
.header-plain-btn[hidden] { display:none; }
/* Save feedback. The spinner occupies the same 14px box as the icon it replaces, so a save in
   flight never reflows the button. The success flash outranks the post-save disabled dimming. */
.header-plain-btn .hp-spinner { display:none; width:14px; height:14px; flex-shrink:0; box-sizing:border-box; border:2px solid rgba(242,242,247,0.22); border-top-color:var(--accent); border-radius:50%; animation:hp-spin 0.62s linear infinite; }
.header-plain-btn.is-busy { pointer-events:none; cursor:default; }
.header-plain-btn.is-busy .icon-svg { display:none; }
.header-plain-btn.is-busy .hp-spinner { display:block; }
.header-plain-btn.btn-success:disabled { opacity:1; }
.header-plain-btn.btn-success .hp-spinner { border-color:rgba(255,255,255,0.32); border-top-color:#fff; }
@keyframes hp-spin { to { transform:rotate(360deg); } }
.quick-artboard-btn { margin-right:18px; display:inline-flex; align-items:center; justify-content:center; height:28px; padding:0 11px; box-sizing:border-box; flex-shrink:0; font-family:var(--font); font-size:12px; font-weight:600; letter-spacing:0.2px; color:var(--text); background:var(--surface); border:1px solid var(--border-strong); border-radius:6px; cursor:pointer; transition:background 0.15s, border-color 0.15s, color 0.15s; box-shadow:inset 0 1px 0 rgba(255,255,255,0.05); touch-action:manipulation; }
.quick-artboard-btn:hover { color:var(--text); background:var(--bg-hover); }
.quick-artboard-btn:active { background:var(--bg-hover); }
.quick-artboard-btn:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }

.na-overlay { position:fixed; inset:0; z-index:10030; display:flex; align-items:center; justify-content:center; padding:24px; box-sizing:border-box; background:rgba(10,10,14,0.5); backdrop-filter:blur(8px) saturate(1.2); -webkit-backdrop-filter:blur(8px) saturate(1.2); }
.na-overlay[hidden] { display:none; }
.na-dialog { position:relative; width:min(440px, calc(100vw - 32px)); overflow:hidden; color:var(--text); background:var(--surface); border:1px solid var(--border-strong); border-radius:12px; box-shadow:0 24px 60px rgba(0,0,0,0.55), 0 0 0 1px rgba(0,0,0,0.3); }

.na-head { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:12px 16px; border-bottom:1px solid var(--border); background:var(--bg-secondary); }
.na-title { margin:0; font-size:14px; font-weight:600; color:var(--text); }
.na-close-btn { display:flex; align-items:center; justify-content:center; padding:0 4px; color:var(--text-secondary); background:transparent; border:none; font-size:20px; line-height:1; cursor:pointer; transition:color 0.15s; flex-shrink:0; }
.na-close-btn:hover, .na-close-btn:focus-visible { color:var(--text); outline:none; }

.na-body { padding:16px; }
.na-main { display:flex; gap:16px; align-items:stretch; }
.na-preview-wrap { width:158px; flex-shrink:0; display:flex; flex-direction:column; align-items:center; gap:10px; }
.na-stage { width:100%; height:148px; display:flex; align-items:center; justify-content:center; background:repeating-conic-gradient(#26262b 0% 25%, #1f1f24 0% 50%) 0 0/14px 14px; border:1px solid var(--border); border-radius:8px; }
.na-preview { background:rgba(0,122,255,0.10); border:1.5px solid var(--accent); box-shadow:0 0 0 1px rgba(0,0,0,0.4), 0 6px 18px rgba(0,0,0,0.4); transition:width 0.12s ease, height 0.12s ease; }
.na-preview-dims { font-family:monospace; font-size:12px; font-weight:700; color:var(--text); letter-spacing:0.3px; }

.na-fields { flex:1; min-width:0; display:flex; align-items:center; }
.na-field-rows { position:relative; flex:1; min-width:0; padding-right:46px; display:flex; flex-direction:column; gap:16px; }
.na-field { display:flex; align-items:center; gap:10px; }
.na-field-label { width:50px; flex-shrink:0; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:var(--text-secondary); }
.na-input-wrap { flex:1; min-width:0; height:38px; display:flex; align-items:center; background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:8px; padding:0 12px; transition:border-color 0.15s, box-shadow 0.15s; }
.na-input-wrap:focus-within { border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-dim); }
.na-input { flex:1; min-width:0; width:100%; background:transparent; border:none; outline:none; color:var(--text); font-family:monospace; font-size:16px; font-weight:700; padding:0; -moz-appearance:textfield; appearance:textfield; }
.na-input::-webkit-outer-spin-button, .na-input::-webkit-inner-spin-button { -webkit-appearance:none; margin:0; }
.na-unit { font-size:12px; font-weight:600; color:var(--text-tertiary); padding-left:8px; flex-shrink:0; }

/* Constrain-proportions link: a rounded ] bracket joining both field rows to the
   chain button, whose surface-coloured fill masks the bracket's centre line. */
.na-bracket { position:absolute; right:22px; width:24px; top:19px; bottom:19px; border:1.5px solid var(--border-strong); border-left:none; border-radius:0 7px 7px 0; pointer-events:none; }
.na-constrain { position:absolute; right:6px; top:50%; transform:translateY(-50%); width:32px; height:32px; display:flex; align-items:center; justify-content:center; padding:0; background:var(--surface); border:none; border-radius:8px; color:var(--text-secondary); cursor:pointer; transition:color 0.15s; }
.na-constrain:hover { color:var(--text); }
.na-constrain:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.na-constrain[aria-pressed="true"] { color:var(--accent); }
.na-constrain .icon-svg { width:22px; height:22px; }

.na-presets { display:grid; grid-template-columns:repeat(5, 1fr); gap:5px; margin-top:14px; }
.na-preset { display:flex; align-items:center; justify-content:center; height:30px; padding:0 4px; font-family:var(--font); font-size:11px; font-weight:700; color:var(--text-secondary); background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:7px; cursor:pointer; white-space:nowrap; transition:0.15s; touch-action:manipulation; }
.na-preset:hover { background:var(--bg-hover); color:var(--text); }
.na-preset.active { background:var(--accent-dim); border-color:var(--accent); color:var(--accent); }

.na-footer { display:flex; justify-content:flex-end; align-items:center; gap:8px; padding:12px 16px; border-top:1px solid var(--border); background:var(--bg-secondary); }
.na-footer[hidden] { display:none; }
.na-btn { display:inline-flex; align-items:center; justify-content:center; padding:10px 18px; font-family:var(--font); font-size:13px; font-weight:500; border-radius:10px; cursor:pointer; transition:filter 0.15s, background 0.15s, color 0.15s, transform 0.15s; touch-action:manipulation; box-sizing:border-box; }
.na-btn:active { transform:scale(0.97); }
.na-btn:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.na-btn-ghost { color:var(--text); background:rgba(255,255,255,0.08); border:none; }
.na-btn-ghost:hover { background:rgba(255,255,255,0.12); }
.na-btn-primary { color:#fff; background:linear-gradient(180deg, var(--accent-hover), var(--accent)); border:1px solid rgba(0,0,0,0.25); box-shadow:0 2px 8px rgba(0,122,255,0.3), inset 0 1px 0 rgba(255,255,255,0.18); }
.na-btn-primary:hover { filter:brightness(1.08); }
.na-btn-primary:disabled { opacity:0.4; cursor:default; filter:none; box-shadow:inset 0 1px 0 rgba(255,255,255,0.18); }
.na-btn-danger { color:#fff; background:#ff453a; border:1px solid rgba(0,0,0,0.25); box-shadow:inset 0 1px 0 rgba(255,255,255,0.18); }
.na-btn-danger:hover { filter:brightness(1.08); }

.na-confirm { display:flex; flex-direction:column; gap:10px; padding:12px 16px; border-top:1px solid var(--border); background:var(--bg-secondary); }
.na-confirm[hidden] { display:none; }
.na-confirm-msg { margin:0; font-size:12px; line-height:1.4; color:var(--text-secondary); }
.na-confirm-actions { display:flex; justify-content:flex-end; gap:8px; }

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

/* --- Floating History panel (js/history-panel.js) --------------------------------------------- */
.history-panel { position:fixed; z-index:900; left:0; top:64px; width:var(--properties-panel-w); display:flex; flex-direction:column; background:var(--surface); color:var(--text); border:1px solid var(--border-strong); border-radius:var(--radius); box-shadow:0 12px 34px rgba(0,0,0,0.5), 0 2px 8px rgba(0,0,0,0.35); overflow:hidden; font-family:var(--font); }
.history-panel[hidden] { display:none; }

.history-panel__bar { flex:0 0 auto; display:flex; align-items:center; justify-content:space-between; height:32px; padding:0 6px 0 12px; background:var(--bg-secondary); border-bottom:1px solid var(--border); cursor:grab; touch-action:none; user-select:none; }
.history-panel__title { font-size:10.5px; font-weight:700; letter-spacing:0.8px; text-transform:uppercase; color:var(--text-secondary); }
.history-panel__nav { display:flex; align-items:center; gap:2px; }
.history-panel__nav-btn { display:inline-flex; align-items:center; justify-content:center; width:24px; height:24px; padding:0; border:none; border-radius:5px; background:transparent; color:var(--text-secondary); cursor:pointer; transition:0.12s; }
.history-panel__nav-btn:hover:not(:disabled) { background:var(--bg-hover); color:var(--text); }
.history-panel__nav-btn:disabled { opacity:0.32; cursor:default; }
.history-panel__nav-btn .icon-svg { width:15px; height:15px; }
.history-panel__close { margin-left:6px; font-size:16px; line-height:1; }

.history-panel__list { flex:1 1 auto; min-height:0; overflow-y:auto; overflow-x:hidden; padding:4px 0; scrollbar-width:thin; scrollbar-color:rgba(255,255,255,0.18) transparent; }
.history-panel__list::-webkit-scrollbar { width:9px; }
.history-panel__list::-webkit-scrollbar-thumb { background:rgba(255,255,255,0.16); border-radius:5px; border:2px solid transparent; background-clip:padding-box; }
.history-panel__list::-webkit-scrollbar-thumb:hover { background:rgba(255,255,255,0.28); background-clip:padding-box; }

.history-entry { display:flex; align-items:center; gap:9px; padding:5px 12px 5px 10px; border-left:2px solid transparent; font-size:11.5px; line-height:1.2; color:var(--text-secondary); cursor:pointer; transition:background 0.1s ease, color 0.1s ease; }
.history-entry:hover { background:var(--bg-hover); color:var(--text); }
.history-entry__icon { width:15px; height:15px; flex:0 0 15px; color:inherit; }
.history-entry__label { overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
.history-entry.is-current { color:var(--text); background:var(--accent-dim); border-left-color:var(--accent); }
.history-entry.is-current .history-entry__icon { color:var(--accent); }
.history-entry.is-future { opacity:0.4; }
.history-entry.is-future:hover { opacity:0.7; }

.history-panel__resize { flex:0 0 auto; height:9px; cursor:ns-resize; touch-action:none; background:var(--bg-secondary); border-top:1px solid var(--border); position:relative; }
.history-panel__resize::after { content:''; position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); width:26px; height:2px; border-radius:2px; background:rgba(255,255,255,0.18); }
.history-panel__resize:hover::after { background:rgba(255,255,255,0.3); }

/* ---- Canvas context menu (js/context-menu.js) ---------------------------------------------- */
.ctx-menu { position:fixed; z-index:9990; min-width:186px; padding:4px 0; box-sizing:border-box; background:var(--surface-raised); border:1px solid var(--border-strong); border-radius:7px; box-shadow:0 12px 32px rgba(0,0,0,0.45), 0 0 0 1px rgba(0,0,0,0.25); font-family:var(--font); -webkit-user-select:none; user-select:none; }
.ctx-menu[hidden] { display:none; }
.ctx-menu__item { display:flex; align-items:center; gap:9px; width:100%; padding:6px 14px 6px 10px; box-sizing:border-box; background:transparent; border:none; text-align:left; font-family:inherit; font-size:11.5px; line-height:1.2; color:var(--text-secondary); cursor:pointer; transition:background 0.1s ease, color 0.1s ease; }
.ctx-menu__item:hover:not(:disabled), .ctx-menu__item:focus-visible { background:var(--bg-hover); color:var(--text); outline:none; }
.ctx-menu__item:disabled { opacity:0.36; cursor:default; }
.ctx-menu__icon { width:15px; height:15px; flex:0 0 15px; color:inherit; }
.ctx-menu__sep { height:1px; margin:4px 0; background:var(--border); }

/* ---- Drop Shadow popup (js/drop-shadow.js) ------------------------------------------------- */
.ds-pop { position:fixed; z-index:910; width:220px; display:flex; flex-direction:column; box-sizing:border-box; background:var(--surface); color:var(--text); border:1px solid var(--border-strong); border-radius:var(--radius); box-shadow:0 12px 34px rgba(0,0,0,0.5), 0 2px 8px rgba(0,0,0,0.35); overflow:hidden; font-family:var(--font); }
.ds-pop[hidden] { display:none; }
.ds-pop__bar { flex:0 0 auto; display:flex; align-items:center; justify-content:space-between; height:30px; padding:0 4px 0 12px; background:var(--bg-secondary); border-bottom:1px solid var(--border); cursor:grab; touch-action:none; -webkit-user-select:none; user-select:none; }
.ds-pop__bar.is-dragging { cursor:grabbing; }
.ds-pop__title { font-size:10.5px; font-weight:700; letter-spacing:0.8px; text-transform:uppercase; color:var(--text-secondary); }
.ds-pop__close { display:inline-flex; align-items:center; justify-content:center; width:22px; height:22px; padding:0; border:none; border-radius:5px; background:transparent; color:var(--text-secondary); font-size:16px; line-height:1; cursor:pointer; transition:0.12s; }
.ds-pop__close:hover { background:var(--bg-hover); color:var(--text); }
.ds-pop__body { display:flex; flex-direction:column; gap:9px; padding:10px 12px 11px; }
.ds-pop__ctrl { display:flex; flex-direction:column; gap:4px; min-width:0; }
.ds-pop__row { display:flex; align-items:center; gap:6px; min-width:0; }
.ds-pop__label { flex:1 1 auto; font-size:10px; line-height:1; font-weight:700; color:var(--text-secondary); cursor:ew-resize; touch-action:none; -webkit-user-select:none; user-select:none; transition:color 0.12s; }
.ds-pop__label:hover { color:var(--text); }
.ds-pop__field { flex:0 0 80px; }

/* Sliders. --ds-a / --ds-b are the accent fill's start/end percentages, written by js/drop-shadow.js.
   The offset tracks are bipolar: a hairline detent marks zero at centre and the fill runs out from it.
   The opacity track is painted as the shadow it edits -- black fading to nothing -- and carries no
   accent fill, the same alpha idiom the color picker uses. */
.ds-pop__slider { -webkit-appearance:none; appearance:none; width:100%; height:11px; margin:0; padding:0; background:transparent; outline:none; cursor:pointer; touch-action:none; }
.ds-pop__slider::-webkit-slider-runnable-track { height:3px; border-radius:2px; background:linear-gradient(to right, transparent var(--ds-a,0%), var(--accent) var(--ds-a,0%), var(--accent) var(--ds-b,0%), transparent var(--ds-b,0%)), rgba(255,255,255,0.14); }
.ds-pop__slider--bipolar::-webkit-slider-runnable-track { background:linear-gradient(to right, transparent var(--ds-a,50%), var(--accent) var(--ds-a,50%), var(--accent) var(--ds-b,50%), transparent var(--ds-b,50%)), linear-gradient(to right, transparent calc(50% - 0.5px), rgba(255,255,255,0.5) calc(50% - 0.5px), rgba(255,255,255,0.5) calc(50% + 0.5px), transparent calc(50% + 0.5px)), rgba(255,255,255,0.14); }
.ds-pop__slider--alpha::-webkit-slider-runnable-track { background:linear-gradient(to right, #08080a, rgba(255,255,255,0.16)); }
.ds-pop__slider::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:11px; height:11px; margin-top:-4px; border-radius:50%; background:#fff; border:1.5px solid var(--accent); box-sizing:border-box; box-shadow:0 1px 3px rgba(0,0,0,0.5); transition:box-shadow 0.12s; }
.ds-pop__slider:focus-visible::-webkit-slider-thumb { box-shadow:0 0 0 3px var(--accent-dim), 0 1px 3px rgba(0,0,0,0.5); }
.ds-pop__slider.is-mixed { opacity:0.45; }
.ds-pop__slider.is-mixed::-webkit-slider-thumb { background:var(--text-secondary); border-color:var(--text-tertiary); }

.ds-pop__foot { display:flex; align-items:center; gap:6px; padding:9px 12px 10px; border-top:1px solid var(--border); background:rgba(0,0,0,0.14); }
.ds-pop__eye { margin-right:auto; display:inline-flex; align-items:center; justify-content:center; width:32px; height:26px; padding:0; border:none; border-radius:6px; background:rgba(255,255,255,0.08); color:var(--text-secondary); cursor:pointer; transition:0.12s; }
.ds-pop__eye:hover { background:rgba(255,255,255,0.12); color:var(--text); }
.ds-pop__eye:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.ds-pop__eye.is-off { color:var(--accent); background:var(--accent-dim); }
.ds-pop__eye .icon-svg { width:16px; height:16px; display:block; }
.ds-pop__btn { display:inline-flex; align-items:center; justify-content:center; min-width:58px; height:26px; padding:0 12px; box-sizing:border-box; border-radius:6px; font-family:var(--font); font-size:11.5px; line-height:1; font-weight:600; letter-spacing:0.2px; cursor:pointer; transition:filter 0.15s, background 0.15s, transform 0.12s; touch-action:manipulation; }
.ds-pop__btn:active { transform:scale(0.97); }
.ds-pop__btn:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.ds-pop__btn--ghost { color:var(--text); background:rgba(255,255,255,0.08); border:none; }
.ds-pop__btn--ghost:hover { background:rgba(255,255,255,0.12); }
.ds-pop__btn--primary { color:#fff; background:linear-gradient(180deg, var(--accent-hover), var(--accent)); border:1px solid rgba(0,0,0,0.25); box-shadow:0 2px 8px rgba(0,122,255,0.3), inset 0 1px 0 rgba(255,255,255,0.18); }
.ds-pop__btn--primary:hover { filter:brightness(1.08); }

/* Utility row above the commit bar: the defaults pair and the effect clipboard. Reuses .ds-pop__btn
   at a smaller, quieter size -- these are conveniences, not the dialog's decision -- so it is
   declared after the button variants it overrides. is-confirmed is the momentary accent pulse on
   Make Default / Copy, the two actions that change nothing on the canvas. */
.ds-pop__tools { display:flex; align-items:center; gap:5px; padding:0 12px 11px; }
.ds-pop__btn--sm { min-width:0; height:22px; padding:0 7px; font-size:11px; font-weight:500; letter-spacing:0; white-space:nowrap; color:var(--text-secondary); }
.ds-pop__btn--sm:hover { color:var(--text); }
.ds-pop__icon-btn { flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center; width:24px; height:22px; padding:0; border:none; border-radius:5px; background:rgba(255,255,255,0.08); color:var(--text-secondary); cursor:pointer; transition:0.12s; }
.ds-pop__icon-btn:hover:not(:disabled) { background:rgba(255,255,255,0.12); color:var(--text); }
.ds-pop__icon-btn:focus-visible { outline:2px solid var(--accent-hover); outline-offset:2px; }
.ds-pop__icon-btn:disabled { opacity:0.34; cursor:default; }
.ds-pop__icon-btn .icon-svg { width:13px; height:13px; display:block; }
.ds-pop__btn--sm + .ds-pop__icon-btn { margin-left:auto; }
.ds-pop__btn.is-confirmed, .ds-pop__icon-btn.is-confirmed { background:var(--accent-dim); color:var(--accent); }

/* Blocked input while the popup owns the document: the outline flickers white and the popup's own
   drop shadow blinks off with it. steps(1) keeps it a hard flicker rather than a pulse. */
@keyframes ds-pop-flash {
  0%, 33.3%, 66.6% { border-color:#ffffff; box-shadow:none; }
  16.6%, 49.9%, 83.3%, 100% { border-color:var(--border-strong); box-shadow:0 12px 34px rgba(0,0,0,0.5), 0 2px 8px rgba(0,0,0,0.35); }
}
@keyframes ds-pop-flash-soft { 0%, 100% { border-color:var(--border-strong); } 50% { border-color:#ffffff; } }
.ds-pop.is-flashing { animation:ds-pop-flash 0.42s steps(1, end) 1; }
@media (prefers-reduced-motion: reduce) { .ds-pop.is-flashing { animation:ds-pop-flash-soft 0.2s ease 1; } }

/* Popup open: tool chrome is hidden for the whole session (selection box, handles, anchors, Live
   Corners widgets, snap feedback) so the shadow can be judged clean. Rulers, guides and the artboard
   outline stay. visibility, not display, so overlay painters can still measure while hidden. */
/* Shared canvas edit-chrome mute. Each owner toggles its own class so two features can never
   fight over one flag; the definition of "chrome" lives here only. See docs/effects.md and
   docs/paint-panel.md. */
body.ds-ui-hidden #previewArea .canvas-overlay,
body.ap-weight-ui-hidden #previewArea .canvas-overlay { visibility:hidden; }
