/* ============================================================================
   Verquil app — Spectra components (frontend baton).
   Authority = DESIGN.md + design/spectra/app.html (visual truth source).
   Tokens only — no bare hex/px for spacing (optical ≤2px annotated). Component
   font sizes ≤ --fs-sm follow the mock's dense-data scale (mock is authority).
   ============================================================================ */

body{font-size:var(--fs-sm)}

/* ---- app shell: sidebar + main ------------------------------------------- */
.app{display:grid;grid-template-columns:238px 1fr;min-height:100vh}

/* sidebar */
.side{background:var(--surface);border-right:1px solid var(--hairline);padding:var(--s5) var(--s4);display:flex;flex-direction:column}
.side .brand{display:flex;align-items:center;gap:9px; /* optical */ padding:6px 8px var(--s6)}
.side .brand svg{width:26px;height:24px;color:var(--accent)}
.side .brand .wm{font-family:var(--f-display);font-weight:600;font-size:19px;letter-spacing:-.015em;color:var(--ink)}
.navg{display:flex;flex-direction:column;gap:2px /* optical */}
.navg a{display:flex;align-items:center;gap:var(--s3);padding:9px 11px; /* optical */ border-radius:9px;color:var(--ink-2);font-weight:500}
.navg a svg{width:18px;height:18px;flex:none;color:var(--ink-muted)}
.navg a:hover{background:var(--surface-2);color:var(--ink)}
.navg a.on{background:var(--surface-3);color:var(--ink)}
.navg a.on svg{color:var(--accent)}
.side .sep{height:1px;background:var(--hairline);margin:var(--s5) 6px /* optical */}
.credits{margin-top:auto;background:var(--surface-2);border:1px solid var(--hairline);border-radius:var(--r-md);padding:var(--s4)}
.credits .lab{font-family:var(--f-mono);font-size:11px;color:var(--ink-faint);letter-spacing:.06em}
.credits .n{font-family:var(--f-display);font-weight:700;font-size:26px;font-variant-numeric:tabular-nums;margin:var(--s1) 0 2px /* optical */}
.credits .sm{font-family:var(--f-mono);font-size:11px;color:var(--ink-faint)}
.side form.signout{margin-top:var(--s4)}
.signout button{display:flex;align-items:center;gap:var(--s3);width:100%;padding:9px 11px; /* optical */ border-radius:9px;color:var(--ink-muted);font-weight:500}
.signout button svg{width:18px;height:18px;flex:none}
.signout button:hover{background:var(--surface-2);color:var(--ink)}

/* main column + topbar */
.main{display:flex;flex-direction:column;min-width:0}
.topbar{display:flex;align-items:center;gap:var(--s4);padding:0 var(--s6);height:60px;border-bottom:1px solid var(--hairline)}
.crumb{font-family:var(--f-mono);font-size:var(--fs-meta);color:var(--ink-faint)}
.crumb b{color:var(--ink);font-weight:500}
.topbar .acct{margin-left:auto;display:flex;align-items:center;gap:var(--s4)}
.status{display:inline-flex;align-items:center;gap:7px; /* optical */ font-family:var(--f-mono);font-size:12px}
.status .d{width:7px;height:7px;border-radius:50%;background:currentColor}
.status.done{color:var(--ok)}
.status.done .d{box-shadow:0 0 0 3px var(--accent-soft)}
.status.run{color:var(--info)}
.status.run .d{animation:pulse var(--dur-slow) var(--ease-inout) infinite alternate}
.status.fail{color:var(--danger)}
.status.wait{color:var(--ink-faint)}
@keyframes pulse{from{opacity:1}to{opacity:.35}}
.avatar{width:30px;height:30px;border-radius:50%;background:var(--surface-3);color:var(--accent);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:12px;border:1px solid var(--hairline-2)}

.editor{padding:var(--s6);overflow:auto;min-width:0;flex:1;width:100%;max-width:960px}
.editor > h1{font-family:var(--f-display);font-weight:700;font-size:22px;letter-spacing:-.01em;margin-bottom:var(--s5)}

/* flash messages */
.flash{display:flex;flex-direction:column;gap:var(--s2);margin-bottom:var(--s5)}
.flash p{border:1px solid var(--hairline-2);border-left:2px solid var(--accent);border-radius:var(--r-sm);background:var(--surface);padding:var(--s3) var(--s4);color:var(--ink-2)}
.flash p.error{border-left-color:var(--danger);color:var(--danger)}

