* {
  box-sizing: border-box;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  margin: 0;
  padding: 0;
}
input, textarea, .field--text { -webkit-user-select: text; }

:root {
  --bg-page: #F0F1FA;
  --glass-fill: rgba(255,255,255,0.58);
  --glass-fill-strong: rgba(255,255,255,0.86);
  --glass-border: rgba(24,26,40,0.08);
  --text-primary: #1B1B23;
  --text-secondary: #47474F;
  --accent: #3E63DD;
  --accent-ink: #FFFFFF;
  --accent-container: #DEE3FF;
  --on-accent-container: #0C1F63;
  --outline: #C7C7D1;
  --outline-variant: #DDDCE4;
  --surface-container: rgba(20,30,90,0.05);
  --surface-container-high: rgba(20,30,90,0.09);
  --success: #1FA971;
  --warning: #E0932B;
  --danger: #E2483D;
  --page-paper: #FFFFFF;
  --page-ink: #2A2C33;
  --radius-lg: 24px;
  --radius-md: 16px;
  --shadow-glass: 0 1px 2px rgba(20,21,32,0.08), 0 6px 20px rgba(20,21,32,0.10);
  --glow-strength: 0;
  --wave-opacity: 0;
  --strobe-opacity: 0;
  --text-scale-heading: 1;
  --text-scale-subheading: 1;
  --text-scale-body: 1;
  --font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
  --font-kerning: 0px;
  --font-weight: 600;
  --font-style: normal;
}
[data-theme="dark"] {
  --bg-page: #10111A;
  --glass-fill: rgba(30,32,42,0.58);
  --glass-fill-strong: rgba(30,32,42,0.88);
  --glass-border: rgba(255,255,255,0.08);
  --text-primary: #E4E2E9;
  --text-secondary: #A6A5B1;
  --accent: #B4C1FF;
  --accent-ink: #10245F;
  --accent-container: #29407A;
  --on-accent-container: #DDE3FF;
  --outline: #46464F;
  --outline-variant: #333440;
  --surface-container: rgba(255,255,255,0.05);
  --surface-container-high: rgba(255,255,255,0.09);
  --page-paper: #F5F5F2;
  --shadow-glass: 0 1px 2px rgba(0,0,0,0.4), 0 6px 22px rgba(0,0,0,0.35);
}

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

.hidden { display: none !important; }

html, body {
  height: 100dvh;
  overflow: hidden;
  position: fixed;
  width: 100%;
  overscroll-behavior: none;
  background: var(--bg-page);
  font-family: var(--font-family);
  letter-spacing: var(--font-kerning);
  font-weight: var(--font-weight);
  font-style: var(--font-style);
  font-size: calc(14px * var(--text-scale-body));
  color: var(--text-primary);
}

.shell { position: relative; height: 100dvh; display: flex; }

.bg-photo { position: absolute; inset: 0; background-size: cover; background-position: center; z-index: 0; }
.glow-ring { position: absolute; inset: 0; pointer-events: none; z-index: 5;
  box-shadow: inset 0 0 0 0 var(--glow-color, var(--accent)); animation: glow-pulse 2.6s ease-in-out infinite; opacity: var(--glow-strength); }
@keyframes glow-pulse { 0%,100% { box-shadow: inset 0 0 24px -4px var(--glow-color, var(--accent)); } 50% { box-shadow: inset 0 0 54px 4px var(--glow-color, var(--accent)); } }
/* "Border waves" was a hard-edged pattern scrolling continuously at speed — exactly
   the kind of repeating high-contrast motion WCAG 2.3.1 flags as a photosensitive
   seizure risk, independent of the strobe effect's own brightness cap below (that cap
   only limits flashing, not a moving pattern). Replaced with a slow, soft color drift:
   no hard edges, no repetition, opacity capped low in app.js's wireEffect() call. */
.wave-bar { position: absolute; left: 0; right: 0; height: 6px; z-index: 5; pointer-events: none;
  background: linear-gradient(90deg, var(--wave-color, var(--accent)), color-mix(in srgb, var(--wave-color, var(--accent)) 25%, transparent), var(--wave-color, var(--accent)));
  background-size: 220% 100%; opacity: var(--wave-opacity); animation: wave-drift 9s ease-in-out infinite; filter: blur(1px); }
.wave-bar.top { top: 0; } .wave-bar.bottom { bottom: 0; }
@keyframes wave-drift { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }
.strobe-overlay { position: absolute; inset: 0; background: var(--strobe-color, var(--accent)); pointer-events: none; z-index: 6;
  opacity: 0; animation: strobe-breathe 4s ease-in-out infinite; }
