/* batchlook — light theme, ported from the Claude Design handoff (design/archive/light-theme-handoff-2026-09-08/README.md). */
/* Every colour resolves through a variable on <html>, so switching theme is one attribute and no stylesheet
   swap. The app follows the OS by default; an explicit choice on <html data-theme> wins in either direction.
   The full-screen viewer deliberately does not participate: a neutral dark surround is how a photograph is
   judged, so it is #0B0D11 in both themes. */
:root {
  --bg:#FFFFFF; --surface:#F5F5F5; --card:#FFFFFF; --divider:#E1E1E1; --track:#EBEBEB; --disc:#E1E1E1; --border:#D5D5D5;
  --text:#2C2C2C; --text2:#505050; --muted:#6D6D6D; --faint:#B3B3B3;
  --accent:#1473E6; --accent-hover:#0D66D0; --accent-press:#0A58B5; --accent-tint:#EAF2FD; --accent-tag:#D6E6FB;
  --danger:#D70015; --danger-bg:#FDE7EA; --ok-fg:#1E7A3C; --ok-bg:#E3F5EA; --warn-fg:#9A5B00; --warn-bg:#FAF0DD;
  --on-accent:#FFFFFF;                       /* text on an accent fill: white in both themes */
  --veil:255,255,255;                        /* the dropzone gradient over the blurred sample pair */
  --r-pill:980px; --r-input:12px; --r-chip:6px; --r-md:8px; --r-card:20px; --r-drop:24px; --r-dialog:24px;
  --sh-sm:0 0 0 1px #E1E1E1; --sh-md:0 1px 2px rgba(0,0,0,.06), 0 8px 24px rgba(0,0,0,.10); --sh-lg:0 2px 6px rgba(0,0,0,.08), 0 24px 60px rgba(0,0,0,.18);
  --ease:cubic-bezier(.2,.8,.2,1);
  color-scheme:light;
}