/* ---- upload dropzone (DESIGN §4 / §6.2) ---------------------------------- */
.dropzone{border:1.5px dashed var(--control-border);border-radius:var(--r-md);background:var(--surface);padding:var(--s6) var(--s5);text-align:center;margin-bottom:var(--s6);transition:border-color var(--dur-fast) var(--ease-out),background-color var(--dur-fast) var(--ease-out)}
.dropzone.drag{border-color:var(--accent);background:var(--surface-2)}
.dropzone svg{width:26px;height:24px;margin:0 auto var(--s3);color:var(--ink-muted)}
.dropzone.drag svg{color:var(--accent)}
.dropzone .hd{font-weight:600;font-size:15px;color:var(--ink)}
.dropzone .sub{font-family:var(--f-mono);font-size:var(--fs-meta);color:var(--ink-faint);margin-top:var(--s2)}
.dropzone .pick{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--s3);margin-top:var(--s4)}
.dropzone .picked{font-family:var(--f-mono);font-size:var(--fs-meta);color:var(--ink-2)}
/* native input visible by default (progressive enhancement); JS swaps in the button */
.dropzone input[type=file]{color:var(--ink-2);font-size:var(--fs-sm);max-width:100%}
.js .dropzone input[type=file]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* buttons */
.btn-pri,.btn-ghost{display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);border-radius:var(--r-sm);padding:var(--s2) var(--s4);font-weight:500;font-size:var(--fs-sm);min-height:36px; /* optical: ≥24px control, dense UI */ transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),transform var(--dur-fast) var(--ease-out)}
.btn-pri{background:var(--accent);color:var(--on-accent);border:1px solid var(--accent);font-weight:600}
.btn-pri:hover{background:#4fe8cb;transform:translateY(-1px)} /* hover mint 一階亮，DESIGN §4 */
.btn-pri:disabled{opacity:.5;cursor:not-allowed;pointer-events:none}
.btn-ghost{background:none;color:var(--ink);border:1px solid var(--control-border)}
.btn-ghost:hover{border-color:var(--accent)}
.btn-pri svg,.btn-ghost svg{width:15px;height:15px;flex:none}

/* ---- batch list (dashboard) ---------------------------------------------- */
.batch{margin-bottom:var(--s6)}
.batch-hd{display:flex;align-items:baseline;gap:var(--s3);margin-bottom:var(--s3)}
.batch-hd h2{font-family:var(--f-mono);font-size:11px;font-weight:400;letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-faint)}
.batch-hd time{font-family:var(--f-mono);font-size:11px;color:var(--ink-faint)}
.joblist{list-style:none;margin:0;padding:0;border:1px solid var(--hairline);border-radius:var(--r-md);background:var(--surface);overflow:hidden}
.jrow{display:flex;align-items:center;gap:var(--s4);padding:var(--s3) var(--s4);border-bottom:1px solid var(--hairline)}
.jrow:last-child{border-bottom:0}
.jrow:hover{background:var(--surface-2)}
.jrow .nm{flex:1;min-width:0;font-weight:500;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.jrow .nm:hover{color:var(--accent)}
.jrow .cr{font-family:var(--f-mono);font-size:var(--fs-meta);color:var(--ink-faint);font-variant-numeric:tabular-nums;text-align:right;min-width:0}
.jrow .why{flex-basis:100%;font-size:var(--fs-meta);color:var(--danger);font-family:var(--f-mono)}
.jrow.has-why{flex-wrap:wrap}
.qs{font-family:var(--f-mono);font-size:10.5px;padding:2px 7px; /* optical */ border-radius:var(--r-xs);flex:none;white-space:nowrap}
.qs.done{color:var(--ok);border:1px solid var(--accent-line)}
.qs.run{color:var(--info);border:1px solid var(--info-line)}
.qs.wait{color:var(--ink-faint);border:1px solid var(--hairline-2)}
.qs.fail{color:var(--danger);border:1px solid var(--danger-line)}
.poll-note{font-family:var(--f-mono);font-size:11px;color:var(--ink-faint);margin-bottom:var(--s4)}

/* empty state — invitation to act */
.empty{border:1px solid var(--hairline);border-radius:var(--r-md);background:var(--surface);padding:var(--s6);text-align:center;color:var(--ink-muted)}
.empty .hd{font-weight:600;color:var(--ink-2);margin-bottom:var(--s2)}

/* ---- job detail ----------------------------------------------------------- */
.jobhd{display:flex;align-items:flex-start;gap:var(--s5);margin-bottom:var(--s5)}
.jobhd h1{font-family:var(--f-display);font-weight:700;font-size:22px;letter-spacing:-.01em;overflow-wrap:anywhere}
.jobhd .meta{display:flex;gap:14px; /* optical */ margin-top:9px; /* optical */ flex-wrap:wrap;font-family:var(--f-mono);font-size:12px;color:var(--ink-faint)}
.jobhd .meta b{color:var(--ink-muted);font-weight:400}
.jobhd .actions{margin-left:auto;display:flex;gap:var(--s2)}
.pill{display:inline-flex;align-items:center;gap:7px; /* optical */ border:1px solid var(--control-border);border-radius:var(--r-sm);padding:var(--s2) 14px; /* optical */ font-weight:500;font-size:13px;color:var(--ink)}
.pill svg{width:15px;height:15px;flex:none}
.pill:hover{border-color:var(--accent)}

/* processing / failed panels */
.state-panel{border:1px solid var(--hairline);border-radius:var(--r-md);background:var(--surface);padding:var(--s6);text-align:center}
.state-panel .st{display:inline-flex;align-items:center;gap:var(--s2);font-family:var(--f-mono);font-size:13px}
.state-panel .st .d{width:8px;height:8px;border-radius:50%;background:currentColor}
.state-panel.run .st{color:var(--info)}
.state-panel.run .st .d{animation:pulse var(--dur-slow) var(--ease-inout) infinite alternate}
.state-panel.fail{border-color:var(--danger-line)}
.state-panel.fail .st{color:var(--danger)}
.state-panel p{margin-top:var(--s3);color:var(--ink-muted);font-size:var(--fs-sm)}
.state-panel .why{color:var(--danger);font-family:var(--f-mono);font-size:var(--fs-meta)}

/* transcript rows — mirrors design/spectra/app.html .row */
.tlist{display:flex;flex-direction:column;border-top:1px solid var(--hairline)}
.trow{display:grid;grid-template-columns:56px 34px 1fr;gap:var(--s4);padding:13px var(--s4); /* optical 13px */ align-items:baseline;border-bottom:1px solid var(--hairline);border-left:2px solid transparent}
.trow:hover{background:var(--surface)}
.trow .tc{font-family:var(--f-mono);font-size:var(--fs-meta);color:var(--ink-faint);font-variant-numeric:tabular-nums}
.trow .sn{font-family:var(--f-mono);font-size:11px;font-weight:600;text-align:center;border-radius:var(--r-xs);padding:2px 0; /* optical */ border:1px solid}
.trow.s1 .sn{color:var(--spk-1);border-color:var(--accent-line)}
.trow.s2 .sn{color:var(--spk-2);border-color:rgba(143,185,180,.36)}
.trow.s3 .sn{color:var(--spk-3);border-color:rgba(167,174,178,.32)}
.trow.s4 .sn{color:var(--spk-4);border-color:rgba(125,134,139,.34)}
.trow .say{font-size:14.5px;line-height:1.55;color:var(--ink);overflow-wrap:anywhere}

/* ---- glossary -------------------------------------------------------------- */
.term-form{display:flex;gap:var(--s3);margin-bottom:var(--s5);max-width:480px}
.term-form .field{flex:1}
.input{width:100%;background:var(--surface);border:1px solid var(--hairline-2);border-radius:var(--r-sm);padding:var(--s2) var(--s3);color:var(--ink);min-height:36px}
.input::placeholder{color:var(--ink-faint)}
.input:hover,.input:focus{border-color:var(--accent)}
.termlist{list-style:none;margin:0;padding:0;border:1px solid var(--hairline);border-radius:var(--r-md);background:var(--surface);overflow:hidden;max-width:480px}
.termlist li{display:flex;align-items:center;gap:var(--s4);padding:var(--s2) var(--s4);border-bottom:1px solid var(--hairline)}
.termlist li:last-child{border-bottom:0}
.termlist .t{flex:1;min-width:0;overflow-wrap:anywhere}
.termlist button{color:var(--ink-muted);font-size:var(--fs-meta);font-family:var(--f-mono);border:1px solid transparent;border-radius:var(--r-xs);padding:2px 7px /* optical */}
.termlist button:hover{color:var(--danger);border-color:var(--danger-line)}
.hint{color:var(--ink-muted);font-size:var(--fs-sm);margin-bottom:var(--s5);max-width:36em}

/* ---- auth gate (login / signup / verify) ---------------------------------- */
.gate{min-height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--s6) var(--s4);background:
  radial-gradient(52% 40% at 50% 12%,var(--accent-soft),transparent 70%),var(--bg)}