@keyframes strobe-breathe { 0%,100% { opacity: 0; } 50% { opacity: var(--strobe-opacity); } }

.glass {
  background: var(--glass-fill);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid var(--glass-border);
}

/* ---- Icon rail ---- */
.rail {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 76px;
  padding: max(20px, env(safe-area-inset-top)) 0 20px;
  background: var(--glass-fill);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  border-right: 1px solid var(--glass-border);
  z-index: 30;
}
.rail-item {
  width: 52px; height: 52px; border-radius: 16px; border: none; background: transparent;
  color: var(--text-secondary); display: flex; align-items: center; justify-content: center; cursor: pointer;
  position: relative; overflow: hidden; transition: background 0.15s ease, color 0.15s ease, transform 0.1s ease;
}
.rail-item svg { width: 22px; height: 22px; }
.rail-item.active { background: var(--accent-container); color: var(--on-accent-container); }
.rail-item:not(.active):hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.rail-item:active { transform: scale(0.92); }

/* Portrait: rail collapses to a bottom strip so the document keeps the width */
@media (orientation: portrait) {
  .shell { flex-direction: column; }
  .rail {
    flex-direction: row; width: 100%; height: 64px;
    border-right: none; border-top: 1px solid var(--glass-border);
    order: 2; justify-content: space-evenly;
    padding: 8px max(8px, env(safe-area-inset-bottom));
  }
  .stage { order: 1; padding: 14px 10px 84px !important; }
}

/* ---- Stage / A4 viewport ---- */
.stage {
  flex: 1; position: relative; z-index: 10;
  display: flex; align-items: center; justify-content: center;
  padding: 24px 24px 110px;
  overflow: hidden;
}
/* .stage centers its children instead of stretching them (align-items/justify-content:
   center), so every .screen needs its own explicit size or it shrinks to its content's
   intrinsic size instead of filling the stage — this is what made the Editor's PDF page
   collapse to 0 height (the page-nav pill was the only thing with real content, so the
   whole screen shrank around it and appeared to float in empty space). */
.screen { width: 100%; height: 100%; }
.stub { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; height: 100%; text-align: center; }
.stub-title { font-size: calc(17px * var(--text-scale-heading)); font-weight: 700; }
.stub-sub { font-size: calc(13px * var(--text-scale-subheading)); color: var(--text-secondary); max-width: 320px; }

/* ---- My Files tab ---- */
#screen-files { display: flex; flex-direction: column; gap: 14px; padding-bottom: 20px; }
.files-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-top: 30px; }
.folder-chips { display: flex; gap: 8px; flex-wrap: wrap; }
.folder-chip {
  display: flex; align-items: center; gap: 6px; padding: 7px 14px; border-radius: 999px; border: none;
  background: var(--glass-fill); backdrop-filter: blur(14px); font-size: 12px; font-weight: 600;
  color: var(--text-secondary); cursor: pointer; border: 1px solid var(--glass-border);
}
.folder-chip.active { background: var(--chip-color, var(--accent)); color: var(--accent-ink); border-color: transparent; }
.folder-chip-x { font-size: 14px; line-height: 1; opacity: 0.7; }
.folder-chip-x:hover { opacity: 1; }
.files-toolbar-actions { display: flex; gap: 8px; }
.upload-btn-inline { display: inline-flex; align-items: center; }

.files-list { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; padding-right: 4px; }
.files-empty { text-align: center; color: var(--text-secondary); font-size: 13px; padding: 40px 0; }
.file-row {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: var(--radius-md);
}
.file-color { width: 14px; height: 14px; border-radius: 50%; border: none; cursor: pointer; flex-shrink: 0; }
.file-name {
  flex: 1; min-width: 0; font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; outline: none; padding: 4px 6px; border-radius: 6px;
}
.file-name:focus { background: rgba(128,128,128,0.12); white-space: normal; text-overflow: initial; }
.file-folder-select {
  font-size: 11px; border: none; background: rgba(128,128,128,0.1); border-radius: 8px; padding: 5px 8px;
  color: var(--text-secondary); max-width: 110px;
}
.file-sync { width: 8px; height: 8px; border-radius: 50%; background: var(--success); flex-shrink: 0; }
.file-sync[data-state="queued"], .file-sync[data-state="syncing"] { background: var(--warning); }
.file-sync[data-state="failed"] { background: var(--danger); }
.file-sync[data-state="local"] { background: var(--text-secondary); }
.file-actions { display: flex; gap: 2px; flex-shrink: 0; }
.file-action {
  width: 40px; height: 40px; border-radius: 50%; border: none; background: transparent; cursor: pointer;
  color: var(--text-secondary); display: flex; align-items: center; justify-content: center; position: relative; overflow: hidden;
}
.file-action svg { width: 15px; height: 15px; }
.file-action:hover { background: rgba(128,128,128,0.14); color: var(--text-primary); }
.file-action--danger:hover { color: var(--danger); }