/* Dark is not an inversion. The accent lightens because #1473E6 on #14171D is 3.4:1 — fine for a fill, not for
   the small accent text on approved labels and links. Shadows get heavier, not lighter: a 6% shadow is invisible
   on a dark ground. The veil inverts or the dropzone becomes a glowing white card with light text on it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:#14171D; --surface:#1C1F26; --card:#1C1F26; --divider:#2A2F38; --track:#262B35; --disc:#2A2F38; --border:#3A4150;
    --text:#E8EAF0; --text2:#C3C9D6; --muted:#8C93A3; --faint:#6B7383;
    --accent:#3B8EF0; --accent-hover:#5AA2F5; --accent-press:#2C7BDC; --accent-tint:#17283D; --accent-tag:#1D3350;
    --danger:#FF8A93; --danger-bg:#3A1116; --ok-fg:#7BD99B; --ok-bg:#14301F; --warn-fg:#E0AC5B; --warn-bg:#33260F;
    --veil:20,23,29;
    --sh-sm:0 0 0 1px #2A2F38; --sh-md:0 1px 2px rgba(0,0,0,.40), 0 8px 24px rgba(0,0,0,.50); --sh-lg:0 2px 6px rgba(0,0,0,.45), 0 24px 60px rgba(0,0,0,.60);
    color-scheme:dark;
  }
}
:root[data-theme="dark"] {
  --bg:#14171D; --surface:#1C1F26; --card:#1C1F26; --divider:#2A2F38; --track:#262B35; --disc:#2A2F38; --border:#3A4150;
  --text:#E8EAF0; --text2:#C3C9D6; --muted:#8C93A3; --faint:#6B7383;
  --accent:#3B8EF0; --accent-hover:#5AA2F5; --accent-press:#2C7BDC; --accent-tint:#17283D; --accent-tag:#1D3350;
  --danger:#FF8A93; --danger-bg:#3A1116; --ok-fg:#7BD99B; --ok-bg:#14301F; --warn-fg:#E0AC5B; --warn-bg:#33260F;
  --veil:20,23,29;
  --sh-sm:0 0 0 1px #2A2F38; --sh-md:0 1px 2px rgba(0,0,0,.40), 0 8px 24px rgba(0,0,0,.50); --sh-lg:0 2px 6px rgba(0,0,0,.45), 0 24px 60px rgba(0,0,0,.60);
  color-scheme:dark;
}

* { box-sizing:border-box; }
[hidden] { display:none !important; }
html, body { height:100%; }
body { margin:0; background:var(--bg); color:var(--text); font:14px/1.45 "Inter", system-ui, -apple-system, sans-serif; -webkit-font-smoothing:antialiased; overflow:hidden; }
a { color:var(--accent); text-decoration:none; } a:hover { color:var(--accent-hover); }
h1,h2,h3,h4,h5 { margin:0; font-weight:700; letter-spacing:-.02em; }
h6 { margin:0; font-size:11px; letter-spacing:.08em; text-transform:uppercase; color:var(--muted); font-weight:600; }
button { font:inherit; color:inherit; cursor:pointer; background:none; border:0; padding:0; white-space:nowrap; }
::selection { background:color-mix(in srgb, var(--accent) 30%, transparent); }
:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.num { font-variant-numeric:tabular-nums; }
.hint { font-size:12px; color:var(--muted); }
.spacer { flex:1; }

/* ---- buttons, tags, inputs ---- */
.btn { display:inline-flex; align-items:center; justify-content:center; gap:8px; height:36px; padding:0 18px; border-radius:var(--r-pill); border:2px solid transparent; font-weight:700; font-size:14px; line-height:1; transition:background 120ms, color 120ms, border-color 120ms, transform 120ms; }
.btn:active { transform:scale(.97); }
.btn:disabled, .btn[aria-disabled="true"] { opacity:.45; cursor:not-allowed; transform:none; }
.btn svg { display:block; flex:none; }
.btn-primary { background:var(--accent); color:var(--on-accent); }
.btn-primary:hover:not(:disabled) { background:var(--accent-hover); }
.btn-primary:active:not(:disabled) { background:var(--accent-press); }
.btn-primary .tag { background:rgba(255,255,255,.22); color:var(--on-accent); }
.btn-secondary { background:transparent; border-color:var(--text); color:var(--text); }
.btn-secondary:hover:not(:disabled) { background:var(--text); color:var(--on-accent); }
.btn-secondary:hover:not(:disabled) .tag { background:rgba(255,255,255,.22); color:var(--on-accent); }
.btn-secondary.is-accent { color:var(--accent); border-color:var(--accent); }
.btn-secondary.is-accent:hover:not(:disabled) { background:var(--accent); color:var(--on-accent); }
.btn-ghost { color:var(--text); text-decoration:underline; text-underline-offset:3px; padding:0 6px; font-weight:500; }
.btn-ghost:hover:not(:disabled) { color:var(--accent); }
.btn-ghost.muted { color:var(--muted); }
.btn-danger { color:var(--danger); text-decoration:underline; text-underline-offset:3px; padding:0 6px; font-weight:500; }
.btn-icon { width:36px; padding:0; }
.h24 { height:24px; padding:0 9px; font-size:12px; } .h26 { height:26px; padding:0 6px; font-size:12px; } .h28 { height:28px; padding:0 10px; font-size:12px; }
.h30 { height:30px; padding:0 10px; } .h40 { height:40px; } .h44 { height:44px; font-size:15px; }
.tag { display:inline-flex; align-items:center; gap:4px; padding:1px 7px; border-radius:var(--r-chip); font-size:11px; font-weight:600; line-height:1.5; white-space:nowrap; }
.tag-neutral { background:var(--disc); color:var(--text); }
.tag-accent { background:var(--accent-tag); color:var(--accent); }
.tag-outline { border:1px solid rgba(20,115,230,.35); color:var(--accent); padding:0 6px; font-size:10px; }
.tag-danger { background:var(--danger-bg); color:var(--danger); }
.tag-ok { background:var(--ok-bg); color:var(--ok-fg); }
.ph .stag { position:absolute; top:8px; left:8px; }
.input, select.input { min-height:40px; padding:0 12px; border-radius:var(--r-input); border:1px solid var(--border); background:var(--card); color:var(--text); font:inherit; font-size:14px; }
.input:hover { border-color:color-mix(in srgb, var(--text) 45%, transparent); } .input:focus { border-color:var(--accent); outline:none; }
.input:focus-visible { border-color:var(--accent); outline:2px solid var(--accent); outline-offset:0; }
.input::placeholder { color:var(--faint); }
select.input { appearance:none; -webkit-appearance:none; padding-right:30px; background:var(--card) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236D6D6D' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 10px center; cursor:pointer; }
.pills { display:flex; background:var(--track); border-radius:var(--r-pill); padding:2px; }
.pills button { flex:1; padding:5px 0; font-size:12px; border-radius:var(--r-pill); color:var(--muted); font-weight:500; }
.pills button.on { background:var(--card); color:var(--text); box-shadow:var(--sh-sm); }
.toggle { width:38px; height:22px; border-radius:99px; background:var(--disc); position:relative; }
.toggle { transition:background 160ms; }
.toggle i { position:absolute; top:3px; left:3px; width:16px; height:16px; border-radius:50%; background:#fff; box-shadow:0 1px 2px rgba(0,0,0,.3); transition:left 160ms var(--ease); }
.toggle:disabled { opacity:.45; cursor:not-allowed; }
.toggle.on { background:var(--accent); } .toggle.on i { left:19px; }

/* ---- app shell ---- */
.app { height:100vh; display:flex; flex-direction:column; background:var(--bg); }
.nav .menu { display:none; color:var(--text); }
.panel-backdrop { display:none; }
.nav { height:56px; flex:none; display:flex; align-items:center; gap:12px; padding:0 20px 0 26px; background:var(--surface); box-shadow:inset 0 -1px 0 var(--divider); }
/* The lock-up is a tall mark beside short letters, 4.193:1. Set the height and let the width follow.
   Baseline, not centre: centring aligns the logo's bounding box, and the b's ascender then pushes the wordmark
   below the breadcrumb. The wordmark has no descenders, so its baseline is the bottom edge of the artwork and
   `align-items:baseline` lands it exactly on the breadcrumb's text baseline. */
.lede { display:flex; align-items:baseline; gap:12px; min-width:0; white-space:nowrap; }
.lede .crumb-name { overflow:hidden; text-overflow:ellipsis; }
.brand { flex:none; display:flex; align-items:center; }
.brand img { height:26px; width:auto; display:block; }
.crumb { color:var(--faint); } .crumb-name { font-weight:500; }
.credits { position:relative; display:flex; align-items:center; gap:8px; height:32px; padding:0 6px 0 12px; border-radius:var(--r-pill); border:1px solid var(--divider); background:var(--card); font-weight:500; overflow:hidden; }
.credits .flash { position:absolute; inset:0; background:var(--accent-tint); animation:bl-flash 700ms ease-out both; pointer-events:none; }
.credits > * { position:relative; }
.credits .n { min-width:64px; white-space:nowrap; }
.credits .add { width:24px; padding:0; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; }
.avatar { width:32px; height:32px; border-radius:50%; background:var(--disc); color:var(--text2); display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:600; }
.avatar:hover { background:var(--accent-tint); color:var(--accent); }
.body { display:flex; flex:1; min-height:0; }
.rail { width:72px; flex:none; background:var(--surface); box-shadow:inset -1px 0 0 var(--divider); display:flex; flex-direction:column; align-items:center; padding:10px 0 12px; gap:2px; }
.rail button { width:60px; height:58px; border-radius:var(--r-md); display:flex; flex-direction:column; align-items:center; justify-content:center; gap:5px; font-size:10px; font-weight:500; color:var(--muted); transition:background 120ms, color 120ms; }
.rail button:hover { background:var(--track); color:var(--text); }
.rail button.on { background:var(--accent-tint); color:var(--accent); }
/* Two regions, not one long column: the jobs list takes what is left and scrolls on its own, so Sets stays in
   view however many jobs are open. Sets get at most the lower part and scroll too. */
.panel { width:224px; flex:none; background:var(--surface); box-shadow:inset -1px 0 0 var(--divider); padding:16px 12px; display:flex; flex-direction:column; gap:22px; overflow:hidden; }
.panel-sec { display:flex; flex-direction:column; gap:8px; flex:1 1 0; min-height:0; }
#sceneSection { flex:0 0 auto; max-height:45%; }   /* its own height first (a job has a handful of sets); jobs take the rest */
#projectList, #sceneList { overflow:auto; min-height:0; overscroll-behavior:contain; }
.panel-head { display:flex; justify-content:space-between; align-items:center; }
.panel .search { min-height:32px; padding:0 10px; font-size:13px; }
.rows { display:flex; flex-direction:column; gap:2px; }
.rowi { padding:9px 10px; border-radius:var(--r-md); cursor:pointer; transition:background 120ms; position:relative; }
.rowi:hover { background:var(--track); }
.rowi.on { background:var(--bg); outline:1px solid var(--accent); outline-offset:-1px; }
.rowi .t { display:flex; justify-content:space-between; align-items:center; gap:6px; font-weight:400; }
.rowi.on .t { font-weight:500; }
.rowi .s { font-size:11px; color:var(--muted); margin-top:2px; }
.rowi .del { position:absolute; right:8px; top:8px; font-size:12px; color:var(--muted); opacity:0; }
.rowi:hover .del { opacity:1; } .rowi .del:hover { color:var(--danger); }
.seti { padding:8px 10px; }
.seti .c { color:var(--muted); font-weight:400; }
.main { --pad-x:22px; --pad-y:18px; flex:1; min-width:0; overflow:hidden; padding:var(--pad-y) var(--pad-x); display:flex; flex-direction:column; gap:14px; }

/* ---- job header ---- */
/* Plain, no background. An earlier draft washed this with the approved photo's dominant colour; dropped, because
   twilight averages to a muddy grey-blue that barely registers and a sunny set shifts it somewhere else entirely.
   Colour lives in the photographs; the chrome stays neutral. */
.jobhead { display:flex; justify-content:space-between; align-items:flex-start; padding:12px 0 0; margin:0; transition:background 900ms ease; }
.jobhead h4 { font-size:20px; }
.jobhead .meta { font-size:12px; color:var(--muted); margin-top:2px; white-space:nowrap; }
.jobhead-actions { display:flex; gap:6px; align-items:center; }
/* A job's state is worth showing as state, not as a dropdown. The pill is tinted by what it says, and the menu
   carries the one-line explanation that used to live in a title attribute nobody hovers. */
.statuswrap { position:relative; }
.statuspill { display:flex; align-items:center; gap:7px; height:30px; padding:0 11px; border-radius:var(--r-pill); font-size:13px; font-weight:600;
  background:var(--st-bg); color:var(--st-fg); border:1px solid color-mix(in srgb, var(--st-fg) 32%, transparent); }
.statuspill .dot { width:7px; height:7px; border-radius:50%; background:currentColor; flex:none; }
.statuspill svg { transition:transform 160ms var(--ease); }
.statuspill[aria-expanded="true"] svg { transform:rotate(180deg); }
.statuspill.active { --st-bg:var(--accent-tint); --st-fg:var(--accent); }
.statuspill.delivered { --st-bg:var(--ok-bg); --st-fg:var(--ok-fg); }
.statuspill.archived { --st-bg:var(--track); --st-fg:var(--muted); }
.statusmenu { position:absolute; top:calc(100% + 6px); right:0; width:272px; z-index:20; background:var(--card); border-radius:14px;
  box-shadow:var(--sh-md); padding:6px; display:flex; flex-direction:column; animation:bl-rise 160ms var(--ease) both; }
.statusmenu button { display:flex; gap:9px; align-items:flex-start; padding:9px 10px; border-radius:10px; text-align:left; color:var(--text); }
.statusmenu button:hover { background:var(--surface); }
.statusmenu .dot { width:7px; height:7px; border-radius:50%; margin-top:5px; flex:none; }
.statusmenu .n { font-size:13px; font-weight:600; display:block; }
.statusmenu .w { font-size:11.5px; color:var(--muted); display:block; margin-top:1px; }
.statusmenu .tick { margin-left:auto; color:var(--accent); flex:none; }
.jobhead select.input { min-height:30px; padding:0 28px 0 10px; font-size:13px; border-radius:var(--r-pill); }

/* ---- empty state ---- */
/* Held until the first load decides which of empty/workspace is right; a blank moment beats the wrong screen. */
.boot { flex:1; display:grid; place-items:center; }
.boot .bigspin, .app-loading .bigspin { width:26px; height:26px; background:url(/loader.svg) center / contain no-repeat; border:0; opacity:.7; }
.app-loading { height:100%; display:grid; place-content:center; justify-items:center; gap:16px; }
.app-loading .bigspin { background:var(--muted); mask:url(/loader.svg) center / contain no-repeat; }
.empty { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:22px; animation:bl-rise 420ms var(--ease) both; }
.empty h2 { font-size:32px; }
.empty p { margin:0; color:var(--text2); font-size:16px; }
.dropzone { position:relative; width:640px; max-width:100%; padding:52px 32px; border-radius:var(--r-drop); background:var(--surface); display:flex; flex-direction:column; align-items:center; gap:12px; cursor:pointer; overflow:hidden; transition:box-shadow 200ms; }
.dropzone:hover, .dropzone.over { box-shadow:0 0 0 2px var(--accent), 0 12px 40px rgba(0,0,0,.08); }
.dropzone .bgpair { position:absolute; inset:-24px; display:grid; grid-template-columns:1fr 1fr; gap:8px; filter:blur(20px) saturate(1.1); opacity:.5; pointer-events:none; }
.dropzone .bgpair span { background-size:cover; background-position:center; }
.dropzone .veil { position:absolute; inset:0; background:linear-gradient(180deg, rgba(var(--veil), .55), rgba(var(--veil), .94) 72%); pointer-events:none; }
.dropzone > *:not(.bgpair):not(.veil) { position:relative; }
.dropzone .disc { width:56px; height:56px; border-radius:50%; background:var(--card); box-shadow:0 2px 10px rgba(0,0,0,.10); display:flex; align-items:center; justify-content:center; color:var(--accent); }
.dropzone .t { font-size:18px; font-weight:500; }

/* ---- presets ---- */
.presets { display:flex; gap:6px; align-items:flex-start; flex-wrap:wrap; }
/* The empty state is a centred column (title, dropzone, button), so its preset grid centres too and the last
   part-filled row sits under the middle rather than leaving a gap on the right. The toolbar copy stays left
   aligned, where it lines up with the prompt box beneath it. */
#presetsEmpty { justify-content:center; }
.preset { width:98px; padding:6px 0 5px; border-radius:var(--r-md); display:flex; flex-direction:column; align-items:center; gap:5px; color:var(--text2); transition:background 120ms, color 120ms; }
.preset:hover { background:var(--track); }
.preset .disc { width:34px; height:34px; border-radius:50%; background:var(--disc); display:flex; align-items:center; justify-content:center; transition:background 120ms; }
.preset.on { color:var(--accent); } .preset.on .disc { background:var(--accent-tint); outline:1px solid var(--accent); outline-offset:-1px; }
.preset.add .disc { background:transparent; border:1px dashed var(--faint); }
.preset .l { font-size:11px; white-space:nowrap; max-width:100%; padding:0 4px; overflow:hidden; text-overflow:ellipsis; }

/* ---- toolbar ---- */
.toolbar { display:flex; flex:none; flex-direction:column; gap:10px; }
.toolbar .presets { flex-wrap:nowrap; overflow-x:auto; padding:2px; margin:-2px; scrollbar-width:none; }
.toolbar .preset { flex:0 0 98px; }
.toolbar .row { display:flex; gap:10px; align-items:center; flex-wrap:wrap; }
.toolbar #prompt { flex:1 1 240px; min-width:0; height:40px; }
.toolbar #provider { flex:0 1 210px; min-width:180px; height:40px; }
.action-bar { flex:none; display:flex; flex-direction:column; gap:8px; padding-top:12px; background:linear-gradient(to right, transparent, var(--divider) 48px, var(--divider) calc(100% - 48px), transparent) no-repeat top / 100% 1px; }
.steps { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.steps .btn { font-size:12px; padding-inline:12px; gap:6px; }
.steps .btn-ghost { padding-inline:4px; }
.steps .btn.progress:disabled { opacity:1; cursor:progress; }
.steps .main-done { background:var(--surface); color:var(--text2); border-color:transparent; font-weight:500; }
.steps .main-done svg { color:var(--ok-fg); }
.batch-targets { display:flex; gap:8px; align-items:center; }
.selection-total { display:none; font-size:12px; }
.sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0; }
.spin { display:inline-block; width:14px; height:14px; background:url(/loader-white.svg) center / contain no-repeat; border:0; }
.spin.dark { background-image:url(/loader.svg); }
/* The shutter turns: 1.2s linear, per design/archive/light-theme-handoff-2026-09-08/logo/README.md. Seven blades tile a complete
   circle, so the silhouette never changes as it rotates — only the tones advance, which is the whole reason
   the mark went to seven. The README says the rule lives inside each SVG; it does not, in our copies or in the
   bundle's, so it lives here. Without it the aperture that replaced the ring spinner has just sat still.
   The global reduced-motion rule sets animation-duration to 1ms, which on an infinite spin is a strobe rather
   than a stop, so these are turned off by name instead. */
/* The grid is rebuilt from innerHTML once a second while edits run, so every spinner is a brand-new element
   that would start its rotation from 0 again — which is the flicker. --spin-phase is a negative delay carrying
   where the turn has got to, so a fresh element picks it up mid-rotation and every spinner turns in unison. */
.spin, .bigspin { animation:bl-spin 1.2s linear infinite; animation-delay:var(--spin-phase, 0ms); }
@media (prefers-reduced-motion: reduce) { .spin, .bigspin { animation:none !important; } }
.btn.unlock { animation:bl-unlock 900ms var(--ease) 120ms both; }
.btn.shake { animation:bl-shake 400ms var(--ease) both; }
.btn.progress { position:relative; overflow:hidden; }
.btn.progress .bar { position:absolute; left:0; top:0; bottom:0; background:rgba(255,255,255,.25); transition:width 420ms var(--ease); }
.btn.progress > *:not(.bar) { position:relative; }
.statusrow { display:flex; justify-content:space-between; gap:16px; min-height:18px; font-size:12px; color:var(--muted); }
.statusrow #spent { margin-left:auto; white-space:nowrap; }
.statusrow .st { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.statusrow .st.warn { color:var(--warn-fg); } .statusrow .st.err { color:var(--danger); }

/* ---- continuity strip ---- */
.strip-card { border-radius:var(--r-input); background:var(--surface); flex:none; max-width:100%; }
.strip-card:has(.cleanup) { flex:1 1 100%; }
.stripbar { display:flex; align-items:center; gap:8px; padding:0 12px; min-height:40px; font-size:12px; }
.stripbar .done { display:flex; align-items:center; gap:6px; font-size:12px; color:var(--text2); animation:bl-rise 320ms var(--ease) both; }
.stripbar .done svg { color:var(--ok-fg); flex:none; }
.stripbar #sheetToggle { width:56px; flex:0 0 56px; }
.stripbar .cleanup { padding-block:8px; color:var(--muted); }
.continuity-mobile { display:none; }
.sheetbody { min-height:0; max-height:30vh; overflow:auto; }
.sheetbody textarea { width:100%; resize:vertical; min-height:130px; font:12.5px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; color:var(--text); background:var(--card); border:1px solid var(--border); border-radius:var(--r-input); padding:10px 12px; }

/* ---- photo grid ---- */
.gridwrap { flex:1; min-height:0; overflow:auto; padding:4px 4px 8px; margin:-4px -4px 0; scrollbar-gutter:stable; }
.grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(300px, 1fr)); gap:14px; align-items:start; }
.card { display:flex; flex-direction:column; background:var(--surface); border-radius:var(--r-card); overflow:hidden; border:2px solid transparent; transition:border-color 240ms var(--ease); }
.card[data-selected] { border-color:var(--accent); background:var(--accent-tint); }
.card:focus { outline:none; }
.card:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.card .xdel { opacity:0; transition:opacity 120ms; } .card:hover .xdel, .card.kb .xdel, .card .xdel:focus-visible { opacity:1; } .card .xdel:hover { color:var(--danger); }
.v-blend { display:inline-flex; align-items:center; gap:6px; font-size:11px; color:var(--text2); margin-left:4px; } .v-blend input { width:110px; accent-color:var(--accent); }
.card.enter { animation:bl-rise 420ms var(--ease) both; }
.card .head { display:flex; justify-content:space-between; align-items:center; gap:9px; padding:2px 8px 2px 12px; min-height:38px; }
.card .head > :last-child { flex:none; }
.card .head .acts { display:flex; align-items:center; gap:2px; }
.card .head .btn-icon.h24 { width:24px; }
.card .head .has-note { color:var(--accent); }
.card .head .fn { flex:1; min-width:0; font-size:13px; font-weight:500; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.card .main-tag { font-size:10px; letter-spacing:.04em; padding:2px 7px; }
.main-price { color:var(--accent); font-size:10px; white-space:nowrap; }
.select-reason { font-size:10px; font-weight:400; color:var(--muted); max-width:48%; overflow:hidden; text-overflow:ellipsis; }
.make-main { display:none; }
.card:hover .make-main, .card:focus-within .make-main { display:inline-flex; }
.new-version { position:absolute; top:8px; right:8px; font-size:10px; letter-spacing:.05em; }
.card .foot .msg.new-label { color:var(--accent); font-weight:600; }
.pair { display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:2px; background:var(--track); }
.ph { position:relative; aspect-ratio:3/2; overflow:hidden; background:var(--track); cursor:zoom-in; }
.ph img { width:100%; height:100%; object-fit:cover; display:block; }
.ph.dark { background:#000; }   /* black behind a photograph in both themes, same reason the viewer stays dark */
.ph .cap { position:absolute; left:8px; bottom:8px; font-size:11px; padding:2px 8px; border-radius:4px; background:rgba(0,0,0,.7); color:var(--on-accent); white-space:nowrap; max-width:calc(100% - 16px); overflow:hidden; text-overflow:ellipsis; }
.ph .cap.late { animation:bl-fade 240ms 300ms both; }
.ph img.reveal { animation:bl-reveal 560ms var(--ease) both; }
.ph .blur { width:100%; height:100%; background-size:cover; background-position:center; filter:blur(12px) brightness(.45) saturate(.6); transform:scale(1.1); }
.ph .shimmer { position:absolute; inset:0; background:linear-gradient(100deg, transparent 35%, rgba(20,115,230,.22) 50%, transparent 65%); animation:bl-shimmer 1.8s cubic-bezier(.4,0,.6,1) infinite; }
.ph .center { position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px; text-align:center; padding:0 20px; font-size:12px; color:var(--muted); animation:bl-fade 240ms both; }
.ph .center.onDark { color:var(--on-accent); }
.ph .center .bigspin { width:26px; height:26px; background:url(/loader-white.svg) center / contain no-repeat; border:0; }
.ph .center.fail { animation:bl-rise 320ms var(--ease) both; }
.ph .center.fail b { color:var(--danger); font-weight:500; font-size:14px; }
.card .foot { display:flex; align-items:center; gap:8px; padding:8px 12px; min-height:46px; flex-wrap:nowrap; }
.card .foot .msg { font-size:12px; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0; }
.card .foot .btn { padding-inline:12px; }
.card .foot .acts { display:flex; gap:8px; align-items:center; flex-shrink:0; margin-left:auto; }
.card .foot:has([data-keep-old]) { flex-wrap:wrap; }
.card .foot:has([data-keep-old]) .new-label { flex-shrink:0; }
.card .foot:has([data-keep-old]) .acts > .btn-ghost { padding-inline:0; }
.card .foot .approved { flex-shrink:0; }
.card .foot .undo { padding-inline:6px; margin-left:-4px; flex-shrink:0; }
.card .foot .msg.err { color:var(--danger); }
.approved { display:flex; align-items:center; gap:6px; color:var(--accent); font-weight:500; }
.approved .disc { display:flex; width:18px; height:18px; border-radius:50%; background:var(--accent-tint); align-items:center; justify-content:center; }
.approved.anim .disc { animation:bl-pop 360ms var(--ease) both; }
.approved.anim path { stroke-dasharray:24; animation:bl-draw 300ms var(--ease) 120ms both; }
.version-history { padding:0 12px 8px; }
.version-history .btn { font-size:11px; padding-inline:0; }
.version-thumb, .v-strip .pending { position:relative; display:block; width:60px; height:40px; flex:0 0 60px; padding:0; border:2px solid transparent; border-radius:6px; box-sizing:border-box; }
.version-thumb img { display:block; width:100%; height:100%; object-fit:cover; border-radius:4px; opacity:.55; transition:opacity 120ms; }
.version-thumb:hover img { opacity:.85; }
.version-thumb.sel { border-color:var(--accent); }
.version-thumb.sel img, .version-thumb.acc img { opacity:1; }
.version-thumb.acc::after { content:'✓'; position:absolute; right:-5px; bottom:-5px; width:16px; height:16px; display:grid; place-items:center; border:2px solid var(--surface); border-radius:50%; background:var(--ok-fg); color:var(--bg); font-size:10px; line-height:1; font-weight:700; }
.version-thumb.fresh::before { content:''; position:absolute; top:-4px; right:-4px; z-index:1; width:11px; height:11px; border:2px solid var(--surface); border-radius:50%; background:var(--accent); }
.version-thumb:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.droptile { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px; min-height:200px; align-self:stretch; border-radius:14px; border:1px dashed var(--border); color:var(--muted); cursor:pointer; transition:border-color 160ms, background 160ms, color 160ms; }
.droptile:hover, .droptile.over { border-color:var(--accent); color:var(--accent); background:rgba(20,115,230,.06); }
.card.enter.i0{animation-delay:0ms}.card.enter.i1{animation-delay:70ms}.card.enter.i2{animation-delay:140ms}.card.enter.i3{animation-delay:210ms}.card.enter.i4{animation-delay:280ms}.card.enter.i5{animation-delay:350ms}.card.enter.i6{animation-delay:420ms}.card.enter.i7{animation-delay:490ms}.card.enter.i8{animation-delay:560ms}

/* ---- toasts ---- */
.toasts { position:fixed; right:20px; bottom:20px; display:flex; flex-direction:column; gap:10px; z-index:60; }
.toast { position:relative; width:360px; display:flex; gap:12px; align-items:flex-start; padding:12px 14px; border-radius:var(--r-card); background:var(--card); box-shadow:var(--sh-md); animation:bl-rise 420ms var(--ease) both; }
.toast.out { animation:bl-fadeout 220ms ease-in both; }
.toast .ic { width:22px; height:22px; border-radius:50%; flex:none; display:flex; align-items:center; justify-content:center; background:var(--accent-tint); color:var(--accent); animation:bl-pop 360ms var(--ease) 200ms both; }
.toast.err .ic { background:var(--danger-bg); color:var(--danger); } .toast.warn .ic { background:var(--warn-bg); color:var(--warn-fg); }
.toast .tt { font-weight:500; } .toast .ts { font-size:12px; color:var(--muted); }
.toast .timer { position:absolute; left:14px; right:14px; bottom:0; height:2px; border-radius:99px; overflow:hidden; }
.toast .timer i { display:block; height:100%; background:var(--accent); opacity:.6; animation:bl-fill 4000ms linear both; }
.toast.err .timer i { background:var(--danger); } .toast.warn .timer i { background:var(--warn-fg); }

/* ---- dialogs ---- */
dialog { border:0; padding:0; background:transparent; color:var(--text); }
dialog::backdrop { background:rgba(20,22,28,.45); animation:bl-fade 240ms both; }
.dlg { background:var(--card); border-radius:var(--r-dialog); box-shadow:var(--sh-lg); padding:24px 26px; display:flex; flex-direction:column; gap:16px; animation:bl-sheet 420ms var(--ease) both; }
.dlg h2 { font-size:18px; }
.dlg label { display:block; font-size:12px; color:var(--muted); font-weight:500; }
.dlg label .input { display:block; width:100%; margin-top:4px; color:var(--text); font-weight:400; }
.dlg .two { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.dlg label.check { display:flex; align-items:center; gap:8px; color:var(--text); font-weight:400; font-size:13px; }
.dlg-actions { display:flex; align-items:center; gap:8px; margin-top:4px; }
#jobDialog .dlg { width:min(480px, 92vw); }
#quoteDialog .dlg { width:580px; }
.exlist { display:flex; flex-direction:column; gap:6px; }
.exrow { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:8px 12px; border-radius:var(--r-md); background:var(--surface); }
.exrow .t { display:flex; align-items:center; gap:6px; font-weight:500; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.exrow select.input { min-height:32px; font-size:13px; padding-right:28px; width:220px; flex:none; }
.hlist { margin:0; padding-left:20px; display:flex; flex-direction:column; gap:6px; font-size:13px; color:var(--text2); }
.keys { display:grid; grid-template-columns:1fr 1fr; gap:6px 14px; font-size:12px; color:var(--text2); }
kbd { display:inline-block; min-width:18px; padding:1px 5px; margin-right:3px; border-radius:4px; background:var(--surface); border:1px solid var(--border); font:11px/1.4 ui-monospace, Menlo, monospace; color:var(--text); text-align:center; }
.dlg label textarea.input { display:block; width:100%; margin-top:4px; min-height:70px; font-weight:400; color:var(--text); }
.qsum { display:flex; align-items:center; gap:16px; padding:12px 14px; border-radius:var(--r-md); background:var(--surface); }
.qsum .cover { position:relative; height:6px; width:120px; border-radius:99px; background:var(--disc); overflow:hidden; }
.qsum .cover .have { position:absolute; left:0; top:0; bottom:0; background:var(--muted); }
.qsum .cover .add { position:absolute; top:0; bottom:0; background:var(--accent); transition:left 200ms, width 420ms var(--ease); }
.packs { display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:10px; }
.pack { position:relative; text-align:left; padding:14px; border-radius:var(--r-md); background:var(--surface); color:var(--text); display:flex; flex-direction:column; gap:2px; transition:box-shadow 200ms var(--ease), transform 200ms var(--ease); }
.pack:hover { box-shadow:0 0 0 1px var(--border); }
.pack.on { box-shadow:0 0 0 2px var(--accent); transform:scale(1.02); }
.pack .k { font-weight:500; font-size:16px; } .pack .s { font-size:12px; color:var(--muted); } .pack .p { margin-top:10px; font-size:18px; font-weight:500; }
.pack .chk { position:absolute; top:10px; right:10px; width:18px; height:18px; border-radius:50%; background:var(--accent); display:flex; align-items:center; justify-content:center; animation:bl-pop 300ms var(--ease) both; }
.ledger { display:flex; flex-direction:column; gap:2px; max-height:180px; overflow:auto; }
.ledrow { display:flex; justify-content:space-between; gap:12px; font-size:12px; padding:4px 2px; border-bottom:1px solid var(--track); }
.ledrow .w { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ledrow .d { flex:none; font-weight:500; } .ledrow .d.neg { color:var(--muted); } .ledrow .d.pos { color:var(--accent); }
.qnote { display:flex; align-items:center; gap:10px; padding:10px 12px; border-radius:var(--r-md); box-shadow:0 0 0 1px var(--divider); font-size:12px; color:var(--muted); }

/* ---- full-screen viewer ---- */
.viewer { position:fixed; inset:0; background:#0B0D11; z-index:50; display:flex; flex-direction:column; color:#E8EAF0; }
.v-top, .v-bottom { display:flex; align-items:center; gap:12px; padding:10px 16px; flex-wrap:wrap; background:#15181E; border-bottom:1px solid #262B35; }
.v-bottom { border-bottom:none; border-top:1px solid #262B35; justify-content:space-between; }
.v-title { flex:1 1 0; min-width:0; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.v-title .hint { color:#8C93A3; font-weight:400; }
.v-modes, .v-actions { display:flex; gap:6px; }
.viewer .btn-secondary { border-color:#3a4150; color:#E8EAF0; } .viewer .btn-secondary:hover:not(:disabled) { background:#262B35; color:#fff; }
.viewer .btn-secondary.on { background:#fff; color:#111; border-color:#fff; }
.viewer .btn-ghost { color:#8C93A3; } .viewer .btn-ghost:hover { color:#fff; }
.v-stage { position:relative; flex:1; display:flex; align-items:stretch; min-height:0; }
.v-nav { width:48px; font-size:34px; color:#8C93A3; border-radius:0; }
.v-nav:hover { color:#fff; background:#15181E; } .v-nav:disabled { opacity:.25; }
.v-scroll { flex:1; overflow:auto; display:flex; align-items:center; justify-content:center; }
.v-scroll.zoomed { display:block; }
.v-stack { position:relative; flex:none; user-select:none; }
.v-stack img { position:absolute; inset:0; width:100%; height:100%; object-fit:fill; display:block; -webkit-user-drag:none; }
.v-stack.compare #vEdit { clip-path:inset(0 0 0 var(--split, 50%)); }
.v-stack.compare .v-handle, .v-stack.compare .v-label { display:block; }
.v-stack.edited #vOrig, .v-stack.blend #vOrig, .v-stack.structure #vOrig { visibility:hidden; } .v-stack.original #vEdit { visibility:hidden; }
.v-handle { display:none; position:absolute; top:0; bottom:0; left:var(--split, 50%); width:2px; background:#fff; cursor:ew-resize; transform:translateX(-1px); box-shadow:0 0 0 1px #0008; }
.v-handle span { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); background:#fff; color:#111; font-size:12px; padding:6px 8px; border-radius:99px; white-space:nowrap; }
.v-label { display:none; position:absolute; bottom:12px; background:#000a; padding:3px 10px; border-radius:6px; font-size:12px; color:#fff; }
.v-label.left { left:12px; } .v-label.right { right:12px; }
.v-strip { display:flex; gap:8px; overflow-x:auto; padding:6px; }
.v-strip .pending { background:var(--track); display:flex; align-items:center; justify-content:center; }

.v-strip .pending { background:#1C2028; display:flex; align-items:center; justify-content:center; }
.v-bottom .hint { color:#8C93A3; }
#vStripShort { display:none; }

/* ---- responsive ---- */
@media (max-width:1100px) {
  .nav { padding-left:14px; }
  .brand img { height:24px; }
  .panel { position:fixed; left:72px; top:56px; bottom:0; z-index:40; width:260px; transform:translateX(calc(-100% - 80px)); transition:transform 240ms var(--ease); box-shadow:var(--sh-lg); }
  .app.panel-open .panel { transform:none; }
  .panel-backdrop { display:block; position:fixed; inset:56px 0 0 0; background:rgba(20,22,28,.25); opacity:0; pointer-events:none; transition:opacity 240ms; z-index:39; }
  .app.panel-open .panel-backdrop { opacity:1; pointer-events:auto; }
  .main { --pad-x:16px; --pad-y:14px; }
  .jobhead { margin:-4px -4px 0; }
}
@media (max-width:700px) {
  .rail { display:none; }
  .nav { padding:0 12px; gap:10px; }
  .nav .menu { display:inline-flex; }
  .crumb, .crumb-name { display:none; }
  .credits .n span:last-child, .credits .n { min-width:0; }
  .panel { left:0; width:min(300px, 86vw); }
  .main { --pad-x:12px; --pad-y:12px; gap:12px; overflow:hidden; }
  .jobhead { gap:8px; padding:0; }
  .jobhead > :first-child { min-width:0; }
  .jobhead h4 { font-size:16px; }
  .jobhead .meta { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:45vw; }
  .jobhead-actions { gap:4px; }
  .presets { flex-wrap:nowrap; overflow-x:auto; padding-bottom:4px; scrollbar-width:none; }
  .presets::-webkit-scrollbar { display:none; }
  .toolbar #prompt { flex:1 1 100%; height:38px; }
  .toolbar #provider { flex:1 1 150px; min-width:0; height:38px; font-size:12px; }
  .strip-card { flex:0 1 auto; }
  .stripbar { padding:0 8px; gap:4px; min-height:38px; }
  .stripbar .btn { padding-inline:4px; }
  .continuity-desktop { display:none; }
  .continuity-mobile { display:inline; }
  .steps { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
  .steps .btn { min-width:0; height:44px; padding-inline:8px; }
  .steps .spacer, .steps .main-done, .steps .add-photos { display:none; }
  .steps #runHero, .steps #propagate { grid-column:1 / -1; }
  .steps #propagate { height:46px; }
  .steps #propagate .apply-price { display:none; }
  .batch-targets { grid-column:1 / -1; grid-row:1; gap:8px; }
  .batch-targets .btn { height:28px; padding:0; }
  .selection-total { display:block; margin-right:auto; }
  .steps:has(#stopQueued:not([hidden])) #propagate { grid-column:1; }
  .steps #stopQueued { grid-column:2; }
  .action-bar { padding-top:10px; }
  .statusrow { gap:4px; min-height:0; }
  .statusrow .st { white-space:normal; }
  .statusrow #spent { display:none; }
  .grid { grid-template-columns:1fr; }
  .gridwrap { overflow:auto; scrollbar-gutter:auto; }
  .empty h2 { font-size:24px; }
  .dropzone { padding:36px 20px; }
  #quoteDialog .dlg { width:94vw; padding:18px; }
  .packs { grid-template-columns:1fr; }
  .qsum .cover { display:none; }
  .v-top, .v-bottom { flex-wrap:wrap; gap:8px; }
  .v-bottom .hint { display:none; }
  .v-bottom #vStripShort { display:block; font-size:11px; flex-shrink:0; max-width:120px; }
  .v-nav { width:36px; }
}

/* ---- motion ---- */
@keyframes bl-spin { to { transform:rotate(360deg); } }
@keyframes bl-shimmer { from { transform:translateX(-100%); } to { transform:translateX(100%); } }
@keyframes bl-reveal { from { opacity:0; transform:scale(1.03); filter:blur(8px); } to { opacity:1; transform:none; filter:blur(0); } }
@keyframes bl-draw { from { stroke-dashoffset:24; } to { stroke-dashoffset:0; } }
@keyframes bl-pop { 0% { transform:scale(.5); opacity:0; } 60% { transform:scale(1.15); opacity:1; } 100% { transform:scale(1); } }
@keyframes bl-unlock { 0% { box-shadow:0 0 0 0 rgba(20,115,230,.7); } 100% { box-shadow:0 0 0 14px transparent; } }
@keyframes bl-fill { from { width:0; } to { width:100%; } }
@keyframes bl-rise { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:none; } }
@keyframes bl-flash { 0% { opacity:0; } 30% { opacity:1; } 100% { opacity:0; } }
@keyframes bl-fade { from { opacity:0; } to { opacity:1; } }
@keyframes bl-fadeout { from { opacity:1; } to { opacity:0; transform:translateY(6px); } }
@keyframes bl-sheet { from { opacity:0; transform:translateY(28px) scale(.98); } to { opacity:1; transform:none; } }
@keyframes bl-shake { 0%,100% { transform:translateX(0); } 20% { transform:translateX(-3px); } 40% { transform:translateX(3px); } 60% { transform:translateX(-3px); } 80% { transform:translateX(3px); } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration:1ms !important; transition-duration:1ms !important; } }

/* ---- full-screen review ---------------------------------------------------------------------------------
   The viewer is #0B0D11 in both themes on purpose, so its own controls carry literal colours rather than the
   theme tokens: in light mode it is the one intentionally dark surface in the product. */
.seg2 { display:flex; gap:2px; padding:2px; border-radius:var(--r-pill); background:#0B0D11; box-shadow:inset 0 0 0 1px #262B35; flex:none; }
.seg2 button { height:28px; padding:0 14px; border-radius:var(--r-pill); font-size:13px; font-weight:600; color:#8C93A3; transition:background 120ms, color 120ms; }
.seg2 button:hover { color:#E8EAF0; }
.seg2 button.on { background:#E8EAF0; color:#111; }
.v-blend { display:flex; align-items:center; gap:8px; color:#8C93A3; font-size:12px; flex:none; }
.v-blend input { width:110px; accent-color:var(--accent); }
.v-blend .pct { width:34px; color:#E8EAF0; font-size:11px; }
.vb.ic { width:22px; height:22px; display:inline-flex; align-items:center; justify-content:center; border-radius:50%; color:#8C93A3; font-size:12px; font-weight:600; box-shadow:inset 0 0 0 1px #3A4150; }
.vb.ic:hover { color:#fff; background:#262B35; }
/* The verdict sits on the photograph, and it is a button: this is the one place a photographer meets the
   structure check, so it is the one place that has to be able to explain itself. */
.sbadge { position:absolute; top:14px; left:62px; z-index:3; display:inline-flex; align-items:center; gap:6px; height:26px; padding:0 11px;
  border-radius:var(--r-pill); font-size:11.5px; font-weight:600; background:var(--sb-bg); color:var(--sb-fg); backdrop-filter:blur(6px); }
.sbadge::after { content:"?"; display:inline-flex; align-items:center; justify-content:center; width:15px; height:15px; border-radius:50%; font-size:10px; box-shadow:inset 0 0 0 1px currentColor; opacity:.75; }
.sbadge:hover { filter:brightness(1.15); }
.sbadge.kept { --sb-bg:rgba(30,122,60,.28); --sb-fg:#7BD99B; }
.sbadge.unsure { --sb-bg:rgba(255,255,255,.16); --sb-fg:#E8EAF0; }
.sbadge.changed { --sb-bg:rgba(215,0,21,.28); --sb-fg:#FF8A93; }
.v-striprow { display:flex; align-items:center; gap:12px; min-width:0; }
@media (max-width:900px) {
  .v-top, .v-bottom { flex-wrap:wrap; gap:8px; padding:8px 10px; }
  .v-blend { display:none; }
  .v-nav { width:36px; }
}

/* ---- in-app help panel ----------------------------------------------------------------------------------
   Slides in over a light scrim with the app still visible behind it: the point is to answer a question about
   what is on screen, not to replace the screen. */
.h-scrim { position:fixed; inset:0; background:rgba(0,0,0,.18); z-index:60; animation:bl-fade 200ms var(--ease) both; }
.h-panel { position:fixed; top:0; right:0; bottom:0; width:min(420px, 92%); z-index:61; background:var(--card); display:flex; flex-direction:column;
  box-shadow:var(--sh-lg); transform:translateX(24px); opacity:0; transition:transform 280ms var(--ease), opacity 280ms var(--ease); }
.h-panel.in { transform:none; opacity:1; }
.h-head { display:flex; align-items:center; justify-content:space-between; padding:14px 12px 14px 18px; box-shadow:inset 0 -1px 0 var(--divider); flex:none; }
.h-head b { font-size:15px; }
.h-body { flex:1; overflow:auto; padding:16px 18px; display:flex; flex-direction:column; gap:20px; }
.h-body h6 { margin:0 0 6px; font-size:11px; letter-spacing:.08em; text-transform:uppercase; color:var(--muted); font-weight:600; }
.h-lead { background:var(--accent-tint); border-radius:var(--r-md); padding:14px; display:flex; flex-direction:column; gap:6px; animation:bl-rise 320ms var(--ease) both; }
.h-lead .eyebrow { font-size:11px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:var(--accent); }
.h-lead .q { font-weight:700; font-size:15px; text-wrap:pretty; }
.h-lead p { margin:0; font-size:13px; color:var(--text2); text-wrap:pretty; }
.h-lead p b { color:var(--text); }
.h-item { display:flex; gap:9px; padding:9px 0; box-shadow:inset 0 -1px 0 var(--divider); }
.h-item:last-child { box-shadow:none; }
.h-item .dot { width:7px; height:7px; border-radius:50%; margin-top:6px; flex:none; }
.h-item .dot.b { background:var(--accent); } .h-item .dot.r { background:var(--danger); } .h-item .dot.g { background:var(--muted); }
.h-item b { display:block; font-size:13px; font-weight:600; }
.h-item span { display:block; font-size:12.5px; color:var(--muted); margin-top:1px; }
.h-foot { flex:none; padding:12px 18px; display:flex; gap:16px; box-shadow:inset 0 1px 0 var(--divider); font-size:12.5px; }
.h-foot a { color:var(--accent); }
@media (max-width:900px) { .h-panel { width:100%; } }

/* ---- settings and presets panes -------------------------------------------------------------------------
   Two rail destinations, not a modal. Settings used to be one dense form behind a Save button; the design
   makes it a pane of section cards where each control saves itself, because a segmented control with a Save
   button underneath it is asking the same question twice. Values come from the light-theme handoff's
   Settings.dc.html (board in git history before commit 34abad1; spec in design/archive), retokenised onto this stylesheet's own names. */
.pane { flex:1; min-width:0; overflow:auto; margin:0 calc(-1 * var(--pad-x)) calc(-1 * var(--pad-y)); padding:8px var(--pad-x) 44px; }
/* Centered in whatever width the pane has (a wide monitor used to leave the whole right half empty), capped so
   lines stay readable. */
.pane-wrap { width:100%; max-width:820px; margin:0 auto; display:flex; flex-direction:column; gap:14px; animation:bl-rise 320ms var(--ease) both; }
.pane-head { display:flex; align-items:flex-end; gap:12px; }
.pane-head h4 { font-size:18px; }
.s-sec { border-radius:var(--r-card); background:var(--surface); padding:20px 22px; display:flex; flex-direction:column; gap:14px; }
.s-sec > .s-head h5 { font-size:16px; }
.s-sub { margin:2px 0 0; font-size:13px; color:var(--muted); text-wrap:pretty; }
.s-row { display:flex; align-items:flex-start; gap:16px; }
.s-row .lab { flex:1; min-width:0; }
.s-lab { font-weight:500; }
.s-note { margin:0; font-size:12px; color:var(--muted); text-wrap:pretty; }
.s-note.warn { color:var(--warn-fg); }

/* Segmented control. The panel's .pills stretches its buttons to fill; this one hugs its content, because it
   sits at the right of a label row where the label owns the slack. */
.seg { display:flex; padding:2px; border-radius:var(--r-pill); background:var(--track); flex:none; }
.seg button { white-space:nowrap; height:28px; padding:0 13px; border-radius:var(--r-pill); font-size:12px; font-weight:600; color:var(--muted); transition:background 120ms, color 120ms; }
.seg button:hover:not(.on) { color:var(--text); }
.seg button.on { background:var(--card); color:var(--text); box-shadow:var(--sh-sm); }

/* Radio card: the option and its consequence in one target. */
.opt { text-align:left; width:100%; display:flex; gap:11px; align-items:flex-start; padding:11px 13px; border-radius:12px; background:var(--card); box-shadow:0 0 0 1px var(--divider); transition:box-shadow 160ms; }
.opt:hover { box-shadow:0 0 0 1px var(--border); }
.opt.on { box-shadow:0 0 0 2px var(--accent); }
.opt .dot { width:16px; height:16px; border-radius:50%; flex:none; margin-top:2px; box-shadow:inset 0 0 0 1.5px var(--faint); transition:box-shadow 160ms; }
.opt.on .dot { box-shadow:inset 0 0 0 5px var(--accent); }
.opt .n { display:block; font-weight:500; }
.opt .d { display:block; font-size:13px; color:var(--muted); text-wrap:pretty; }

.prop { display:inline-block; margin-left:8px; padding:1px 7px; border-radius:var(--r-pill); font-size:10px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); box-shadow:inset 0 0 0 1px var(--border); vertical-align:2px; }

/* Rows inside a section sit on --card: the section itself is already --surface. */
.s-sec .exrow { background:var(--card); padding:10px 13px; border-radius:12px; gap:12px; }
.s-sec .exrow .ic { width:30px; height:30px; border-radius:50%; background:var(--track); color:var(--text2); display:flex; align-items:center; justify-content:center; flex:none; }
.s-sec .exrow .who { flex:1; min-width:0; }
.s-sec .exrow .who .n { display:block; font-weight:500; }
.s-sec .exrow .who .m { display:block; font-size:12px; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.s-sec .exrow .acts { display:flex; gap:2px; flex:none; }
.s-sec .keys { gap:7px 18px; }
.s-sec .input { width:100%; }
.s-sec .two { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.s-sec label.f { display:block; font-size:12px; color:var(--muted); font-weight:500; }
.s-sec label.f .input { display:block; margin-top:4px; color:var(--text); font-weight:400; }

@media (max-width:900px) {
  .pane { padding-bottom:28px; }
  .s-row { flex-direction:column; gap:10px; }
  .s-sec .keys { grid-template-columns:1fr; }
  .s-sec .two { grid-template-columns:1fr; }
  .s-sec .exrow { flex-wrap:wrap; }
}
.opts { display:flex; flex-direction:column; gap:8px; }
#setDelivery, #setNotify { display:flex; flex-direction:column; gap:14px; }
/* A key cap is a --card chip on a --surface section. Bound to --surface it was the same colour as the card
   it sat on and vanished. */
.s-sec kbd { background:var(--card); }
#presetGroups { display:flex; flex-direction:column; gap:14px; }

/* ---- credits pane ---------------------------------------------------------------------------------------
   The balance, what it buys, and where it went. Values from the light-theme handoff's Credits.dc.html (git history; spec in design/archive). */
.pane-wrap.wide { max-width:960px; gap:26px; }
.c-card { border-radius:var(--r-card); background:var(--surface); padding:22px 24px; }
.c-hero { display:flex; align-items:center; gap:24px; }
.c-hero .who { flex:1; min-width:0; }
.c-lab { font-size:12px; color:var(--muted); font-weight:500; }
.c-big { font-size:44px; font-weight:700; letter-spacing:-.03em; line-height:1.1; margin-top:2px; }
.c-heroact { display:flex; flex-direction:column; gap:10px; align-items:flex-end; flex:none; }
.c-head { display:flex; align-items:baseline; gap:10px; margin-bottom:12px; }
.c-head h4 { font-size:18px; white-space:nowrap; }
.c-packs { display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:12px; }
.c-pack { position:relative; text-align:left; padding:16px; border-radius:12px; background:var(--card); display:flex; flex-direction:column; gap:3px;
  box-shadow:0 0 0 1px var(--divider); transition:box-shadow 200ms var(--ease), transform 200ms var(--ease); }
.c-pack:hover { box-shadow:0 0 0 1px var(--border); }
.c-pack.on { box-shadow:0 0 0 2px var(--accent); transform:scale(1.02); }
.c-pack .k { font-size:22px; font-weight:700; letter-spacing:-.02em; }
.c-pack .b { font-size:12px; color:var(--accent); font-weight:600; min-height:16px; }
.c-pack .f { margin-top:8px; font-size:12px; color:var(--muted); }
.c-pack .chk { position:absolute; top:12px; right:12px; width:18px; height:18px; border-radius:50%; background:var(--accent); display:flex; align-items:center; justify-content:center; }
.c-pay { padding:16px 18px; display:flex; align-items:center; gap:12px; }
.c-pay .who { flex:1; min-width:0; }
/* The ledger is tabular data, so it is a table — which also brings the design system's own row treatment:
   rules that fade out at both ends, and a hover tint that layers over the rule rather than replacing it
   (the handoff's _ds/nocturne-*/styles.css, now in design/handoff/_ds/). The artboard drew bare divs with a hard rule and no
   hover; the shared component layer is the one to follow. */
.two { display:grid; grid-template-columns:1fr 1fr; gap:48px; align-items:center; }
.two h2 { margin-bottom:10px; } .two .lead { color:var(--text2); max-width:460px; }
.block { border-radius:var(--r-card); background:var(--surface); padding:12px 12px 8px; }
table.table { width:100%; border-collapse:collapse; font-size:14px; }
.table th { text-align:left; font-size:11px; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); font-weight:600; padding:10px 12px; border-bottom:1px solid transparent; }
.table td { padding:12px; border-bottom:1px solid transparent; }   /* keeps the layout; the row paints the rule */
.ledger-foot { display:flex; align-items:center; gap:10px; padding:12px 12px 4px; }
.ledger-foot .hint { margin-right:auto; }
/* Rules are drawn on the row, not the cells, so they can fade out over 48px at each end instead of stopping
   dead at the table edge. A per-cell border cannot fade across a row. The hover tint is layered on top of the
   same gradient, so the rule keeps painting underneath it. */
.table thead tr { background:linear-gradient(to right, transparent, var(--divider) 48px, var(--divider) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px; }
.table tbody tr { background:linear-gradient(to right, transparent, color-mix(in srgb, var(--text) 8%, transparent) 48px, color-mix(in srgb, var(--text) 8%, transparent) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px; transition:background-color 120ms; }
.table tbody tr:last-child { background-image:none; }
.table tbody tr:hover {
  background:
    linear-gradient(color-mix(in srgb, var(--text) 4%, transparent), color-mix(in srgb, var(--text) 4%, transparent)) no-repeat 0 0 / 100% 100%,
    linear-gradient(to right, transparent, color-mix(in srgb, var(--text) 8%, transparent) 48px, color-mix(in srgb, var(--text) 8%, transparent) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px;
}
.table tbody tr:last-child:hover { background:linear-gradient(color-mix(in srgb, var(--text) 4%, transparent), color-mix(in srgb, var(--text) 4%, transparent)) no-repeat 0 0 / 100% 100%; }
.table td.r, .table th.r { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }   /* a price or its heading never wraps */
.table td.m { color:var(--muted); }
.block .note { padding:10px 6px 6px; font-size:12px; color:var(--muted); }
.table { width:100%; border-collapse:collapse; font-size:13px; }
.table td.when { width:132px; color:var(--muted); font-variant-numeric:tabular-nums; white-space:nowrap; }
.table td.what { max-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.table td.what .where { color:var(--muted); }
.table td.amt { font-weight:600; }
/* Green is "money came back" — a refund or a load. A settle adjustment moves either way and is a price
   correction, not a refund, so it stays muted whichever way it goes; the table exists to answer "did I get my
   money back?" and an adjustment is not that answer. */
.table td.amt.back { color:var(--ok-fg); }
.table td.amt.spent, .table td.amt.adjust { color:var(--muted); }
#credMin { margin:10px 2px 0; }
@media (max-width:900px) {
  .c-packs { grid-template-columns:1fr; }
  .c-head { flex-wrap:wrap; gap:2px 10px; }
  .c-hero { flex-direction:column; align-items:flex-start; gap:16px; }
  .c-heroact { align-items:flex-start; }
  .c-row { flex-wrap:wrap; gap:6px 12px; }
  .c-row .when, .c-row .after { width:auto; }
}
/* A preset carries its own model, so clicking one can change the model under the run button. Ring the picker
   when that happens rather than letting it change in silence. */
#provider.changed { animation:bl-pick 1100ms var(--ease) both; }
@keyframes bl-pick { 0%, 55% { box-shadow:0 0 0 2px var(--accent); } 100% { box-shadow:0 0 0 0 transparent; } }

/* Native selection remains keyboard operable after each poll. */
.batch-check { width:16px; height:16px; margin:0; accent-color:var(--accent); flex:none; cursor:pointer; }
.batch-check:disabled { cursor:default; }
.batch-check:focus-visible { outline-offset:2px; }
.system-notice { display:flex; flex-wrap:wrap; align-items:center; gap:8px; padding:10px 20px; border-bottom:1px solid var(--divider); background:var(--surface); font-size:12px; }
.diagnostics-wrap { padding:24px; display:grid; gap:16px; }
#diagnosticsDialog { width:min(660px, calc(100vw - 32px)); max-height:85vh; overflow:auto; background:var(--card); border:1px solid var(--border); border-radius:12px; }
.health-event { display:grid; gap:4px; padding:12px 0; border-bottom:1px solid var(--divider); font-size:13px; overflow-wrap:anywhere; }

.diagnostics-wrap > .s-row { display:flex; align-items:center; justify-content:space-between; gap:16px; }
.diagnostics-wrap > .s-row h3, .diagnostics-wrap > p { margin:0; }

/* ---- account sign-in ------------------------------------------------------------------------------------
   From the Claude Design "Sign in" board (2026-09-13): one 420px card on the page background, the lock-up once at
   the top, labels above 44px fields, one primary, a text link beneath. Banners for account-level messages,
   inline text for field-level ones. Existing tokens; the card is full width minus 16px on phones. */
dialog.auth { border:0; padding:0; background:transparent; max-width:none; width:100%; height:100%; max-height:none; }
dialog.auth[open] { display:flex; align-items:flex-start; justify-content:center; padding-top:clamp(24px, 10vh, 96px); box-sizing:border-box; }
dialog.auth::backdrop { background:var(--bg); }
.auth-card { width:min(420px, calc(100vw - 32px)); display:flex; flex-direction:column; gap:20px; color:var(--text); }
.auth-logo { display:block; height:36px; width:auto; margin:0 auto; }
.auth-view { display:flex; flex-direction:column; gap:14px; }
.auth-title { margin:0; text-align:center; font-size:22px; font-weight:600; letter-spacing:-.01em; }
.auth-sub { margin:-8px 0 0; text-align:center; color:var(--muted); font-size:14px; line-height:1.45; }
.auth-field { display:flex; flex-direction:column; gap:6px; font-size:13px; color:var(--text2); }
.auth-field > span:first-child { font-weight:500; }
.auth-field .input { height:44px; width:100%; box-sizing:border-box; font-size:14px; }
.auth-field .input.invalid { border-color:var(--danger); box-shadow:0 0 0 1px var(--danger); }
.auth-locked { position:relative; display:block; }
.auth-locked .input { background:var(--surface); color:var(--text2); padding-right:36px; }
.auth-locked svg { position:absolute; right:12px; top:50%; transform:translateY(-50%); color:var(--muted); pointer-events:none; }
.auth-inline { font-size:12px; line-height:1.4; }
.auth-inline.muted { color:var(--muted); }
.auth-inline.danger { color:var(--danger); }
.auth-textlink { background:none; border:0; padding:0; font:inherit; color:var(--accent); cursor:pointer; text-decoration:underline; text-underline-offset:2px; }
.auth-banner { display:flex; gap:10px; align-items:flex-start; padding:10px 12px; border-radius:var(--r-md); font-size:13px; line-height:1.4; }
.auth-banner svg { flex:none; margin-top:1px; }
.auth-banner.danger { background:var(--danger-bg); color:var(--danger); }
.auth-banner.info { background:var(--accent-tint); color:var(--accent-press); }
.auth-primary { width:100%; margin-top:4px; font-size:15px; }
.auth-link { align-self:center; background:none; border:0; padding:6px 8px; font:inherit; font-size:13px; color:var(--accent); cursor:pointer; border-radius:var(--r-chip); }
.auth-link:hover { text-decoration:underline; text-underline-offset:2px; }
.auth-link:focus-visible, .auth-textlink:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }

/* Rail account item (bottom of the rail) and its popover: initials, then name, email and Sign out. */
.rail-initials { display:inline-flex; align-items:center; justify-content:center; width:24px; height:24px; border-radius:50%; background:var(--accent-tint); color:var(--accent); font-size:11px; font-weight:600; letter-spacing:.02em; }
.account-pop { position:fixed; left:76px; bottom:16px; z-index:30; min-width:220px; padding:12px 14px; border-radius:var(--r-card); background:var(--card); box-shadow:var(--sh-md); display:flex; flex-direction:column; gap:4px; }
.account-pop-name { font-weight:600; font-size:14px; }
.account-pop-email { color:var(--muted); font-size:13px; margin-bottom:8px; word-break:break-all; }
@media (max-width:760px) { .account-pop { left:12px; right:12px; bottom:76px; } }