.gate .brand{display:flex;align-items:center;gap:9px; /* optical */ margin-bottom:var(--s6)}
.gate .brand svg{width:30px;height:28px;color:var(--accent)}
.gate .brand .wm{font-family:var(--f-display);font-weight:600;font-size:22px;letter-spacing:-.015em}
.card{width:100%;max-width:400px;background:var(--surface);border:1px solid var(--hairline-2);border-radius:var(--r-lg);padding:var(--s6);box-shadow:var(--shadow-float)}
.card h1{font-family:var(--f-display);font-weight:700;font-size:22px;letter-spacing:-.01em;margin-bottom:var(--s5)}
.card .fld{margin-bottom:var(--s4)}
.card .fld input{width:100%;background:var(--surface-2);border:1px solid var(--hairline-2);border-radius:var(--r-sm);padding:var(--s2) var(--s3);color:var(--ink);min-height:40px}
.card .fld input:hover,.card .fld input:focus{border-color:var(--accent)}
.card .fld.has-err input{border-color:var(--danger)}
.card label{display:block;font-family:var(--f-mono);font-size:11px;letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-muted);margin-bottom:var(--s2)}
.card .help{font-size:var(--fs-meta);color:var(--ink-muted);margin-top:var(--s2)}
.card .err{font-size:var(--fs-meta);color:var(--danger);margin-top:var(--s2)}
.card .fld.has-err .input{border-color:var(--danger)}
.card .form-err{border:1px solid var(--danger-line);border-radius:var(--r-sm);color:var(--danger);font-size:var(--fs-sm);padding:var(--s3);margin-bottom:var(--s4)}
.card .btn-pri{width:100%;margin-top:var(--s2)}
.gate .alt{margin-top:var(--s5);color:var(--ink-muted);font-size:var(--fs-sm)}
.gate .alt a{color:var(--accent)}
.gate .alt a:hover{text-decoration:underline}
.card p.lead{color:var(--ink-2);line-height:var(--lh-body)}
.card p.lead b{color:var(--ink);font-weight:600}