.grid-templates { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 16px; width: 100%; }
.template-card {
  background: var(--glass-fill); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--glass-border); border-radius: var(--radius-lg); padding: 20px; min-height: 120px;
  display: flex; flex-direction: column; justify-content: flex-end; font-weight: 600; font-size: 16px;
  box-shadow: var(--shadow-glass); transition: box-shadow 0.15s ease;
}
.template-card:active { transform: scale(0.97); }

.template-picker { display: flex; flex-direction: column; align-items: center; gap: 24px; width: 100%; height: 100%; overflow-y: auto; padding: 10px 0 30px; }
.grid-templates:empty { display: none; }
.import-tile-host { display: flex; justify-content: center; width: 100%; }

/* Sized to match the actual document view it stands in for — that view is
   height-driven (.pdf-stage-wrapper .pages-track fills available height at the A4
   ratio), so this needs to be too, not capped to a small fixed width regardless of
   how much room the stage actually has. */
.import-tile-doc {
  height: min(72vh, 640px); width: auto; max-width: 90vw; aspect-ratio: 210 / 297;
  border: 2px dashed var(--outline); border-radius: var(--radius-md);
  background: var(--glass-fill); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); box-shadow: var(--shadow-glass);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; text-align: center;
  padding: 24px; cursor: pointer; transition: border-color 0.15s ease, background 0.15s ease;
}
.import-tile-doc:hover, .import-tile-doc.drag-over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--glass-fill)); }
.import-tile-doc svg { width: 56px; height: 56px; color: var(--accent); }
.import-tile-doc .import-label { font-size: 17px; font-weight: 700; }
.import-tile-doc .import-hint { font-size: 12.5px; font-weight: 400; color: var(--text-secondary); max-width: 32ch; }
.import-tile-doc.busy { opacity: 0.6; pointer-events: none; }

.gen-review { width: min(560px, 90vw); margin-top: 8px; }
.gen-field-list { display: flex; flex-direction: column; gap: 6px; max-height: 320px; overflow-y: auto; }
.gen-field-row { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 10px; background: var(--surface-container); }
.gen-field-label { flex: 1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gen-field-type { font-size: 12px; padding: 6px 8px; border-radius: 8px; border: 1px solid var(--outline-variant); background: var(--surface); color: var(--text-primary); }
.gen-field-delete { width: 30px; height: 30px; border-radius: 50%; border: none; background: transparent; color: var(--text-secondary); display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0; }
.gen-field-delete svg { width: 14px; height: 14px; }
.gen-field-delete:hover { color: var(--danger); background: rgba(226,72,61,0.1); }
#generationsTitle { margin-bottom: 4px; }
#btnGenerationsOpen { margin-top: 14px; width: 100%; }

.editor-view { width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; }

.page-nav {
  display: flex; align-items: center; gap: 12px; padding: 6px 14px; border-radius: 999px;
  background: var(--glass-fill); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--glass-border); font-size: 13px; font-weight: 600; flex-shrink: 0;
}
.page-nav .icon-btn {
  width: 40px; height: 40px; border-radius: 50%; border: none; background: rgba(128,128,128,0.14);
  color: var(--text-primary); display: flex; align-items: center; justify-content: center; cursor: pointer;
  flex-shrink: 0;
}
.page-nav .icon-btn svg { width: 16px; height: 16px; }
.page-nav .icon-btn:disabled { opacity: 0.35; cursor: default; }

/* A4 fixed ratio in paginated mode — one page at a time. This replaces the earlier
   US-Letter (8.5/11) bug. Continuous mode stacks multiple A4 pages, so the ratio moves
   onto each .page-block instead of the wrapper — never drop the 210/297 ratio itself. */
.pdf-stage-wrapper {
  position: relative;
  flex: 1; min-height: 0; width: 100%;
  display: flex; align-items: center; justify-content: center;
}
.pdf-stage-wrapper.mode-paginated .pages-track {
  position: relative; height: 100%; max-height: 100%; aspect-ratio: 210 / 297;
  background: var(--page-paper); border-radius: var(--radius-md); overflow: hidden;
  box-shadow: 0 14px 40px rgba(0,0,0,0.16);
}
.pdf-stage-wrapper.mode-paginated .page-block { position: absolute; inset: 0; display: none; }
.pdf-stage-wrapper.mode-paginated .page-block.current { display: block; }

.pdf-stage-wrapper.mode-continuous {
  height: 100%; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch;
}
.pdf-stage-wrapper.mode-continuous .pages-track {
  display: flex; flex-direction: column; gap: 18px; width: min(100%, calc((100vh - 220px) * 210 / 297));
  margin: 0 auto; padding: 4px 0;
}
.pdf-stage-wrapper.mode-continuous .page-block {
  position: relative; width: 100%; aspect-ratio: 210 / 297; flex-shrink: 0;
  background: var(--page-paper); border-radius: var(--radius-md); overflow: hidden;
  box-shadow: 0 14px 40px rgba(0,0,0,0.16);
}

.page-block canvas { width: 100%; height: 100%; display: block; }
.overlay-container { position: absolute; inset: 0; }

.field {
  position: absolute; min-width: 44px; min-height: 44px;
  border: 1.5px dashed var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-radius: 6px; touch-action: none; display: flex; align-items: center; padding: 4px 8px;
  font-size: 13px; color: var(--accent);
}
.field--signature { border-style: solid; background-color: transparent; }

/* ---- Floating glass HUD ---- */
/* max-width + overflow-x:auto instead of letting content clip against .stage's
   overflow:hidden — on narrow phones the full button set is wider than the
   viewport, and clipping (rather than scrolling) made the Complete button
   partly unreachable. Scrolling keeps every control reachable at any width. */
.hud {
  position: absolute; bottom: 24px; left: 50%; transform: translateX(-50%);
  max-width: calc(100% - 24px);
  display: flex; align-items: center; gap: 4px; padding: 8px; border-radius: 22px;
  background: var(--glass-fill-strong); backdrop-filter: blur(24px) saturate(180%); -webkit-backdrop-filter: blur(24px) saturate(180%);
  border: 1px solid var(--glass-border); box-shadow: var(--shadow-glass); z-index: 20;
  overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.hud::-webkit-scrollbar { display: none; }
.hud-btn {
  width: 46px; height: 46px; border-radius: 15px; border: none; background: transparent; color: var(--text-primary);
  display: flex; align-items: center; justify-content: center; cursor: pointer; position: relative; overflow: hidden;
  transition: background 0.15s ease, transform 0.1s ease; flex-shrink: 0;
}
.hud-btn svg { width: 20px; height: 20px; }
.hud-btn:hover { background: rgba(128,128,128,0.14); }
.hud-btn:active { transform: scale(0.9); }
/* Persistent tool selection (Canvas brush/eraser/smudge/select/pan) — .active is
   toggled in JS but was never given a visible style, so switching tools looked like
   nothing happened. */
.hud-btn.active { background: var(--accent-container); color: var(--on-accent-container); }
.hud-btn.active:hover { background: var(--accent-container); }
.hud-divider { width: 1px; height: 26px; background: var(--glass-border); margin: 0 4px; flex-shrink: 0; }
.hud-complete {
  padding: 0 18px; height: 46px; border-radius: 15px; background: var(--accent); color: var(--accent-ink);
  font-size: 14px; font-weight: 600; border: none; cursor: pointer; display: flex; align-items: center; gap: 6px;
  position: relative; overflow: hidden; flex-shrink: 0; white-space: nowrap;
}
.hud-complete:active { transform: scale(0.96); }

/* ---- Ripple pulse (applied via JS to any .node-ripple element) ---- */
.ripple { position: absolute; border-radius: 50%; background: currentColor; opacity: 0.35; transform: scale(0);
  animation: ripple-anim 0.5s ease-out forwards; pointer-events: none; }
@keyframes ripple-anim { to { transform: scale(1); opacity: 0; } }

/* ---- Customize panel ---- */
.panel {
  position: absolute; top: 0; right: 0; bottom: 0; width: 300px;
  background: var(--glass-fill-strong); backdrop-filter: blur(24px) saturate(180%); -webkit-backdrop-filter: blur(24px) saturate(180%);
  border-left: 1px solid var(--glass-border); box-shadow: -8px 0 32px rgba(0,0,0,0.10);
  padding: max(24px, env(safe-area-inset-top)) 20px 20px;
  transform: translateX(100%); transition: transform 0.3s cubic-bezier(0.2,0.8,0.2,1);
  z-index: 40; overflow-y: auto;
}
.panel.open { transform: translateX(0); }
@media (orientation: portrait) { .panel { width: 100%; } }
.panel h3 { font-size: calc(15px * var(--text-scale-heading)); font-weight: 600; margin: 0 0 4px; }
.panel-section { margin-bottom: 22px; }
.panel-label { font-size: calc(11px * var(--text-scale-subheading)); font-weight: 600; color: var(--text-secondary); margin-bottom: 10px; }
.hint-text { font-size: 11px; color: var(--text-secondary); margin-top: 4px; }

.theme-row { display: flex; gap: 2px; padding: 3px; border-radius: 999px; background: var(--surface-container); }
.theme-swatch { flex: 1; height: 40px; border-radius: 999px; cursor: pointer; border: none;
  display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 500;
  color: var(--text-secondary); background: transparent; transition: background 0.18s ease, color 0.18s ease, font-weight 0.18s ease; }
.theme-swatch:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.theme-swatch.selected { background: var(--accent); color: var(--accent-ink); font-weight: 600; }

.gallery-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 10px; }
.gallery-thumb { aspect-ratio: 1; border-radius: 16px; cursor: pointer; border: 2px solid transparent; background-size: cover; background-position: center; box-shadow: var(--shadow-glass); overflow: hidden; background-clip: padding-box; }
.gallery-thumb.selected { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-container); }
.upload-btn { display: block; width: 100%; padding: 10px; font-size: 11.5px; font-weight: 600; text-align: center; border-radius: 12px;
  border: 1px dashed var(--outline); color: var(--text-secondary); cursor: pointer; }