/* skip link */
.skip{position:absolute;left:var(--s4);top:-100vh;background:var(--accent);color:var(--on-accent);padding:var(--s2) var(--s4);border-radius:var(--r-sm);z-index:10;font-weight:600}
.skip:focus{top:var(--s4)}

/* ---- mobile nav strip (≤820 sidebar collapses; keeps nav/signout reachable) - */
.mnav{display:none}
@media (max-width:820px){
  .mnav{display:flex;align-items:center;gap:var(--s2);padding:var(--s2) var(--s5);border-bottom:1px solid var(--hairline);overflow-x:auto}
  .mnav a{font-family:var(--f-mono);font-size:12px;color:var(--ink-2);padding:var(--s1) var(--s3);border:1px solid var(--hairline-2);border-radius:var(--r-pill);white-space:nowrap}
  .mnav a.on{color:var(--accent);border-color:var(--accent-line)}
  .mnav .bal{margin-left:auto;font-family:var(--f-mono);font-size:12px;color:var(--ink-faint);font-variant-numeric:tabular-nums;white-space:nowrap}
  .mnav form{display:contents}
  .mnav button{font-family:var(--f-mono);font-size:12px;color:var(--ink-muted);padding:var(--s1) var(--s3);border:1px solid var(--hairline-2);border-radius:var(--r-pill);white-space:nowrap}
}

/* ---- RWD (mock breakpoints) ------------------------------------------------ */
@media (max-width:820px){ .app{grid-template-columns:1fr} .side{display:none} }
@media (max-width:640px){
  .jobhd{flex-direction:column;gap:var(--s4)}
  .jobhd .actions{margin-left:0;flex-wrap:wrap}
  .editor{padding:var(--s5)}
}
@media (max-width:520px){
  .topbar{padding:0 var(--s5);gap:var(--s3)}
  .crumb .pre{display:none}
  .crumb{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
  .topbar .acct{gap:var(--s3)}
  /* keep left padding: accent bar / timecode / text stay separated (mock rule) */
  .trow{grid-template-columns:46px 28px 1fr;gap:14px;padding:14px var(--s1) 14px var(--s4)} /* optical 14px */
  .term-form{flex-direction:column}
}