.upload-btn:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); border-color: var(--accent); color: var(--accent); }

.action-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 44px; padding: 10px 16px; border-radius: var(--radius-md); border: 1px solid var(--outline-variant);
  background: var(--glass-fill); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  color: var(--text-primary); font-size: 13px; font-weight: 600; cursor: pointer;
  position: relative; overflow: hidden; white-space: nowrap;
}
.action-btn:hover { background: color-mix(in srgb, var(--accent) 8%, var(--glass-fill-strong)); }
.action-btn:active { transform: scale(0.96); }

.hue-row { display: flex; align-items: center; gap: 10px; }
.hue-row input[type=color] { width: 44px; height: 36px; border: none; border-radius: 12px; background: none; cursor: pointer; box-shadow: var(--shadow-glass); }

.font-select {
  width: 100%; padding: 10px 12px; margin-bottom: 8px; font-size: 13px; border-radius: 12px;
  border: 1px solid var(--outline-variant); background: var(--glass-fill); backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px); color: var(--text-primary); cursor: pointer;
}

.toggle-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.toggle-row span { font-size: 12.5px; }
.switch { position: relative; width: 44px; height: 26px; flex-shrink: 0; }
.switch input { opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.switch .track { position: absolute; inset: 0; background: var(--surface-container-high); border: 2px solid var(--outline); border-radius: 999px; pointer-events: none; transition: background 0.18s ease, border-color 0.18s ease; }
/* top is (track-height - knob-height) / 2 in both states — was 5px/3px against a 26px
   track (needs 7px/5px for a 12px/16px knob), so the knob sat visibly above center and
   jumped vertically on toggle instead of just sliding across. */
.switch .knob { position: absolute; top: 7px; left: 5px; width: 12px; height: 12px; border-radius: 50%; background: var(--outline); transition: transform 0.18s ease, background 0.18s ease, width 0.15s ease, height 0.15s ease, top 0.15s ease, left 0.15s ease; pointer-events: none; }
.switch input:checked + .track { background: var(--accent); border-color: var(--accent); }
.switch input:checked + .track + .knob { transform: translateX(15px); background: var(--accent-ink); width: 16px; height: 16px; top: 5px; left: 3px; }

.slider-row { margin-bottom: 14px; }
.slider-row label { font-size: 12px; color: var(--text-secondary); display: block; margin-bottom: 6px; }
.slider-row input[type=range] { width: 100%; accent-color: var(--accent); }

/* Browsers render <input type=color>'s actual color chip as an internal element that
   ignores the input's own border-radius unless targeted directly — left alone, a
   rectangular chip sits inside whatever rounded shape the input is styled as, with
   visible gaps at the corners. Applies to every circular color input in the app. */
input[type=color] { -webkit-appearance: none; appearance: none; }
input[type=color]::-webkit-color-swatch-wrapper { padding: 0; border-radius: inherit; }
input[type=color]::-webkit-color-swatch { border: none; border-radius: inherit; }
input[type=color]::-moz-color-swatch { border: none; border-radius: inherit; }

.effect-color {
  width: 26px; height: 26px; border: 2px solid var(--surface); border-radius: 50%; padding: 0; cursor: pointer;
  box-shadow: 0 0 0 1px var(--outline-variant); flex-shrink: 0;
}

/* ---- Modal ---- */
.modal { position: absolute; inset: 0; background: rgba(0,0,0,0.45); display: flex; align-items: center; justify-content: center; z-index: 50; }
.modal-card { border-radius: var(--radius-lg); padding: 24px; width: min(90%, 480px); }
.modal-card h2 { font-size: calc(18px * var(--text-scale-heading)); margin-bottom: 16px; }
.signature-canvas { width: 100%; height: 200px; background: rgba(255,255,255,0.6); border: 1px solid var(--glass-border); border-radius: var(--radius-md); touch-action: none; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; }

.btn { min-height: 44px; min-width: 44px; padding: 10px 18px; border-radius: var(--radius-md); border: none; font-size: 15px; font-weight: 600; cursor: pointer; }
.btn-primary { background: var(--accent); color: white; }
.btn-secondary { background: rgba(0,0,0,0.06); color: var(--text-primary); }

/* ---- Toast ---- */
.toast {
  position: absolute; top: max(20px, env(safe-area-inset-top)); left: 50%; transform: translateX(-50%) translateY(-16px);
  background: var(--glass-fill-strong); backdrop-filter: blur(20px); border: 1px solid var(--glass-border);
  box-shadow: var(--shadow-glass); padding: 12px 20px; border-radius: 14px; font-size: 13px; font-weight: 500;
  display: flex; align-items: center; gap: 8px; opacity: 0; pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease; z-index: 60;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); }
.toast-share {
  width: 26px; height: 26px; border-radius: 50%; border: none; background: rgba(128,128,128,0.16);
  color: var(--text-primary); display: flex; align-items: center; justify-content: center; cursor: pointer;
  pointer-events: auto;
}
.toast-share svg { width: 14px; height: 14px; }
.toast { pointer-events: none; }
.toast.show { pointer-events: auto; }

/* ---- NEXUS recording banner (persistent, unmissable, visible from any tab) ---- */
.nexus-rec-banner {
  position: absolute; top: max(20px, env(safe-area-inset-top)); left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px; background: var(--danger); color: #fff;
  padding: 8px 18px; border-radius: 999px; font-size: 13px; font-weight: 700; letter-spacing: 0.02em;
  box-shadow: 0 6px 20px rgba(226,72,61,0.4); z-index: 70; pointer-events: none;
}
.rec-dot { width: 9px; height: 9px; border-radius: 50%; background: #fff; animation: rec-pulse 1.1s ease-in-out infinite; }
@keyframes rec-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }

/* ---- NEXUS tab ---- */
.nexus-layout { display: flex; gap: 18px; width: 100%; height: 100%; }
.nexus-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 14px; overflow-y: auto; padding-bottom: 20px; }
.nexus-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 30px; }
.nexus-transcript {
  flex-shrink: 0; min-height: 160px; max-height: 320px; overflow-y: auto; padding: 16px; border-radius: var(--radius-md);
  background: var(--glass-fill); backdrop-filter: blur(16px); border: 1px solid var(--glass-border);
  font-size: 14px; line-height: 1.6; color: var(--text-primary);
}
.nexus-placeholder { color: var(--text-secondary); font-size: 13px; }
.nexus-transcript p { margin-bottom: 8px; }

.nexus-summary { padding: 16px; border-radius: var(--radius-md); background: var(--glass-fill); backdrop-filter: blur(16px); border: 1px solid var(--glass-border); }
.nexus-summary-h { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-secondary); margin: 14px 0 6px; }
.nexus-summary-h:first-child { margin-top: 0; }
.nexus-summary p, .nexus-summary ul { font-size: 13px; color: var(--text-primary); }
.nexus-summary ul { padding-left: 18px; }
.nexus-none { color: var(--text-secondary); }
.nexus-keywords { display: flex; gap: 6px; flex-wrap: wrap; }
.nexus-tag { font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: 999px; background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }

.nexus-export-row { display: flex; gap: 8px; flex-wrap: wrap; }

.nexus-history {
  width: 260px; flex-shrink: 0; display: flex; flex-direction: column; gap: 10px; padding: 16px;
  border-radius: var(--radius-md); background: var(--glass-fill); backdrop-filter: blur(16px); border: 1px solid var(--glass-border);
  overflow: hidden;
}
.nexus-search { padding: 8px 10px; border-radius: 8px; border: 1px solid var(--glass-border); background: rgba(128,128,128,0.08); font-size: 13px; color: var(--text-primary); }
.nexus-history-list { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
.nexus-history-item {
  text-align: left; padding: 9px 10px; border-radius: 8px; border: none; background: transparent; cursor: pointer;
  font-size: 12px; color: var(--text-primary); position: relative; overflow: hidden;
}
.nexus-history-item:hover { background: rgba(128,128,128,0.1); }
.nexus-history-item.active { background: var(--accent); color: var(--accent-ink); }
.nexus-history-empty { font-size: 12px; color: var(--text-secondary); padding: 10px 0; }

@media (orientation: portrait) {
  .nexus-layout { flex-direction: column; }
  .nexus-history { width: 100%; max-height: 220px; }
}

/* ---- Canvas tab ---- */
#screen-canvas { position: relative; }
.canvas-stage-wrapper {
  position: absolute; inset: 0; border-radius: var(--radius-md); overflow: hidden;
  background: repeating-conic-gradient(#e4e5ea 0% 25%, #edeef2 0% 50%) 50% / 24px 24px;
}
[data-theme="dark"] .canvas-stage-wrapper { background: repeating-conic-gradient(#1c1e24 0% 25%, #22242b 0% 50%) 50% / 24px 24px; }
.konva-container { width: 100%; height: 100%; touch-action: none; }

.canvas-color-input { width: 34px; height: 34px; border: none; border-radius: 10px; background: none; cursor: pointer; padding: 0; flex-shrink: 0; }
.canvas-size-input { width: 90px; accent-color: var(--accent); flex-shrink: 0; }

/* .panel defaults to transform:translateX(100%) (off-screen) until .open is added —
   the Customize panel toggles .open on rail-nav, but the Canvas layers panel is shown
   via .hidden instead (no slide animation needed), so it needs the transform disabled
   or it sits permanently just off the right edge, showing only a sliver. Bottom is
   pulled in above the floating HUD (which the base .panel's bottom:0 would otherwise
   sit on top of at z-index 45 vs. the HUD's 20, blocking clicks to it entirely). */
.canvas-panel { z-index: 45; transform: none; bottom: 100px; }
.canvas-panel.hidden { display: none; }

.canvas-layer-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.canvas-layer-row {
  display: flex; align-items: flex-start; gap: 8px; padding: 8px 10px; border-radius: 10px;
  background: rgba(128,128,128,0.08); font-size: 12px; cursor: pointer;
}
.canvas-layer-row.active { background: var(--accent-container); color: var(--on-accent-container); }
/* Two stacked rows to the right of the thumbnail — name+visibility on top, opacity
   and reorder controls below — instead of cramming everything onto one line, which
   left almost no width for the name (it was truncating to a single letter). */
.canvas-layer-row .layer-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.canvas-layer-row .layer-top-line { display: flex; align-items: center; gap: 6px; }
.canvas-layer-row .layer-bottom-line { display: flex; align-items: center; gap: 4px; }
.canvas-layer-row .layer-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Live per-layer preview — without this every row looked identical apart from its
   name, so adding a layer (a genuinely new, separate Konva raster underneath) looked
   like nothing had happened. */
.layer-thumb {
  width: 34px; height: 34px; border-radius: 8px; flex-shrink: 0; border: 1px solid var(--outline-variant);
  position: relative; overflow: hidden; background-color: #f0f0f0;
  background-image: linear-gradient(45deg, #ccc 25%, transparent 25%), linear-gradient(-45deg, #ccc 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #ccc 75%), linear-gradient(-45deg, transparent 75%, #ccc 75%);
  background-size: 8px 8px; background-position: 0 0, 0 4px, 4px -4px, -4px 0px;
}
.layer-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* Brush "armed" ring — shown from pointerdown until the pointer has moved past a
   small threshold, so bare contact previews where a stroke would start instead of
   immediately committing ink (the bug: startStroke() used to draw on touch alone). */
.brush-armed-ring {
  position: fixed; border: 1.5px dashed var(--accent); border-radius: 50%; pointer-events: none;
  z-index: 60; transform: translate(-50%, -50%); display: none;
}
.canvas-layer-row button {
  width: 28px; height: 28px; border-radius: 50%; border: none; background: transparent; color: var(--text-secondary);
  display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0;
}
.canvas-layer-row button svg { width: 14px; height: 14px; }
.canvas-layer-row .layer-opacity { flex: 1; min-width: 0; accent-color: var(--accent); }

.brush-import-tile {
  display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center;
  border: 1.5px dashed var(--outline); border-radius: var(--radius-md); padding: 20px 14px;
  cursor: pointer; transition: border-color 0.15s ease, background 0.15s ease;
}
.brush-import-tile:hover, .brush-import-tile.drag-over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.brush-import-tile svg { width: 26px; height: 26px; color: var(--accent); }
.brush-import-tile .import-label { font-size: 13px; font-weight: 700; }
.brush-import-tile .import-hint { font-size: 10.5px; color: var(--text-secondary); }

.consent-note { display: flex; gap: 8px; margin-top: 10px; padding: 10px 12px; border-radius: 10px; background: var(--surface-container); font-size: 10.5px; color: var(--text-secondary); line-height: 1.4; }

.brush-album-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(74px, 1fr)); gap: 10px; }
.brush-album-card { position: relative; background: rgba(128,128,128,0.08); border-radius: 12px; padding: 10px 6px; text-align: center; cursor: pointer; }
.brush-album-swatch { width: 34px; height: 34px; border-radius: 50%; margin: 0 auto 6px; background: var(--surface-container-high); display: flex; align-items: center; justify-content: center; }
.brush-album-swatch .dot { border-radius: 50%; background: currentColor; }
.brush-album-card .name { font-size: 10px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.brush-album-card .pack { font-size: 9px; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.layers-add-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.color-dual-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.color-palette-row { display: flex; flex-wrap: wrap; gap: 8px; }
.color-palette-swatch {
  width: 26px; height: 26px; border-radius: 50%; border: 2px solid var(--surface); cursor: pointer; padding: 0;
  box-shadow: 0 0 0 1px var(--outline-variant);
}
.color-palette-swatch.selected { box-shadow: 0 0 0 2px var(--accent); }

.canvas-brush-presets { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.brush-preset-swatch {
  width: 40px; height: 40px; border-radius: 50%; border: 2px solid transparent; cursor: pointer;
  display: flex; align-items: center; justify-content: center; background: rgba(128,128,128,0.1); position: relative;
}
.brush-preset-swatch.selected { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-container); }
.brush-preset-swatch .dot { border-radius: 50%; }
.brush-preset-delete, .brush-album-delete {
  position: absolute; top: -4px; right: -4px; width: 16px; height: 16px; border-radius: 50%;
  border: none; background: var(--danger); color: #fff; font-size: 10px; line-height: 1;
  display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0;
}
.brush-preset-swatch .preset-name {
  position: absolute; bottom: -16px; left: 50%; transform: translateX(-50%); font-size: 9px;
  color: var(--text-secondary); white-space: nowrap;
}

/* ---- Customize HUD (text-override design mode) ---- */
#screen-designmode { display: flex; flex-direction: column; gap: 18px; padding-bottom: 20px; overflow-y: auto; }
.design-intro { margin-top: 30px; max-width: 60ch; }
.design-intro h2 { font-size: calc(20px * var(--text-scale-heading)); font-weight: 700; margin-bottom: 6px; }
.design-intro p { font-size: 13px; color: var(--text-secondary); line-height: 1.5; }
.design-proxy-list { display: flex; flex-direction: column; gap: 6px; max-width: 640px; }
.design-proxy-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 16px; border-radius: var(--radius-md); background: var(--glass-fill);
  backdrop-filter: blur(14px); border: 1px solid var(--glass-border); cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.design-proxy-row:hover { background: var(--glass-fill-strong); border-color: var(--accent); }
.design-proxy-row.active { border-color: var(--accent); background: var(--accent-container); }
.design-proxy-text { font-size: 14px; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.design-proxy-tag { font-size: 10.5px; font-weight: 600; color: var(--text-secondary); background: var(--surface-container); padding: 4px 10px; border-radius: 999px; flex-shrink: 0; }

.inspector-stepper { display: flex; align-items: center; gap: 12px; }
.inspector-stepper button {
  width: 34px; height: 34px; border-radius: 10px; border: 1px solid var(--outline-variant);
  background: var(--glass-fill); color: var(--text-primary); font-size: 16px; cursor: pointer;
}
.inspector-stepper span { font-family: monospace; font-size: 13px; min-width: 46px; text-align: center; }
.inspector-actions-row { display: flex; gap: 8px; }
.inspector-actions-row .btn { flex: 1; }

/* ---- Sync status ---- */
.sync-status {
  position: absolute; top: max(20px, env(safe-area-inset-top)); right: 20px;
  display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-secondary);
  background: var(--glass-fill); backdrop-filter: blur(16px); padding: 6px 12px; border-radius: 999px;
  border: 1px solid var(--glass-border); z-index: 20; pointer-events: none;
}
.sync-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--success); }
.sync-status[data-state="syncing"] .sync-dot { background: var(--warning); }
.sync-status[data-state="failed"] .sync-dot { background: var(--danger); }
