tts-voice-creator-clone-and.../static/style.css
mARTin-B78 55f634e626 Show quotation marks in the casting script, with a toggle (v1.20.29)
German prose never quotes narration, so displaying the guillemets makes a
mislabeled line obvious at a glance. Extraction strips them from ~80% of
segments, so they are rendered rather than stored: dialogue rows display
wrapped in » «, lines that kept their own marks are left as-is, and the saved
text is untouched so synthesis and exports are unaffected. A toolbar button
toggles visibility and the choice persists.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 10:51:46 +02:00

7325 lines
416 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ── [hidden] must always hide ────────────────────────────────────────────────
Any component that sets `display:flex/grid/block` on its base selector beats
the UA's `[hidden]{display:none}` at equal specificity, making the element
render as an empty box while "hidden". This bit .ab-char-bar, .wf-stepper,
.reader-extract-banner, .ab-castpanel-inline and ~20 others individually —
one root rule ends the whole bug class. */
[hidden] { display: none !important; }
/* ── MDI icon integration ────────────────────────────────────────────────── */
.mdi {
vertical-align: -0.125em;
line-height: 1;
display: inline-block;
}
button .mdi, a .mdi { font-size: 22px; }
.nav-icon .mdi { font-size: 22px; line-height: 1; }
.section-icon .mdi { font-size: 22px; line-height: 1; }
.llm-card-icon .mdi { font-size: inherit; }
.llm-local-icon.mdi { font-size: 22px; }
.backend-metric-tag .mdi, .llm-metric-chip .mdi, .dc-metric-chip .mdi { font-size: 11px; vertical-align: -0.05em; }
.link-icon { font-size: 11px; opacity: .7; margin-left: 1px; }
/* ── Off-screen rendering skip (native virtualization) ───────────────────────
Long lists (300+ voices, 500+ online cards, big casts) only paint rows near the
viewport. content-visibility:auto lets the browser skip layout/paint for the rest;
contain-intrinsic-size reserves approximate height so the scrollbar stays stable. */
.vl-row { content-visibility: auto; contain-intrinsic-size: auto 64px; }
.voice-source-card, .fa-card, .el-card { content-visibility: auto; contain-intrinsic-size: auto 320px; }
.reh-cast-view-card .reh-cast-card { content-visibility: auto; contain-intrinsic-size: auto 420px; }
.reh-cast-view-list .reh-cast-card { content-visibility: auto; contain-intrinsic-size: auto 72px; }
/* ── Theme tokens (warm cream light theme) ──────────────────────────────── */
:root {
--bg: #F5F3EE;
--surface: #FFFFFF;
--panel: #F3F4F6;
--border: #E5E7EB;
--text: #111827;
--subtext: #5C6470;
--placehld: #5C6470;
--accent: #2563EB;
--green: #16A34A;
--red: #DC2626;
--error: #DC2626;
--yellow: #D97706;
--mauve: #7C3AED;
--teal: #0F766E;
--on-accent:#FFFFFF;
--radius: 8px;
--font: 'Segoe UI', system-ui, sans-serif;
--shadow: 0 2px 8px rgba(0,0,0,0.08);
--sidebar-width: 220px;
}
[data-theme="dark"] {
--bg: #111827;
--surface: #1F2937;
--panel: #374151;
--border: #4B5563;
--text: #F9FAFB;
--subtext: #9CA3AF;
--placehld: #6B7280;
--accent: #3B82F6;
--green: #22C55E;
--red: #EF4444;
--error: #EF4444;
--yellow: #F59E0B;
--mauve: #A855F7;
--teal: #14B8A6;
--on-accent:#FFFFFF;
--shadow: 0 4px 12px rgba(0,0,0,0.5);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; } /* stop iOS auto-inflating text */
body {
background: var(--bg); color: var(--text); font-family: var(--font);
font-size: 16px; height: 100vh; display: flex; flex-direction: column;
overflow: hidden;
-webkit-tap-highlight-color: transparent;
}
/* Dynamic viewport height — avoids the iOS Safari address-bar resize cutting off / locking
the layout (a common cause of "stuck"/unscrollable mobile pages). dvh==vh on desktop. */
@supports (height: 100dvh) { body { height: 100dvh; } }
/* Never allow sideways scroll on phones, and keep content clear of the notch */
@media (max-width: 768px) {
body { overflow-x: hidden; }
#app-shell { padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); }
}
/* Language picker in the sidebar brand */
.app-lang-toggle {
margin-left: auto; padding: 2px; border: 1px solid var(--border); border-radius: 5px;
background: var(--panel); cursor: pointer; line-height: 0; display: inline-flex;
align-items: center; transition: border-color .15s, transform .1s;
}
.app-lang-toggle:hover { border-color: var(--accent); }
.app-lang-toggle:active { transform: scale(.94); }
.app-lang-toggle:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,.18); }
.app-lang-toggle .fi { width: 20px; height: 14px; border-radius: 2px; }
/* ── App shell ───────────────────────────────────────────────────────────── */
#app-shell {
display: flex; flex: 1; min-height: 0; overflow: hidden;
}
/* ── Sidebar ─────────────────────────────────────────────────────────────── */
#sidebar {
width: var(--sidebar-width); flex-shrink: 0;
background: var(--surface); border-right: 1px solid var(--border);
display: flex; flex-direction: column; overflow-y: auto; overflow-x: hidden;
box-shadow: 2px 0 12px rgba(0,0,0,0.06);
}
.sidebar-brand {
padding: 18px 16px 14px;
border-bottom: 1px solid var(--border);
display: flex; align-items: flex-start; justify-content: space-between; gap: 8px;
}
.sidebar-brand-text { min-width: 0; }
.sidebar-collapse-btn, .sidebar-expand-btn {
background: none; border: none; cursor: pointer; color: var(--subtext);
padding: 4px; border-radius: 6px; font-size: 18px; line-height: 1;
flex-shrink: 0; display: flex; align-items: center; justify-content: center;
}
.sidebar-collapse-btn:hover { background: var(--panel); color: var(--text); }
#sidebar { transition: width .18s ease; }
.sidebar-expand-btn { display: none; }
/* ── Collapsed = slim 56 px icon rail; individual item labels appear as
floating tooltips via JS (#nav-rail-tooltip) — layout never shifts ── */
@media (min-width: 768px) {
body.sidebar-collapsed #sidebar { width: 56px; overflow-x: hidden; }
/* Rail: hide all text/badges/chevrons, keep leading icons only */
body.sidebar-collapsed #sidebar .nav-label,
body.sidebar-collapsed #sidebar .nav-badge,
body.sidebar-collapsed #sidebar .ntc,
body.sidebar-collapsed #sidebar .nav-chevron,
body.sidebar-collapsed #sidebar .nav-group-label,
body.sidebar-collapsed #sidebar .nav-group-head,
body.sidebar-collapsed #sidebar .sidebar-brand-text { display: none; }
body.sidebar-collapsed #sidebar .sidebar-brand { justify-content: center; padding-left: 0; padding-right: 0; }
body.sidebar-collapsed #sidebar .nav-item,
body.sidebar-collapsed #sidebar .nav-tree-item,
body.sidebar-collapsed #sidebar .nav-tree-head {
padding-left: 18px; padding-right: 0; gap: 0; white-space: nowrap;
font-size: 0;
}
body.sidebar-collapsed #sidebar .nav-item .mdi,
body.sidebar-collapsed #sidebar .nav-tree-item .mdi,
body.sidebar-collapsed #sidebar .nav-tree-head .mdi { font-size: 15px; }
body.sidebar-collapsed #sidebar .nav-tree .nav-tree-item,
body.sidebar-collapsed #sidebar .nav-tree .nav-tree-head.nav-subhead,
body.sidebar-collapsed #sidebar .nav-tree .nav-tree .nav-tree-item { padding-left: 18px; }
}
/* Floating label tooltip for icon-rail items */
#nav-rail-tooltip {
position: fixed; z-index: 200;
background: var(--surface); border: 1px solid var(--border);
border-radius: 6px; padding: 5px 11px;
font-size: 13px; font-weight: 500; color: var(--text);
white-space: nowrap; pointer-events: none; display: none;
box-shadow: 2px 4px 14px rgba(0,0,0,.18);
transform: translateY(-50%);
}
@media (max-width: 767px) {
.sidebar-collapse-btn, .sidebar-expand-btn { display: none !important; }
}
.sidebar-brand h1 {
font-size: 15px; font-weight: 800; color: var(--accent);
letter-spacing: -0.01em; line-height: 1.2;
display: flex; align-items: center; gap: 6px;
}
.sidebar-brand p {
font-size: 14px; color: var(--subtext); margin-top: 3px;
}
.sidebar-nav { flex: 1; padding: 8px 0; }
.nav-group-label {
padding: 10px 16px 4px;
font-size: 10px; font-weight: 800; color: var(--subtext);
text-transform: uppercase; letter-spacing: 0.09em;
}
/* ── Sidebar tree (My Voices) ────────────────────────────────────────────── */
.nav-tree-head { position: relative; }
.nav-label { flex: 1; }
.nav-badge {
font-size: 10.5px; font-weight: 700; color: var(--subtext);
background: var(--panel); border: 1px solid var(--border);
border-radius: 10px; padding: 1px 6px; min-width: 18px; text-align: center;
}
.nav-chevron { font-size: 14px; color: var(--subtext); transition: transform .2s; margin-left: 2px; }
.nav-casting-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); flex-shrink: 0; margin-left: auto; animation: pulse 1s infinite; }
.nav-chevron.open { transform: rotate(180deg); }
.nav-tree { display: none; flex-direction: column; padding: 2px 0 6px; }
.nav-tree.open { display: flex; }
.nav-tree-item {
display: flex; align-items: center; gap: 7px;
padding: 5px 16px 5px 32px; font-size: 12.5px; color: var(--subtext);
cursor: pointer; transition: background .1s, color .1s;
}
.nav-tree-item .mdi { font-size: 14px; flex-shrink: 0; }
.nav-tree-item:hover { background: var(--panel); color: var(--text); }
.nav-tree-item.is-active { color: var(--accent); font-weight: 700; }
/* Only show sub-item highlight when the parent section head is the CURRENT page.
When you're on a different section the remembered sub-item stays stored but
should not look "active" — it just creates visual noise. */
.nav-item:not(.active) ~ .nav-tree .nav-tree-item.is-active,
.nav-item:not(.active) ~ .nav-tree .nav-tree-head.nav-subhead.active {
color: var(--subtext); font-weight: normal;
}
/* Suppress sub-item highlight when its section-head is not the current section.
Covers Language Models, Books, Stage etc. that are hardcoded is-active in HTML. */
[data-nav-section]:not(.active) + .nav-tree .nav-tree-item.is-active {
color: var(--subtext); background: transparent; font-weight: normal;
}
/* ── Background-process busy indicator ──────────────────────────────────────
A small animated dot shown on a nav-item or nav-tree-head when a background
task (synthesis, benchmark, cast, playback) is running in that section.
Set via window.setNavBusy(sectionId, true|false) in nav.js. */
@keyframes nav-busy-pulse { 0%,100%{opacity:.5;transform:scale(.9)} 50%{opacity:1;transform:scale(1.15)} }
.nav-busy-dot {
display: inline-block; width: 7px; height: 7px; border-radius: 50%;
background: var(--accent); flex-shrink: 0; margin-left: auto;
animation: nav-busy-pulse 1.2s ease-in-out infinite;
}
/* Current page/section within its parent group */
.nav-tree-item.active {
background: rgba(37,99,235,0.08); color: var(--accent); font-weight: 700;
border-right: 3px solid var(--accent);
}
/* Virtual tag subfolders under My Voices */
.nav-tree-tag-label { padding: 7px 16px 3px 32px; font-size: 9.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--subtext); pointer-events: none; }
.nav-tree-item.nav-tree-tag { padding-left: 38px; }
.nav-tree-item.nav-tree-tag .mdi { font-size: 13px; opacity: .8; }
.ntc { font-size: 14px; color: var(--subtext); font-weight: 500; }
/* ── Collapsible group headers (Voice Actions · Speak · Setup) ───────────── */
.nav-group-head {
display: flex; align-items: center; gap: 8px; cursor: pointer;
padding: 10px 16px 4px; margin-top: 2px;
font-size: 10px; font-weight: 800; color: var(--subtext);
text-transform: uppercase; letter-spacing: 0.09em;
user-select: none;
}
.nav-group-head .nav-label { flex: 1; }
.nav-group-head:hover { color: var(--text); }
.nav-group-head .nav-chevron { font-size: 13px; }
/* ── Sub-headers nested inside a tree (Tags · Script Rehearsal · Library ·
Engines · Integrations · Settings) — look like items, carry a chevron ── */
.nav-tree .nav-tree-head.nav-subhead {
display: flex; align-items: center; gap: 7px; cursor: pointer;
padding: 5px 16px 5px 32px; font-size: 12.5px; color: var(--subtext);
transition: background .1s, color .1s;
}
.nav-tree .nav-tree-head.nav-subhead .nav-icon .mdi,
.nav-tree .nav-tree-head.nav-subhead > .mdi { font-size: 14px; flex-shrink: 0; }
.nav-tree .nav-tree-head.nav-subhead .nav-label { flex: 1; }
.nav-tree .nav-tree-head.nav-subhead:hover { background: var(--panel); color: var(--text); }
.nav-tree .nav-tree-head.nav-subhead.active { color: var(--accent); font-weight: 700; }
/* Nested trees indent one extra level per depth */
.nav-tree .nav-tree .nav-tree-item,
.nav-tree .nav-tree .nav-tree-head.nav-subhead { padding-left: 44px; }
.nav-tree .nav-tree .nav-tree .nav-tree-item { padding-left: 56px; }
.nav-tree-item.is-active .ntc { color: var(--accent); }
.nav-item {
display: flex; align-items: center; gap: 10px;
padding: 9px 16px; cursor: pointer; color: var(--subtext);
font-size: 13.5px; font-weight: 500;
transition: background 0.12s, color 0.12s;
border-right: 3px solid transparent;
user-select: none;
}
.nav-item:hover { background: var(--panel); color: var(--text); }
.nav-item.active {
background: rgba(37,99,235,0.08);
color: var(--accent); font-weight: 700;
border-right-color: var(--accent);
}
.nav-icon { font-size: 15px; width: 18px; text-align: center; flex-shrink: 0; }
.sidebar-footer {
padding: 12px 16px; border-top: 1px solid var(--border);
display: flex; gap: 8px; align-items: center;
}
.sidebar-footer button {
background: var(--panel); border: 1px solid var(--border); color: var(--subtext);
border-radius: var(--radius); padding: 6px 10px; font-size: 13px; cursor: pointer;
flex: 1; transition: background 0.12s, color 0.12s;
}
.sidebar-footer button:hover { background: var(--border); color: var(--text); }
/* ── Main content ────────────────────────────────────────────────────────── */
#main-content {
flex: 1; overflow-y: auto; overflow-x: hidden;
padding: 0 28px 0; min-width: 0;
}
/* ── Page sections ───────────────────────────────────────────────────────── */
.page-section { padding-top: 7px; display: none; }
.page-section.is-active { display: block; }
.section-head {
display: flex; align-items: center; gap: 14px;
padding: 20px; border-bottom: 2px solid var(--border);
margin-bottom: 20px;
background: var(--surface);
border-radius: var(--radius);
}
.section-icon { font-size: 26px; line-height: 1; }
.section-title h2 {
font-size: 20px; font-weight: 800; color: var(--text);
letter-spacing: -0.02em; margin: 0;
}
.section-title p {
font-size: 13px; color: var(--subtext); margin: 3px 0 0; line-height: 1.4;
}
/* Section head right-side actions (search + button) */
.section-head-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-shrink: 0; }
/* Previous/Next workflow shortcut, auto-injected top-right on every section
header — same navigation as the stepper widget further down, without
needing to scroll to it first. */
.wf-header-nav { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-shrink: 0; }
.wf-header-nav-btn {
display: inline-flex; align-items: center; gap: 4px;
padding: 7px 14px; border-radius: 8px; border: 1px solid var(--border);
background: var(--panel); color: var(--text); font-size: 13px; font-weight: 600; cursor: pointer;
}
.wf-header-nav-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); background: rgba(37,99,235,.08); }
.wf-header-nav-btn:disabled { opacity: .35; cursor: not-allowed; }
.wf-header-nav-label { max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Guidance bar under the section header: what to do on this step, and what
either Previous/Next actually leads to — sits right where the user's eye
already is after reading the Previous/Next buttons. */
.wf-step-hint {
display: flex; align-items: baseline; gap: 10px;
padding: 8px 20px; margin: -12px 0 20px;
background: var(--panel); border: 1px solid var(--border); border-top: none;
border-radius: 0 0 var(--radius) var(--radius);
font-size: 12.5px; color: var(--subtext); line-height: 1.4;
}
/* Studio's own Previous/Next (not .wf-header-nav — see s-caststudio.html) */
.stu-phase-nav { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-shrink: 0; }
.stu-phase-nav-btn {
display: inline-flex; align-items: center; gap: 4px;
padding: 7px 14px; border-radius: 8px; border: 1px solid var(--border);
background: var(--panel); color: var(--text); font-size: 13px; font-weight: 600; cursor: pointer;
}
.stu-phase-nav-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); background: rgba(37,99,235,.08); }
.stu-phase-nav-btn:disabled { opacity: .35; cursor: not-allowed; }
.wf-step-hint-badge {
flex-shrink: 0; font-weight: 700; color: var(--accent);
font-size: 11px; letter-spacing: .02em; text-transform: uppercase;
}
.wf-step-hint-text { flex: 1; min-width: 0; }
.section-search {
width: 220px; padding: 6px 12px; font-size: 13px; font-family: var(--font);
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
color: var(--text); transition: border-color .15s;
}
.section-search:focus, .section-search:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,.12); }
.section-new-voice-btn { padding: 6px 14px; font-size: 13px; white-space: nowrap; }
.section-search::placeholder {
color: var(--placehld);
}
/* ── Force all tab-content visible ──────────────────────────────────────── */
.tab-content {
display: flex !important; flex-direction: column; gap: 18px; padding: 0;
}
#tab-library { min-height: 0; }
/* Hide noisy sub-panels we don't need in this layout */
.library-benchmark-panel { display: none !important; }
#library-filter-panel { display: none; }
#disabled-info { display: none; }
/* ── Cards ──────────────────────────────────────────────────────────────── */
.card {
background: var(--surface); border: 1px solid var(--border);
border-radius: var(--radius); padding: 20px;
display: flex; flex-direction: column; gap: 14px;
box-shadow: var(--shadow); min-width: 0; max-width: 100%;
}
.card h2 {
font-size: 12px; font-weight: 700; color: var(--subtext);
text-transform: uppercase; letter-spacing: .09em;
}
/* ── Collapsible cards ───────────────────────────────────────────────────── */
.card-collapse-h2 { cursor: pointer; user-select: none; display: flex; align-items: center; gap: 7px; }
.card-collapse-h2:hover { opacity: .8; }
.card-chev { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 18px; height: 18px; border-radius: 4px; background: var(--panel); border: 1px solid var(--border); color: var(--accent); font-size: 13px; line-height: 1; transition: transform .2s; }
.card-col-closed .card-chev { transform: rotate(-90deg); }
/* Sync <details> inside cards to the same chevron look */
.card > details > summary { list-style: none; cursor: pointer; user-select: none; display: flex; align-items: center; gap: 7px; }
.card > details > summary::marker, .card > details > summary::-webkit-details-marker { display: none; }
.card > details > summary::before { content: '▾'; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 16px; height: 16px; border-radius: 4px; background: var(--panel); border: 1px solid var(--border); color: var(--accent); font-size: 10px; transition: transform .2s; }
.card > details:not([open]) > summary::before { transform: rotate(-90deg); }
/* ── Drop zone ──────────────────────────────────────────────────────────── */
/* Clone source picker — segmented File / URL / Mic */
/* Integrated tab box: the tab strip and the panel below read as one unit */
.clone-tabbox { display: flex; flex-direction: column; }
.clone-src-picker { display: flex; gap: 4px; margin: 0 0 -1px; align-items: flex-end; padding: 0 4px; border-bottom: 1px solid var(--border); position: relative; z-index: 1; }
.clone-src-tab { display: inline-flex; align-items: center; justify-content: center; gap: 7px; padding: 11px 18px; border: 1px solid transparent; border-bottom: none; background: transparent; color: var(--subtext); font-size: 14px; font-weight: 600; border-radius: 10px 10px 0 0; cursor: pointer; transition: background .15s, color .15s, border-color .15s; font-family: var(--font); position: relative; }
.clone-src-tab:hover { color: var(--text); background: color-mix(in srgb, var(--surface) 60%, transparent); }
.clone-src-tab.active { background: var(--surface); color: var(--accent); border-color: var(--border); border-bottom-color: var(--surface); }
.clone-src-tab.active::after { content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 2px; background: var(--accent); border-radius: 2px 2px 0 0; }
.clone-src-tab .mdi { font-size: 18px; }
.clone-srcpanel { background: var(--surface); border: 1px solid var(--border); border-radius: 0 var(--radius) var(--radius) var(--radius); padding: 20px; box-shadow: var(--shadow); }
.clone-src-intro { color: var(--subtext); font-size: 13px; margin: 0 0 14px; display: flex; align-items: center; gap: 7px; }
.clone-src-intro .mdi { font-size: 16px; color: var(--accent); }
.clone-id-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
/* author `display` on .card overrides the UA [hidden] rule — restore it */
.clone-src-card[hidden] { display: none; }
@media (max-width: 560px) { .clone-src-tab span:not(.mdi) { display: none; } }
#drop-zone {
border: 2px dashed var(--border); border-radius: var(--radius);
padding: 44px 20px; text-align: center; cursor: pointer; color: var(--subtext);
transition: border-color .2s, background .2s; font-size: 15px;
}
#drop-zone.drag-over { border-color: var(--accent); background: rgba(37,99,235,.05); color: var(--accent); }
#drop-zone span { display: block; font-size: 13px; margin-top: 9px; }
#drop-zone input[type=file] { display: none; }
/* ── Buttons ────────────────────────────────────────────────────────────── */
button {
cursor: pointer; border: none; border-radius: var(--radius);
padding: 9px 18px; font-size: 14px; font-family: inherit;
transition: opacity .15s, filter .15s;
}
button:disabled { opacity: .4; cursor: default; }
button:not(:disabled):hover { filter: brightness(0.95); }
.btn-primary { background: var(--accent); color: var(--on-accent); font-weight: 600; }
.btn-secondary { background: var(--panel); color: var(--text); border: 1px solid var(--border); }
.btn-danger { background: var(--error); color: #fff; font-weight: 600; }
.btn-green { background: #15803D; color: var(--on-accent); font-weight: 600; }
.btn-red { background: var(--red); color: var(--on-accent); font-weight: 600; }
.btn-teal { background: var(--teal); color: var(--on-accent); font-weight: 600; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
/* ── Waveform ───────────────────────────────────────────────────────────── */
#waveform-wrap { background: var(--panel); border-radius: var(--radius); overflow: hidden; }
#waveform { min-height: 90px; }
.time-row { display: flex; gap: 18px; align-items: center; flex-wrap: wrap; }
.time-row label { color: var(--subtext); font-size: 13px; display: flex; align-items: center; gap: 7px; }
.time-row input[type=number] {
background: var(--panel); border: 1px solid var(--border); color: var(--text);
border-radius: 4px; padding: 6px 10px; width: 100px; font-size: 14px;
}
#trim-duration { font-size: 14px; padding: 6px 14px; border-radius: 4px; font-weight: 600; }
.dur-ok { background: rgba(22,163,74,.12); color: var(--green); }
.dur-warn { background: rgba(217,119,6,.12); color: var(--yellow); }
.dur-bad { background: rgba(220,38,38,.12); color: var(--red); }
/* ── URL row ────────────────────────────────────────────────────────────── */
.url-row { display: flex; gap: 8px; }
.url-row input[type=text] {
flex: 1; background: var(--panel); border: 1px solid var(--border);
color: var(--text); border-radius: var(--radius); padding: 9px 14px; font-size: 14px;
}
input::placeholder, textarea::placeholder { color: var(--placehld); }
#yt-progress { font-size: 13px; color: var(--subtext); min-height: 1.4em; font-family: monospace; }
/* ── Recording ──────────────────────────────────────────────────────────── */
#rec-indicator { display: none; align-items: center; gap: 8px; color: var(--red); font-size: 14px; }
#rec-indicator.active { display: flex; }
#rec-dot { width: 10px; height: 10px; background: var(--red); border-radius: 50%; animation: pulse 1s infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .3; } }
/* ── Voice ID field ─────────────────────────────────────────────────────── */
.voice-id-row input[type=text] {
flex: 1; background: var(--panel); border: 1px solid var(--border); color: var(--text);
border-radius: var(--radius); padding: 10px 14px; font-size: 15px; font-family: monospace;
font-weight: 600; width: 100%;
}
.voice-id-row { display: flex; gap: 8px; }
input.id-valid { border-color: var(--green) !important; }
input.id-invalid { border-color: var(--red) !important; }
/* ── Helper details ─────────────────────────────────────────────────────── */
details.helper { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); }
details.helper summary { padding: 10px 14px; cursor: pointer; font-size: 13px; color: var(--subtext); user-select: none; list-style: none; }
details.helper summary::before { content: '\25B6 '; font-size: 14px; }
details.helper[open] summary::before { content: '\25BC '; }
details.helper .helper-body { padding: 12px 14px 14px; display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; }
.field { display: flex; flex-direction: column; gap: 5px; }
.field label { font-size: 12px; color: var(--subtext); font-weight: 600; letter-spacing: .03em; text-transform: uppercase; }
.field select, .field input[type=text] {
background: var(--bg); border: 1px solid var(--border); color: var(--text);
border-radius: var(--radius); padding: 8px 12px; font-size: 14px;
}
/* ── Textareas ──────────────────────────────────────────────────────────── */
#transcript-area, #preview-text-area, #design-instruct, #design-sample-text {
width: 100%; background: var(--panel); border: 1px solid var(--border); color: var(--text);
border-radius: var(--radius); padding: 10px 14px; font-size: 14px; font-family: inherit; resize: vertical;
}
#transcript-area { min-height: 90px; }
#preview-text-area { min-height: 72px; }
#design-instruct { min-height: 110px; }
#design-sample-text { min-height: 56px; }
audio { width: 100%; }
@media (min-width: 900px) {
#clone-sample-text, #lib-add-sample-text {
min-height: 190px;
font-size: 22px;
line-height: 1.65;
}
}
/* ── Voice Design ───────────────────────────────────────────────────────── */
.design-hints { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 12px; color: var(--subtext); }
.design-hints th, .design-hints td { text-align: left; vertical-align: top; padding: 7px 9px; border-bottom: 1px solid var(--border); }
.design-hints th { color: var(--text); font-size: 14px; text-transform: uppercase; letter-spacing: .06em; }
.design-samples-details summary { cursor: pointer; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; color: var(--subtext); user-select: none; list-style: none; }
.design-samples-details summary::-webkit-details-marker { display: none; }
.design-samples-details summary::before { content: '\25B6'; color: var(--accent); font-size: 14px; }
.design-samples-details[open] summary::before { content: '\25BC'; }
.design-samples-details summary span:first-child { font-size: 12px; font-weight: 700; color: var(--subtext); text-transform: uppercase; letter-spacing: .09em; }
.design-samples-details .design-sample-header { margin-top: 12px; }
.preset-row { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; margin-top: 10px; }
.preset-row input, .preset-row select { background: var(--panel); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); padding: 8px 12px; font-size: 14px; }
.design-sample-grid { display: grid; grid-template-columns: minmax(150px,1fr) 52px 86px minmax(220px,1.4fr) minmax(220px,1.4fr) 176px; gap: 8px; align-items: center; }
.design-sample-header { padding: 8px 10px 10px; border-bottom: 1px solid var(--border); }
.design-sample-header div { white-space: nowrap; overflow: hidden; font-size: 14px; font-weight: 700; color: var(--subtext); text-transform: uppercase; letter-spacing: .07em; }
.qwen-sample { border: 1px solid var(--border); border-radius: 6px; background: var(--panel); padding: 8px 10px; transition: border-color .15s; }
.qwen-sample:hover { border-color: var(--accent); }
.qwen-sample strong { color: var(--accent); font-size: 13px; }
.qwen-sample .sample-sex, .qwen-sample .sample-language { color: var(--subtext); font-size: 12px; font-family: monospace; }
.qwen-sample .sample-desc, .qwen-sample .sample-text { color: var(--subtext); font-size: 12px; line-height: 1.35; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qwen-sample audio { display: none; grid-column: 1 / -1; margin-top: 6px; }
.qwen-sample-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; justify-content: flex-end; }
.lang-select { background: var(--panel); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); padding: 8px 12px; font-size: 14px; }
.d-naming-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; }
.d-naming-row .field { flex: 0 0 auto; }
.d-naming-row .field.flex1 { flex: 1 1 140px; }
#d-voice-id { font-family: monospace; font-weight: 600; font-size: 15px; color: var(--accent); width: 100%; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); padding: 8px 12px; }
#d-transcript { min-height: 70px; width: 100%; background: var(--panel); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); padding: 10px 14px; font-size: 14px; font-family: inherit; resize: vertical; }
#d-lang, #d-gender, #d-name { background: var(--bg); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); padding: 8px 12px; font-size: 14px; }
#design-save-result { display: flex; flex-direction: column; gap: 8px; }
#tts-voice-select { background: var(--panel); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); padding: 8px 12px; font-size: 14px; min-width: 200px; }
.preview-match-panel { margin-top: 12px; border: 1px solid var(--border); border-radius: 6px; background: rgba(37,99,235,.04); padding: 12px; display: grid; grid-template-columns: minmax(220px,.75fr) minmax(260px,1fr); gap: 12px; }
.preview-match-panel[hidden] { display: none; }
.preview-match-meta { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.preview-match-title { font-weight: 700; color: var(--text); }
.preview-match-detail { color: var(--subtext); font-size: 12px; line-height: 1.45; }
.preview-match-warning { color: var(--yellow); font-size: 12px; line-height: 1.45; }
.preview-match-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.preview-match-panel audio { width: 100%; min-width: 0; }
.preview-match-transcript { background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 10px; color: var(--subtext); font-family: monospace; font-size: 12px; line-height: 1.4; max-height: 88px; overflow: auto; white-space: pre-wrap; }
@media (max-width: 900px) { .preview-match-panel { grid-template-columns: 1fr; } }
.tryout-voice-row { display: grid; grid-template-columns: minmax(150px,1fr) minmax(230px,1.7fr) minmax(150px,1fr); gap: 12px; align-items: end; }
.tryout-voice-row .field select { width: 100%; min-width: 0; }
.tryout-voice-pick { display: flex; gap: 6px; align-items: stretch; min-width: 0; }
.tryout-voice-pick select { flex: 1 1 auto; min-width: 0; }
.tryout-voice-pick .vp-root { flex: 1 1 auto; min-width: 0; } /* searchable widget replaces the select */
.conv-config-group .vp-root[data-vp-for="conv-tts-voice-select"] {
min-width: min(360px, 100%);
flex: 1 1 360px;
}
.conv-config-group .vp-root[data-vp-for="conv-tts-voice-select"] .vp-drop {
z-index: 120;
}
@media (max-width: 900px) {
.conv-config-group .vp-root[data-vp-for="conv-tts-voice-select"] {
width: 100%;
min-width: 0;
}
}
.tryout-voice-pick .btn-sm { flex: 0 0 auto; padding: 0 11px; display: inline-flex; align-items: center; }
@media (max-width: 720px) { .tryout-voice-row { grid-template-columns: 1fr; } }
/* ── Settings pages ─────────────────────────────────────────────────────── */
.s-settings-page { display:none; flex-direction:column; gap:16px; }
.s-settings-page.is-active { display:flex; }
.s-engines-page { display:none; flex-direction:column; gap:16px; }
.s-engines-page.is-active { display:flex; }
/* Combined Library — tabs + panels */
.lib-tabs { display:flex; gap:6px; margin:4px 0 16px; flex-wrap:wrap; }
.lib-tab {
display:inline-flex; align-items:center; gap:6px; padding:8px 14px;
border:1px solid var(--border); border-radius:8px; background:var(--surface);
color:var(--subtext); font-size:13px; font-weight:500; cursor:pointer;
transition:background .14s ease, color .14s ease, border-color .14s ease;
}
.lib-tab:hover { color:var(--text); border-color:var(--accent); }
.lib-tab.is-active { background:var(--accent); border-color:var(--accent); color:#fff; }
.lib-panel { display:none; }
.lib-panel.is-active { display:block; }
.lib-empty { display:flex; flex-direction:column; align-items:center; gap:8px; padding:40px 0; color:var(--subtext); text-align:center; }
.lib-empty .mdi { font-size:42px; opacity:.4; }
.lib-empty p { margin:0; font-size:13px; line-height:1.5; }
.lib-empty-hint { opacity:.8; }
.lib-chars-loading { padding:32px; text-align:center; color:var(--subtext); font-size:13px; }
/* ── Characters / Cast view ─────────────────────────────────────────────────── */
.lib-chars-toolbar { display:flex; gap:8px; margin-bottom:16px; flex-wrap:wrap; align-items:center; }
.lib-chars-toolbar #lib-chars-back-reader { margin-right:4px; }
.lib-chars-sort { display:flex; align-items:center; gap:6px; font-size:12.5px; color:var(--subtext); font-weight:600; }
.lib-chars-sort select {
padding:5px 8px; border-radius:6px; border:1px solid var(--border); background:var(--surface);
color:var(--text); font-size:12.5px; cursor:pointer;
}
.lib-chars-view-toggle { display:flex; gap:2px; margin-left:auto; }
.lib-chars-view-toggle button.is-active { background:var(--accent); color:#fff; border-color:var(--accent); }
/* Table view — dense alternative to the card grid for scanning a large cast */
.lib-chars-tbl-wrap { overflow-x:auto; border:1px solid var(--border); border-radius:12px; background:var(--surface); position:relative; }
.lib-chars-tbl { width:100%; min-width:1662px; table-layout:fixed; border-collapse:collapse; font-size:12.9px; white-space:nowrap; }
.lib-chars-tbl td { overflow: hidden; text-overflow: ellipsis; }
.lib-chars-tbl thead th {
text-align:left; padding:8px 8px; font-size:10.5px; font-weight:800; text-transform:uppercase;
letter-spacing:.04em; color:var(--subtext); border-bottom:1px solid var(--border); background:var(--panel);
position:sticky; top:0; z-index:1;
}
.lib-chars-tbl thead th.lib-chars-tbl-sortable { cursor: pointer; user-select: none; }
.lib-chars-tbl thead th.lib-chars-tbl-sortable:hover { color: var(--accent); }
.lib-chars-tbl thead th.lib-chars-tbl-sortable .mdi { font-size: 11px; vertical-align: -1px; }
.lib-chars-tbl td { padding:8px 8px; border-bottom:1px solid var(--border); vertical-align:middle; }
.lib-chars-tbl th:nth-child(1), .lib-chars-tbl td:nth-child(1),
.lib-chars-tbl th:nth-child(2), .lib-chars-tbl td:nth-child(2),
.lib-chars-tbl th:nth-child(3), .lib-chars-tbl td:nth-child(3) {
position: sticky;
background: var(--surface);
}
.lib-chars-tbl thead th:nth-child(1),
.lib-chars-tbl thead th:nth-child(2),
.lib-chars-tbl thead th:nth-child(3) {
background: var(--panel);
}
.lib-chars-tbl th:nth-child(1), .lib-chars-tbl td:nth-child(1) { left: 0; z-index: 5; width: 28px; min-width: 28px; }
.lib-chars-tbl th:nth-child(2), .lib-chars-tbl td:nth-child(2) { left: 28px; z-index: 4; width: 40px; min-width: 40px; }
.lib-chars-tbl th:nth-child(3), .lib-chars-tbl td:nth-child(3) {
left: 68px; z-index: 3; width: 260px; min-width: 260px;
box-shadow: 10px 0 14px -14px rgba(0,0,0,.28);
}
.lib-chars-tbl-row:hover td:nth-child(1),
.lib-chars-tbl-row:hover td:nth-child(2),
.lib-chars-tbl-row:hover td:nth-child(3) {
background: var(--panel);
}
/* Rows reuse .lib-char-card so the existing per-card click/voice/export wiring
picks them up, but that class's display:flex;flex-direction:column (meant
for the card grid) turned every <tr> into a flex column, stacking its <td>s
vertically instead of laying the table out in columns. Reset it back to a
real table row, and undo the card-specific chrome that leaked in with it. */
tr.lib-char-card.lib-chars-tbl-row {
display: table-row; cursor: pointer;
background: none; border: 0; border-radius: 0; box-shadow: none; transition: none;
}
tr.lib-char-card.lib-chars-tbl-row:hover { transform: none; box-shadow: none; background: var(--panel); }
.lib-chars-tbl-row:hover { background:var(--panel); }
.lib-chars-tbl td.lib-chars-tbl-avatar-cell {
overflow: visible;
text-overflow: clip;
padding-left: 6px;
padding-right: 2px;
}
/* Same specificity as the base .lib-char-avatar rule (card-grid sizing) but
declared earlier in the file, so without the extra qualifiers here the
later, larger card-grid rule silently won the cascade — table rows ended
up with ~90px avatars overlapping the name text instead of these 26px
ones. Ancestor + two classes beats the single-class rule regardless of
source order. */
.lib-chars-tbl-avatar-cell .lib-char-avatar.lib-chars-tbl-avatar {
width: 48px; height: 48px; font-size: 18px; border: none; box-shadow: 0 1px 4px rgba(0,0,0,.10);
border-radius: 50%; overflow: hidden;
}
.lib-chars-tbl-row .lib-char-export { position:static; opacity:1; width:auto; height:auto; border:0; background:none; color:var(--subtext); padding:2px; }
.lib-chars-tbl-row .lib-char-export:hover { color:var(--accent); background:none; border:0; }
.lib-chars-tbl-name { font-weight:600; white-space:normal; min-width:240px; }
.lib-chars-tbl-name-main { display:flex; align-items:center; gap:8px; flex-wrap:wrap; line-height:1.15; }
.lib-chars-tbl-sub { margin-top:3px; font-size:11.5px; color:var(--subtext); white-space:normal; line-height:1.35; }
.lib-chars-tbl-book { margin-top:4px; font-size:11px; color:var(--accent); white-space:normal; line-height:1.35; font-weight:600; }
/* Two stacked rows (voice name+play, then Auswahl/Auto) instead of one —
a long voice id used to push the action buttons out of the visible
column width entirely, confirmed live. */
.lib-chars-tbl-voice-wrap { display:flex; flex-direction:column; align-items:flex-start; gap:4px; }
.lib-chars-tbl-voice-row { display:flex; align-items:center; gap:6px; flex-wrap:wrap; max-width:100%; }
.lib-chars-tbl-voice button { padding:2px 7px; font-size:11px; }
/* display:flex directly on a <td> breaks its table-cell layout participation
(Chrome renders it detached from the column grid — width/position stop
matching its own header entirely). Flex only the inner wrapper instead. */
.lib-chars-tbl-tags { white-space:normal; max-width:260px; }
.lib-chars-tbl-tags-wrap { display:flex; flex-wrap:wrap; gap:3px; }
.lib-chars-tbl-dash { opacity:.4; }
.lib-chars-tbl-check { display:inline-flex; }
.lib-chars-tbl-check.is-yes { color:#4caf50; }
.lib-chars-tbl-check.is-no { color:var(--subtext); opacity:.35; }
.lib-chars-tbl td .lib-char-align-bar { width:60px; flex:none; display:inline-block; }
.lib-chars-production { margin-bottom:28px; border-radius: 12px; transition: box-shadow .3s, background .3s; }
.lib-chars-production-highlight { box-shadow: 0 0 0 3px var(--accent); background: color-mix(in srgb, var(--accent) 6%, transparent); }
/* Compact single-line list row instead of a bordered box per fact — the
card body has very little room once the banner became a square (see
.lib-char-card's playing-card aspect-ratio), so a table/list layout that
only spends space on facts that actually have a value fits far more in. */
.lib-char-stat-row {
display:flex; align-items:baseline; gap:7px; min-width:0;
padding:4px 0; border-bottom:1px solid rgba(0,0,0,.06);
font-size:12.5px; line-height:1.35;
}
.lib-char-stat-icon { flex-shrink:0; font-size:12px; color:var(--accent); align-self:center; }
.lib-char-stat-label {
flex-shrink:0; text-transform:uppercase; letter-spacing:.06em; font-size:10px;
font-weight:800; color:var(--subtext); width:72px;
}
.lib-char-stat-value { min-width:0; font-weight:600; color:var(--text); overflow-wrap:anywhere; }
.lib-chars-prod-head {
display: flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:8px;
padding:10px 14px; border-radius:8px 8px 0 0; gap:10px;
background: linear-gradient(90deg, var(--pk1,#4f46e5), var(--pk2,#7c3aed));
color: #fff; cursor:pointer;
}
.lib-chars-prod-collapse-btn {
flex-shrink:0; width:24px; height:24px; padding:0; border:0; border-radius:6px;
background:rgba(255,255,255,.15); color:#fff; cursor:pointer;
display:flex; align-items:center; justify-content:center;
}
.lib-chars-prod-collapse-btn:hover { background:rgba(255,255,255,.28); }
.lib-chars-prod-collapse-btn .mdi { transition:transform .18s; }
.lib-chars-production-collapsed .lib-chars-prod-collapse-btn .mdi { transform:rotate(-90deg); }
.lib-chars-production-collapsed .lib-chars-prod-head { border-radius:8px; }
.lib-chars-production-collapsed .lib-chars-prod-body { display:none; }
.lib-chars-prod-title { font-weight:600; font-size:14px; display:flex; align-items:center; gap:8px; }
.lib-chars-prod-title .mdi { opacity:.8; }
.lib-chars-prod-actions { display:flex; gap:6px; flex-wrap:wrap; }
.lib-chars-prod-actions .btn-secondary {
background: rgba(255,255,255,.15); border-color: rgba(255,255,255,.3); color:#fff; font-size:11px;
}
.lib-chars-prod-actions .btn-secondary:hover { background: rgba(255,255,255,.28); }
.lib-chars-prod-actions .lib-chars-bulk-delete-btn:not(:disabled) { border-color: rgba(255,120,120,.6); }
.lib-chars-prod-actions .lib-chars-bulk-delete-btn:not(:disabled):hover { background: rgba(220,60,60,.35); }
.lib-chars-prod-actions .lib-chars-image-provider {
background: rgba(255,255,255,.15); border: 1px solid rgba(255,255,255,.3); color:#fff;
font-size: 11px; border-radius: 5px; padding: 0 6px; height: 26px; font-family: inherit;
}
.lib-chars-prod-actions .lib-chars-image-provider option { color: #111; }
.lib-chars-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 18px; padding:18px;
background: var(--panel);
border: 1px solid var(--border); border-top: none; border-radius: 0 0 8px 8px;
}
/* Portrait-style character card */
.lib-char-card {
display: flex; flex-direction:column; align-items:stretch;
background: var(--surface); cursor:pointer; position:relative;
border-radius:16px; overflow:hidden; border:1px solid var(--border);
transition: transform .13s, box-shadow .13s;
box-shadow: 0 10px 24px rgba(0,0,0,.12);
/* Standard playing-card proportion (2.5:3.5) so every card in the grid
reads as a uniform deck regardless of how much fact/text content each
character has — the body below flexes to fill whatever's left under
the square banner instead of driving the card's total height. */
aspect-ratio: 5 / 7;
/* A production's full character grid (each card carrying a generated
portrait image) stays fully laid out and painted at once with no
virtualization, the same category of issue confirmed and fixed for the
casting view's segment list — matches part of what was running when a
later crash was reported (bulk profile/portrait/voice generation across
dozens of characters). Same proven fix, same reasoning: off-screen
cards stop costing layout/paint, nothing else about the page changes. */
content-visibility: auto;
contain-intrinsic-size: auto 320px;
}
.lib-char-card:hover { transform:translateY(-4px); box-shadow:0 14px 34px rgba(0,0,0,.18); }
.lib-char-select {
position:absolute; top:8px; left:8px; z-index:3; cursor:pointer;
width:20px; height:20px; display:flex; align-items:center; justify-content:center;
background:rgba(0,0,0,.35); border-radius:5px;
}
.lib-char-select-cb { width:15px; height:15px; cursor:pointer; }
/* Coloured banner at top of each card */
.lib-char-card-banner {
aspect-ratio: 1 / 1; height:auto; flex-shrink:0;
display:flex; align-items:flex-end; justify-content:flex-start; position:relative;
gap:14px; padding:16px; overflow:hidden;
background: linear-gradient(135deg, var(--ch1,#4f46e5) 0%, var(--ch2,#7c3aed) 100%);
}
.lib-char-avatar {
width:96px; height:96px; border-radius:50%;
display:flex; align-items:center; justify-content:center;
font-size:36px; font-weight:700; color:#fff; letter-spacing:0;
border:4px solid rgba(255,255,255,.32); box-shadow:0 10px 22px rgba(0,0,0,.34);
flex-shrink:0;
}
/* Once the banner itself is the portrait, the avatar circle collapses to a
small "change photo" corner button instead of duplicating the same image
at icon size on top of itself. */
.lib-char-card-banner.has-photo { align-items:flex-end; }
.lib-char-avatar.is-photo-edit {
position:absolute; top:10px; right:10px; width:30px; height:30px;
font-size:15px; border-width:2px; box-shadow:0 3px 8px rgba(0,0,0,.4);
background:rgba(0,0,0,.38); opacity:.75; transition:opacity .15s;
}
.lib-char-avatar.is-photo-edit:hover { opacity:1; }
.lib-char-banner-copy {
flex:1; min-width:0; min-height:0; display:flex; flex-direction:column; justify-content:center; gap:6px;
color:#fff; padding:4px 34px 4px 0; overflow:hidden;
}
.lib-char-name {
font-weight:800; font-size:20px; text-align:left;
display:flex; align-items:center; gap:8px; flex-wrap:wrap;
line-height:1.1;
}
.lib-char-tier { font-size:9px; font-weight:700; letter-spacing:.5px; text-transform:uppercase;
padding:2px 6px; border-radius:10px; }
.lib-char-tier.main { background: rgba(245,158,11,.2); color: #d97706; }
.lib-char-tier.support { background: rgba(99,102,241,.15); color: var(--accent); }
/* Whether a character has a voice — and which one — used to only be
readable as text at the very bottom of a long card, so scanning a whole
grid for "who still needs a voice" meant reading every card in full. A
clickable pill right at the top of the banner makes it a glance instead
of a read, and doubles as the fastest way to fix it: opens the same
pick/design popup used everywhere else. */
.lib-char-voice-top-row {
/* left offset clears the select checkbox, which sits at the same corner
(top:8px/left:8px, 20px wide) one layer above the banner. Holds the
"hear a sample" play button directly in front of the voice pill instead
of down at the bottom of the card, now that the pill itself lives here. */
position:absolute; top:10px; left:34px; z-index:2;
display:flex; align-items:center; gap:6px; max-width:calc(100% - 44px);
}
.lib-char-card-banner.has-photo .lib-char-voice-top-row { max-width:calc(100% - 80px); }
.lib-char-voice-top-row .lib-char-voice-play {
flex-shrink:0; width:22px; height:22px; padding:0; border-radius:50%; border:0;
background:var(--green,#22c55e); color:#fff;
}
.lib-char-voice-top-row .lib-char-voice-play:hover { background:#1ca750; }
.lib-char-voice-top-row .lib-char-voice-play.playing { background:var(--accent); }
.lib-char-voice-pill {
display:flex; align-items:center; gap:5px; min-width:0; flex:1;
height:22px; padding:0 9px; border-radius:11px; border:0; cursor:pointer;
background:rgba(0,0,0,.4); color:rgba(255,255,255,.7); font-size:11px; font-weight:700;
transition:background .12s, color .12s;
}
.lib-char-voice-pill:hover { background:rgba(0,0,0,.6); color:#fff; }
.lib-char-voice-pill .mdi { flex-shrink:0; font-size:13px; }
.lib-char-voice-pill-text { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.lib-char-voice-pill.has-voice { background:var(--green,#22c55e); color:#fff; }
.lib-char-voice-pill.has-voice:hover { background:#1ca750; }
.lib-char-voice-pill.voice-missing { background:var(--red,#ef4444); color:#fff; }
.lib-char-voice-pill.voice-missing:hover { background:#dc2626; }
.lib-chars-tbl-voice-missing, .lcd-voice-missing { color:var(--red,#ef4444); font-weight:600; }
.lib-chars-tbl-voice-missing .mdi, .lcd-voice-missing .mdi { font-size:13px; }
.lib-char-roleline {
font-size:14px; color:rgba(255,255,255,.92); font-weight:700; line-height:1.25;
display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.lib-char-subline {
font-size:12.5px; color:rgba(255,255,255,.75); line-height:1.35; font-style:italic;
overflow-wrap:anywhere;
display:-webkit-box; -webkit-line-clamp:1; -webkit-box-orient:vertical; overflow:hidden;
}
.lib-char-meta-chips { display:flex; flex-wrap:wrap; gap:6px; margin-top:2px; }
.lib-char-meta-chip {
display:inline-flex; align-items:center; gap:5px; padding:4px 8px; border-radius:999px;
background: rgba(255,255,255,.15); border:1px solid rgba(255,255,255,.18);
color:#fff; font-size:11px; font-weight:700;
}
.lib-char-meta-chip .mdi { font-size:11px; }
.lib-char-body {
/* Fills whatever's left under the square banner within the card's own
aspect-ratio, instead of a hardcoded height — the card's total size is
now driven by aspect-ratio + width, not by summing fixed child sizes. */
flex:1; min-height:0; padding:14px 16px 16px; display:flex; flex-direction:column; gap:6px;
overflow-y:auto;
}
.lib-char-facts {
display:flex; flex-direction:column;
}
.lib-char-archetype {
font-size:13px; color:var(--subtext); text-align:left; margin:0; font-style:italic;
}
.lib-char-snippet {
font-size:13.5px; line-height:1.55; color:var(--subtext); flex:1; margin:0;
display:-webkit-box; -webkit-line-clamp:5; -webkit-box-orient:vertical; overflow:hidden;
min-height: 88px;
}
/* Table-view voice actions (Auswahl/Auto) — base look + per-action hover tint. */
.lib-char-pick-voice, .lib-char-auto-voice, .lib-char-online-voice, .lib-char-gen-voice {
font-size:10px; padding:2px 8px; border-radius:4px; cursor:pointer;
border:1px solid var(--border); background:var(--panel); color:var(--text);
transition: background .12s, border-color .12s, color .12s;
}
.lib-char-pick-voice:hover { border-color:var(--accent); color:var(--accent); }
.lib-char-auto-voice:hover { border-color: var(--green,#22c55e); color: var(--green,#22c55e); }
.lib-char-online-voice:hover { border-color:#0ea5e9; color:#0ea5e9; }
.lib-char-gen-voice:hover { border-color:#a855f7; color:#a855f7; }
/* Quick "hear a sample line" play button — sits next to the voice ID in
both the card and table views, wherever a character already has a voice
assigned. Toggles to a stop icon while its own preview is playing. */
.lib-char-voice-play {
flex-shrink:0; min-width:22px; height:22px; padding:0 10px; border-radius:11px;
display:inline-flex; align-items:center; justify-content:center; gap:5px;
border:1px solid var(--border); background:var(--panel); color:var(--accent);
cursor:pointer; font-size:12px; transition:background .12s, border-color .12s, color .12s;
}
/* Icon-only (table view) stays a plain circle — no label text to pad for. */
.lib-chars-tbl-voice-wrap .lib-char-voice-play { padding:0; width:22px; border-radius:50%; }
.lib-char-voice-play:hover { border-color:var(--accent); background:rgba(var(--accent-rgb,124,106,247),.12); }
.lib-char-voice-play.loading .mdi { animation: spin .8s linear infinite; }
.lib-char-voice-play.playing { border-color:var(--accent); background:var(--accent); color:#fff; }
.lib-chars-tbl-voice-wrap .lib-char-voice-play { margin-left:2px; }
/* Icon-only "design a new voice" action — for when the current voice just
doesn't fit, next to (not replacing) Auswahl/Auto so there's an explicit
one-click way to get something genuinely different. */
.lib-char-redesign-voice {
flex-shrink:0; width:22px; height:22px; padding:0; border-radius:50%;
display:inline-flex; align-items:center; justify-content:center;
border:1px solid var(--border); background:var(--panel); color:var(--accent);
cursor:pointer; font-size:13px; transition:background .12s, border-color .12s, color .12s;
}
.lib-char-redesign-voice:hover:not(:disabled) { border-color:var(--accent); background:rgba(var(--accent-rgb,124,106,247),.12); }
.lib-char-redesign-voice:disabled { opacity:.5; cursor:not-allowed; }
/* Big hover preview of a character's profile picture — a table/card
thumbnail alone (often 32-40px) gives no real sense of the actual
portrait. Fixed-position, follows whichever avatar is hovered, never the
click target itself (pointer-events:none) so it can't interfere with the
avatar's own click-to-upload behavior. */
.lib-avatar-hover-preview {
position:fixed; z-index:2000; width:512px; height:512px;
border-radius:12px; overflow:hidden; pointer-events:none;
box-shadow:0 12px 40px rgba(0,0,0,.35); border:1px solid var(--border);
background:var(--panel);
}
.lib-avatar-hover-preview img { width:100%; height:100%; object-fit:cover; display:block; }
/* Alignment bar */
.lib-char-align { display:flex; align-items:center; gap:5px; margin:6px 0 4px; }
.lib-char-align-evil { font-size:9px; color:#555; flex-shrink:0; line-height:1; }
.lib-char-align-good { font-size:9px; color:#ddd; flex-shrink:0; line-height:1; }
.lib-char-align-bar {
flex:1; height:7px; border-radius:4px; position:relative; cursor:default;
background: linear-gradient(to right, #111 0%, #444 30%, #888 50%, #ccc 70%, #f0f0f0 100%);
box-shadow: inset 0 1px 2px rgba(0,0,0,.4);
}
.lib-char-align-dot {
position:absolute; top:50%; transform:translate(-50%,-50%);
width:11px; height:11px; border-radius:50%;
background: #fff; border:2px solid rgba(0,0,0,.6);
box-shadow: 0 0 0 1px rgba(255,255,255,.4), 0 1px 3px rgba(0,0,0,.5);
transition: left .3s ease;
}
.lib-char-align-arrow { font-size:13px; flex-shrink:0; line-height:1; font-style:normal; }
/* Most-interacted character dots */
.lib-char-rels { display:flex; align-items:center; gap:5px; margin:5px 0 7px; flex-wrap:wrap; }
.lib-char-rel-dot {
width:24px; height:24px; border-radius:50%; display:inline-flex; align-items:center;
justify-content:center; font-size:10px; font-weight:700; color:#fff; flex-shrink:0;
cursor:default; border:1.5px solid rgba(255,255,255,.15);
box-shadow: 0 1px 3px rgba(0,0,0,.3);
}
@media (max-width: 1100px) {
.lib-chars-grid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
}
@media (max-width: 700px) {
.lib-chars-grid { grid-template-columns: 1fr; }
/* A single full-width column would stretch a 5:7 card absurdly tall —
drop the aspect-ratio and let content size the card again. */
.lib-char-card { aspect-ratio: auto; height: auto; }
.lib-char-card-banner { aspect-ratio: auto; height: auto; min-height: 120px; }
.lib-char-avatar { width:82px; height:82px; font-size:30px; }
.lib-char-name { font-size:18px; }
.lib-chars-tbl { min-width: 1340px; }
}
/* ── Character detail modal (D&D / LARP card) ───────────────────────────────── */
.lib-char-detail-ov {
position:fixed; inset:0; z-index:1100;
background: rgba(0,0,0,.78); backdrop-filter:blur(6px);
display:flex; align-items:flex-start; justify-content:center;
padding:32px 16px 48px; overflow-y:auto;
}
.lib-char-detail-box {
background: var(--surface); border-radius:16px; width:100%; max-width:860px;
box-shadow: 0 32px 80px rgba(0,0,0,.6); overflow:hidden; flex-shrink:0;
}
.lcd-header {
display:flex; gap:20px; align-items:stretch; padding:28px 28px 24px;
background: linear-gradient(135deg, var(--lc1,#4f46e5) 0%, var(--lc2,#7c3aed) 100%);
color:#fff; position:relative;
}
/* A character with an already-saved profile picture used to show it as a
small ~80px square tucked in the corner like the plain letter fallback —
once there's a real photo, it deserves to fill the whole header instead
of being squeezed down to icon size. The letter-only placeholder stays at
its normal compact size (align-items:stretch above only affects children
that don't set their own height, like this one via align-self below). */
.lcd-header .cs-avatar.cs-avatar-img {
width:110px; height:auto; align-self:stretch; border-radius:8px;
}
.lcd-avatar {
flex-shrink:0; width:90px; height:90px; border-radius:50%;
display:flex; align-items:center; justify-content:center;
font-size:38px; font-weight:700; color:#fff; letter-spacing:0;
border:3px solid rgba(255,255,255,.4); box-shadow: 0 6px 18px rgba(0,0,0,.35);
overflow:hidden; cursor:pointer;
}
.lcd-avatar:hover::after {
content:'\F04F4'; font-family:'Material Design Icons'; font-size:28px;
position:absolute; inset:0; border-radius:50%;
display:flex; align-items:center; justify-content:center;
background:rgba(0,0,0,.45); color:#fff;
}
.lcd-avatar { position:relative; }
.lcd-avatar img { width:100%; height:100%; object-fit:cover; }
.lcd-avatar-wrap { position: relative; flex-shrink: 0; }
.lcd-avatar-actions {
position: absolute; left: 50%; bottom: -8px; transform: translateX(-50%); z-index: 2;
display: flex; gap: 4px;
}
.lcd-avatar-actions button {
width: 24px; height: 24px; border-radius: 50%;
display: flex; align-items: center; justify-content: center;
background: var(--accent); color: #fff; border: 2px solid var(--surface);
cursor: pointer; font-size: 12px; box-shadow: 0 2px 6px rgba(0,0,0,.25);
}
.lcd-avatar-actions button:hover { filter: brightness(1.1); }
.lcd-avatar-actions button:disabled { opacity: .6; cursor: default; }
.lcd-avatar-online-btn { background: var(--teal, #0F766E) !important; }
.lcd-avatar-upload-btn { background: var(--mauve, #7C3AED) !important; }
.lcd-header-body { flex:1; min-width:0; }
.lcd-name { font-size:26px; font-weight:700; line-height:1.15; margin-bottom:5px; }
.lcd-aliases { font-size:14px; opacity:.72; margin-bottom:7px; font-style:italic; }
.lcd-archetype { font-size:17px; opacity:.88; margin-bottom:12px; font-weight:500; }
.lcd-tier-gender { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.lcd-tier { font-size:12px; font-weight:700; letter-spacing:.6px; text-transform:uppercase;
padding:4px 12px; border-radius:14px; background:rgba(255,255,255,.22); }
.lcd-linecount {
display:inline-flex; align-items:center; justify-content:center;
font-size:12px; font-weight:700; letter-spacing:.02em;
padding:4px 10px; border-radius:14px;
border:1px solid rgba(255,255,255,.28);
background:rgba(255,255,255,.14);
color:#fff;
}
.lcd-gender { font-size:14px; opacity:.82; }
/* The auto-generated concept-art sheet — a full-width banner just below the
header (its own .lcd-section-full row), sized to actually be readable
instead of squeezed to a 110px header thumbnail (confirmed live: too
small to make out any detail in a multi-pose design sheet). */
.lcd-conceptart-headrow {
display: flex; align-items: center; justify-content: space-between; gap: 12px;
margin-bottom: 14px;
}
.lcd-conceptart-img {
width: 100%; max-height: 70vh; border-radius: 10px; overflow: hidden;
cursor: pointer; border: 1px solid var(--border);
display: flex; justify-content: center; background: color-mix(in srgb, var(--panel) 60%, transparent);
}
.lcd-conceptart-img img { max-width: 100%; max-height: 70vh; object-fit: contain; display: block; }
.lcd-conceptart-empty {
width: 100%; min-height: 160px; border-radius: 10px;
border: 2px dashed var(--border);
display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: 6px; font-size: 13px; text-align: center; color: var(--subtext); padding: 20px;
}
.lcd-conceptart-empty .mdi { font-size: 30px; }
.lcd-conceptart-empty.is-noprompt { opacity: .6; }
.conceptart-lightbox-box { width: min(900px, 96vw); max-height: 94vh; overflow-y: auto; }
.conceptart-lightbox-img { width: 100%; height: auto; border-radius: 10px; display: block; }
.lcd-header-btns { display:flex; gap:8px; flex-shrink:0; align-self:flex-start; }
.lcd-header-btns button {
background:rgba(255,255,255,.18); border:1px solid rgba(255,255,255,.32); color:#fff;
border-radius:8px; padding:7px 16px; font-size:14px; cursor:pointer;
transition:background .12s; display:flex; align-items:center; gap:6px;
}
.lcd-header-btns button:hover { background:rgba(255,255,255,.32); }
/* Body with alternating section backgrounds */
.lcd-body { padding:0; }
.lcd-align-section {
padding:20px 28px 18px; border-bottom:1px solid var(--border);
background: var(--panel);
}
.lcd-align-bar-wrap { display:flex; align-items:center; gap:12px; margin:10px 0 6px; }
.lcd-align-label { font-size:14px; color:var(--subtext); flex-shrink:0; font-weight:600; }
.lcd-align-bar {
flex:1; height:12px; border-radius:6px; position:relative;
background: linear-gradient(to right, #1a1a1a 0%, #555 30%, #888 50%, #bbb 70%, #efefef 100%);
box-shadow: inset 0 2px 4px rgba(0,0,0,.5);
}
.lcd-align-dot {
position:absolute; top:50%; transform:translate(-50%,-50%);
width:20px; height:20px; border-radius:50%;
background:#fff; border:3px solid rgba(0,0,0,.5);
box-shadow: 0 0 0 2px rgba(255,255,255,.6), 0 3px 8px rgba(0,0,0,.55);
}
.lcd-align-arc { font-size:15px; font-weight:500; margin-top:7px; }
.lcd-arc-note { font-size:14px; color:var(--subtext); font-style:italic; margin-top:5px; line-height:1.6; }
/* Two-column section grid */
.lcd-sections { display:grid; grid-template-columns:1fr 1fr; }
@media (max-width:620px) { .lcd-sections { grid-template-columns:1fr; } }
.lcd-section {
padding:22px 28px; border-bottom:1px solid var(--border);
background: var(--surface);
}
.lcd-section:nth-child(odd) { border-right:1px solid var(--border); }
/* Alternating panel rows */
.lcd-section:nth-child(4n+1),
.lcd-section:nth-child(4n+2) { background: var(--panel); }
.lcd-section-full {
padding:22px 28px; border-bottom:1px solid var(--border);
background: var(--surface);
}
.lcd-section-full:nth-child(even) { background: var(--panel); }
.lcd-empty-note {
display: flex; align-items: center; gap: 10px;
color: var(--subtext); font-size: 14px; font-style: italic;
}
.lcd-empty-note .mdi { font-size: 20px; opacity: .7; }
.lcd-section-label {
font-size:11px; font-weight:700; letter-spacing:.9px; text-transform:uppercase;
color:var(--accent); margin-bottom:14px; display:flex; align-items:center; gap:7px;
}
/* Generation Prompts section: four fold-out "ready to copy" boxes */
.lcd-prompts-section .lcd-section-label { justify-content: space-between; }
.lcd-prompts-section .lcd-gen-prompts { margin-left: auto; text-transform: none; letter-spacing: 0; }
.lcd-prompt-box {
border: 1px solid var(--border); border-radius: 8px; background: var(--surface);
margin-bottom: 8px; overflow: hidden;
}
.lcd-prompt-box summary {
cursor: pointer; padding: 9px 12px; font-size: 12.5px; font-weight: 700; color: var(--text);
list-style: none; display: flex; align-items: center; gap: 6px; user-select: none;
}
.lcd-prompt-box summary::before { content: ''; font-size: 15px; color: var(--subtext); transition: transform .15s; }
.lcd-prompt-box[open] summary::before { transform: rotate(90deg); }
.lcd-prompt-box summary:hover { background: var(--panel); }
.lcd-prompt-empty { font-weight: 400; font-size: 11px; color: var(--subtext); font-style: italic; }
.lcd-prompt-body { padding: 0 12px 10px; display: flex; flex-direction: column; gap: 8px; }
.cs-concept-art-preview { border-radius: 8px; overflow: hidden; border: 1px solid var(--border); }
.cs-concept-art-preview img { display: block; width: 100%; height: auto; }
.lcd-prompt-text {
white-space: pre-wrap; font-size: 12.5px; line-height: 1.55; color: var(--text);
background: var(--panel); border: 1px solid var(--border); border-radius: 6px;
padding: 8px 10px; min-height: 40px; outline: none;
}
.lcd-prompt-text:focus { border-color: var(--accent); }
.lcd-prompt-actions { display: flex; gap: 6px; justify-content: flex-end; }
.lcd-field { margin-bottom:16px; }
.lcd-field:last-child { margin-bottom:0; }
/* Compact list row — label left, value right, thin separator — used inside
the grouped 2-column sections for a scannable list feel instead of the
more spacious stacked .lcd-field blocks. */
.lcd-row {
display: grid; grid-template-columns: minmax(88px, auto) 1fr; gap: 10px;
padding: 7px 0; border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
font-size: 13.5px;
}
.lcd-row:last-child { border-bottom: none; }
.lcd-row.lcd-row-full { grid-template-columns: 1fr; }
.lcd-row dt {
font-weight: 800; color: var(--subtext); text-transform: uppercase;
font-size: 10px; letter-spacing: .05em; line-height: 1.4;
}
.lcd-row dd { margin: 0; color: var(--text); line-height: 1.5; }
.lcd-row dd .cs-source-mark { margin-left: 6px; vertical-align: middle; }
.lcd-field-label {
font-size:11px; font-weight:700; color:var(--subtext); text-transform:uppercase;
letter-spacing:.5px; margin-bottom:5px;
}
.lcd-field-value { font-size:15px; line-height:1.65; color:var(--text); white-space:pre-wrap; }
.lcd-rels-dots { display:flex; flex-wrap:wrap; gap:8px; margin-top:10px; }
.lcd-rel-dot {
width:36px; height:36px; border-radius:50%; display:inline-flex; align-items:center;
justify-content:center; font-size:14px; font-weight:700; color:#fff;
border:2px solid rgba(255,255,255,.18); box-shadow:0 3px 7px rgba(0,0,0,.35);
cursor:default;
}
.lcd-voice-section {
padding:22px 28px 28px; background:var(--panel);
}
.lcd-voice-row { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-top:10px; }
.lcd-voice-label { font-size:15px; flex:1; min-width:140px; }
.lcd-voice-row button {
font-size:13px; padding:6px 16px; border-radius:7px; cursor:pointer;
border:1px solid var(--border); background:var(--surface); color:var(--text);
transition:background .12s, border-color .12s, color .12s;
}
.lcd-pick-voice:hover { border-color:var(--accent); color:var(--accent); }
.lcd-auto-voice:hover { border-color:var(--green,#22c55e); color:var(--green,#22c55e); }
.lcd-online-voice:hover { border-color:#0ea5e9; color:#0ea5e9; }
.lcd-gen-voice:hover { border-color:#a855f7; color:#a855f7; }
.lcd-analysis {
background:var(--panel); border-top:1px solid var(--border);
padding:20px 28px; font-size:14px; line-height:1.7; color:var(--subtext); white-space:pre-wrap;
}
/* Voice section at top of modal body */
.lcd-voice-top {
padding:20px 28px 18px; border-bottom:1px solid var(--border);
background:var(--surface); display:flex; align-items:center; gap:12px; flex-wrap:wrap;
}
.lcd-voice-top .lcd-section-label { margin-bottom:0; flex-shrink:0; }
.lcd-voice-top .lcd-voice-label { font-size:14px; flex:1; min-width:120px; }
.lcd-voice-top button {
font-size:13px; padding:6px 16px; border-radius:7px; cursor:pointer;
border:1px solid var(--border); background:var(--panel); color:var(--text);
transition:background .12s, border-color .12s, color .12s;
}
.lcd-voice-top .lcd-pick-voice:hover { border-color:var(--accent); color:var(--accent); }
.lcd-voice-top .lcd-auto-voice:hover { border-color:var(--green,#22c55e); color:var(--green,#22c55e); }
.lcd-voice-top .lcd-online-voice:hover { border-color:#0ea5e9; color:#0ea5e9; }
.lcd-voice-top .lcd-gen-voice:hover { border-color:#a855f7; color:#a855f7; }
/* Sources section */
.lcd-sources {
padding:20px 28px; background:var(--panel); border-top:1px solid var(--border);
}
.lcd-source-list { display:flex; flex-direction:column; gap:8px; margin-top:10px; }
.lcd-source-item {
background:var(--surface); border:1px solid var(--border); border-radius:8px;
padding:10px 14px;
}
.lcd-source-page { font-size:11px; font-weight:700; color:var(--accent); margin-bottom:4px; text-transform:uppercase; letter-spacing:.4px; }
.lcd-source-quote { font-size:13px; line-height:1.55; color:var(--text); font-style:italic; }
.lcd-source-hint { font-size:11px; color:var(--subtext); margin-top:3px; }
.lcd-sources-hint { font-size:10px; opacity:.45; font-weight:400; letter-spacing:0; }
.lcd-source-clickable { cursor:pointer; transition:background .12s, border-color .12s; }
.lcd-source-clickable:hover { background:rgba(var(--accent-rgb,124,106,247),.12); border-color:var(--accent); }
/* ── Character detail page (full-page layout, no modal) ─────────────────── */
/*
Fixed height so each panel scrolls independently.
The outer content wrapper already has overflow-y:auto (line ~284),
so sticky doesn't work inside it. Instead we give .lib-char-page a
real viewport height and let each column overflow internally.
*/
.lib-char-page {
display:flex; flex-direction:row;
height:calc(100dvh - 148px); /* viewport minus app header + section tabs */
min-height:400px; overflow:hidden;
}
.lib-cpg-main { flex:1; overflow-y:auto; min-width:0; padding-bottom:60px; }
.lib-cpg-back {
display:inline-flex; align-items:center; gap:6px;
background:none; border:none; cursor:pointer; color:var(--accent);
font-size:13px; padding:14px 20px 8px; opacity:.8;
}
.lib-cpg-back:hover { opacity:1; }
/* Remove the outer box from the modal — header fills edge-to-edge */
.lib-char-page .lcd-header { border-radius:0; }
.lib-char-page .lcd-body { padding:0; }
/* Inline-editable fields inside the detail page */
.lcd-field-editable {
outline:none; border-radius:4px; cursor:text;
padding:2px 5px; margin:-2px -5px;
transition:background .15s, box-shadow .15s;
min-height:1.2em;
}
.lcd-field-editable:hover { background:rgba(255,255,255,.05); }
.lcd-field-editable:focus { background:rgba(255,255,255,.09); box-shadow:inset 0 -2px 0 var(--accent); }
/* Same treatment for the live casting card's own pencil-toggle editing —
only actionable once the card is in edit mode (contenteditable="true"). */
.cs-field-editable[contenteditable="true"] {
outline:none; border-radius:4px; cursor:text;
padding:2px 5px; margin:-2px -5px; display:inline-block;
transition:background .15s, box-shadow .15s;
}
.cs-field-editable[contenteditable="true"]:hover { background:rgba(var(--accent-rgb,124,106,247),.08); }
.cs-field-editable[contenteditable="true"]:focus { background:rgba(var(--accent-rgb,124,106,247),.14); box-shadow:inset 0 -2px 0 var(--accent); }
/* Header name/aliases/archetype editable */
.lcd-header [contenteditable] { outline:none; cursor:text; }
.lcd-header [contenteditable]:hover { text-decoration:underline; text-underline-offset:3px; text-decoration-style:dotted; }
.lcd-header [contenteditable]:focus { text-decoration:none; background:rgba(0,0,0,.2); border-radius:4px; padding:0 4px; }
/* Alignment slider */
.lcd-align-slider { flex:1; height:6px; accent-color:var(--accent,#7c6af7); cursor:pointer; }
.lcd-align-slider-val { font-size:13px; font-weight:600; opacity:.7; flex-shrink:0; min-width:48px; text-align:right; }
/* Right sidebar — independent scroll, no sticky needed (fixed-height parent) */
.lib-cpg-sidebar {
width:240px; flex-shrink:0;
border-left:3px solid var(--border);
box-shadow:-4px 0 12px rgba(0,0,0,.18);
overflow-y:auto; background:var(--panel);
}
.lib-cpg-sidebar-title {
padding:12px 14px 8px; font-size:10px; font-weight:700;
letter-spacing:.07em; text-transform:uppercase; opacity:.45; border-bottom:1px solid var(--border);
}
.lib-cpg-sidebar-item {
display:flex; align-items:center; gap:9px; padding:8px 12px;
cursor:pointer; transition:background .12s; border-bottom:1px solid rgba(255,255,255,.03);
}
.lib-cpg-sidebar-item:hover, .lib-cpg-sidebar-item.is-active { background:var(--surface); }
.lib-cpg-sidebar-item.is-active { border-left:2px solid var(--accent); padding-left:10px; }
.lib-cpg-sidebar-dot {
width:26px; height:26px; border-radius:50%; flex-shrink:0;
display:flex; align-items:center; justify-content:center;
font-size:11px; font-weight:700; color:#fff;
}
.lib-cpg-sidebar-name { flex:1; font-size:12px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.lib-cpg-sidebar-count { font-size:11px; opacity:.4; flex-shrink:0; }
/* Voice picker popup */
.lib-voice-picker-popup {
/* position/left/top/bottom/width set inline in JS (fixed, anchored via
getBoundingClientRect) — see _openVoicePicker */
z-index:500;
background: var(--surface); border:1px solid var(--border); border-radius:8px;
box-shadow: 0 8px 24px rgba(0,0,0,.25); overflow:hidden; max-height:280px;
display:flex; flex-direction:column;
}
.lib-vp-search { padding:8px; border-bottom:1px solid var(--border); }
.lib-vp-quick { padding:0 8px 8px; border-bottom:1px solid var(--border); }
.lib-vp-design-btn {
width:100%; display:flex; align-items:center; justify-content:center; gap:6px;
padding:7px; border-radius:6px; border:1px dashed var(--accent); background:none;
color:var(--accent); font-size:12px; font-weight:600; cursor:pointer;
transition:background .12s;
}
.lib-vp-design-btn:hover { background:rgba(var(--accent-rgb,124,106,247),.1); }
.lib-vp-input { width:100%; box-sizing:border-box; background:var(--panel); border:1px solid var(--border);
border-radius:6px; padding:5px 9px; font-size:12px; color:var(--text); outline:none; }
.lib-vp-input:focus { border-color:var(--accent); }
.lib-vp-list { overflow-y:auto; flex:1; }
.lib-vp-item { padding:7px 12px; font-size:12px; cursor:pointer; transition:background .1s; }
.lib-vp-item:hover { background:var(--panel); }
.lib-vp-item.selected { color:var(--accent); font-weight:600; }
/* Character production tags */
.cl-card-tags { display:flex; flex-wrap:wrap; gap:4px; margin-top:8px; }
.cl-tag-chip {
display:inline-flex; align-items:center; gap:3px; padding:2px 8px;
border-radius:10px; background:var(--chip-bg, rgba(127,127,127,.16));
color:var(--subtext); font-size:11px; font-weight:500;
}
.cl-tag-chip .mdi { font-size:12px; opacity:.7; }
.lib-char-tags { display:flex; flex-wrap:wrap; gap:4px; margin:4px 0; }
/* Page card head */
.s-page-head { border-bottom:1px solid var(--border); padding-bottom:14px; }
.s-page-head h3 { font-size:16px; font-weight:700; margin:0 0 4px; color:var(--text); }
.s-page-head p { font-size:13px; color:var(--subtext); margin:0; line-height:1.5; }
.s-page-head-row { display:flex; justify-content:space-between; align-items:flex-start; gap:16px; }
.s-stack-badge { display:inline-flex; align-items:center; gap:5px; border:1px solid color-mix(in srgb,var(--green) 40%,transparent); background:rgba(22,163,74,.07); color:#166534; border-radius:999px; padding:5px 11px; font-size:12px; font-weight:600; white-space:nowrap; flex-shrink:0; }
/* Groups */
.s-group { display:flex; flex-direction:column; gap:14px; }
.s-group + .s-group { border-top:1px solid var(--border); padding-top:18px; }
.s-group-head { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; }
.s-group-head strong { font-size:14px; font-weight:600; color:var(--text); }
.s-group-head span { font-size:12px; color:var(--subtext); }
/* Field grids */
.settings-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(280px,1fr)); gap:16px; }
.settings-grid.three { grid-template-columns:repeat(auto-fit, minmax(240px,1fr)); }
.settings-grid.compact { grid-template-columns:repeat(2, minmax(220px,1fr)); gap:14px; }
.settings-behavior-grid { grid-template-columns:minmax(220px,.6fr) minmax(220px,.6fr); gap:16px; align-items:start; }
.settings-param-grid textarea { min-height:58px; }
/* Fields */
.s-field { display:flex; flex-direction:column; gap:6px; }
.s-field label { font-size:13px; color:var(--text); font-weight:500; }
.s-label-note { font-weight:400; color:var(--subtext); }
.s-field input, .s-field select, .s-field textarea { background:var(--panel); border:1px solid var(--border); color:var(--text); border-radius:var(--radius); padding:9px 12px; font-size:14px; transition:border-color .15s,box-shadow .15s; width:100%; box-sizing:border-box; }
.s-field input:focus, .s-field select:focus, .s-field textarea:focus { border-color:var(--accent); outline:none; box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 12%,transparent); }
.s-field textarea { min-height:76px; resize:vertical; font-family:monospace; }
.s-hint { font-size:12px; color:var(--subtext); line-height:1.5; }
.s-key-row { display:flex; gap:6px; }
.s-key-row input { flex:1; }
.s-eye-btn { background:var(--panel); border:1px solid var(--border); color:var(--subtext); border-radius:var(--radius); padding:0 13px; font-size:15px; cursor:pointer; flex-shrink:0; transition:color .15s; }
.s-eye-btn:hover { color:var(--text); }
.settings-guide { display: grid; grid-template-columns: 34px minmax(0,1fr); gap: 12px; align-items: start; margin: 14px 0 4px; padding: 12px 14px; border: 1px solid color-mix(in srgb, var(--accent) 24%, var(--border)); border-radius: 8px; background: color-mix(in srgb, var(--accent) 6%, var(--surface)); }
.settings-guide-icon { width: 34px; height: 34px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center; color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); font-size: 18px; }
.settings-guide-body { min-width: 0; }
.settings-guide-body strong { display: block; font-size: 13px; color: var(--text); margin-bottom: 3px; }
.settings-guide-body p { margin: 0; color: var(--subtext); font-size: 12px; line-height: 1.5; }
.settings-guide-body ul { margin: 7px 0 0; padding-left: 18px; color: var(--subtext); font-size: 12px; line-height: 1.55; }
.s-field label { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.s-help-tip { position: relative; display: inline-flex; align-items: center; }
.s-help-tip button { width: 18px; height: 18px; border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border)); border-radius: 50%; background: color-mix(in srgb, var(--accent) 7%, var(--panel)); color: var(--accent); display: inline-flex; align-items: center; justify-content: center; padding: 0; cursor: help; font-size: 12px; line-height: 1; }
.s-help-tip button:hover, .s-help-tip button:focus-visible { background: var(--accent); color: #fff; }
.s-tooltip { position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%) translateY(3px); width: min(300px, calc(100vw - 40px)); padding: 9px 10px; border-radius: 7px; background: var(--text); color: var(--bg); font-size: 12px; line-height: 1.45; font-weight: 500; box-shadow: var(--shadow); opacity: 0; pointer-events: none; z-index: 250; transition: opacity .14s ease, transform .14s ease; }
.s-tooltip::after { content: ''; position: absolute; left: 50%; top: 100%; transform: translateX(-50%); border: 6px solid transparent; border-top-color: var(--text); }
.s-help-tip:hover .s-tooltip, .s-help-tip:focus-within .s-tooltip { opacity: 1; transform: translateX(-50%) translateY(0); }
.s-field-tip { display: block; border-left: 3px solid color-mix(in srgb, var(--accent) 32%, var(--border)); padding: 6px 9px; border-radius: 0 6px 6px 0; background: color-mix(in srgb, var(--accent) 4%, var(--panel)); color: var(--subtext); font-size: 12px; line-height: 1.45; }
.s-field:focus-within .s-field-tip { color: var(--text); background: color-mix(in srgb, var(--accent) 7%, var(--panel)); border-left-color: var(--accent); }
.s-page-actions { position: sticky; bottom: 0; background: color-mix(in srgb, var(--surface) 94%, transparent); backdrop-filter: blur(8px); margin: 0 -2px -2px; padding: 14px 2px 2px; z-index: 5; }
@media (max-width: 700px) { .settings-guide { grid-template-columns: 1fr; } .settings-guide-icon { display: none; } .s-tooltip { display: none; } }
/* STT layout */
.stt-settings-grid { grid-template-columns:minmax(320px,.65fr) minmax(240px,1fr); }
.settings-mini-actions { margin-top:4px; gap:8px; flex-wrap:wrap; }
.settings-mini-actions button { min-height:32px; padding:6px 11px; font-size:12px; }
/* Captures toggle grid */
.s-toggle-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(240px,1fr)); gap:10px; }
.s-toggle-row { display:flex; align-items:flex-start; gap:12px; cursor:pointer; padding:10px 12px; border:1px solid var(--border); border-radius:var(--radius); background:var(--panel); transition:border-color .15s; }
.s-toggle-row:hover { border-color:var(--accent); }
.s-toggle-row input[type="checkbox"] { margin-top:2px; flex-shrink:0; accent-color:var(--accent); width:16px; height:16px; cursor:pointer; }
.s-toggle-title { display:block; font-size:13px; font-weight:600; color:var(--text); margin-bottom:2px; }
.s-toggle-row .s-hint { display:block; margin:0; }
/* Page save/reload actions */
.s-page-actions { border-top:1px solid var(--border); padding-top:14px; display:flex; gap:10px; }
.s-page-actions button { min-width:120px; }
/* Log viewer */
.s-log-toolbar { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.s-log-live-label { display:inline-flex; align-items:center; gap:6px; font-size:13px; color:var(--subtext); cursor:pointer; padding:0 4px; }
.s-log-live-label input { accent-color:var(--accent); cursor:pointer; }
.s-log-count { font-size:12px; color:var(--subtext); margin-left:auto; }
.s-log-filters { display:flex; gap:6px; flex-wrap:wrap; }
.s-log-filter { border:1px solid var(--border); background:transparent; color:var(--subtext); border-radius:999px; padding:3px 10px; font-size:12px; cursor:pointer; transition:all .15s; }
.s-log-filter:hover { border-color:var(--accent); color:var(--accent); }
.s-log-filter.is-active { background:var(--accent); border-color:var(--accent); color:#fff; }
.s-log-viewer { background:var(--panel); border:1px solid var(--border); border-radius:var(--radius); padding:12px 14px; font-family:monospace; font-size:12px; line-height:1.6; max-height:75vh; overflow-y:auto; display:flex; flex-direction:column; gap:1px; }
.s-log-empty { color:var(--subtext); font-family:inherit; text-align:center; padding:24px 0; }
.s-log-row { display:grid; grid-template-columns:max-content max-content 1fr; gap:12px; align-items:baseline; padding:2px 0; border-bottom:1px solid color-mix(in srgb,var(--border) 50%,transparent); }
.s-log-row:last-child { border-bottom:none; }
.s-log-ts { color:var(--subtext); font-size:11px; white-space:nowrap; }
.s-log-level { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; }
.s-log-level.ERROR, .s-log-level.CRITICAL { color:var(--red); }
.s-log-level.WARNING { color:#f59e0b; }
.s-log-level.INFO { color:var(--accent); }
.s-log-level.DEBUG { color:var(--subtext); }
.s-log-msg { color:var(--text); word-break:break-all; }
/* About */
.s-about-block { display:flex; flex-direction:column; gap:14px; max-width:640px; }
.s-about-name { font-size:20px; font-weight:700; color:var(--text); display:flex; align-items:center; gap:8px; }
.s-about-name .mdi { font-size:22px; color:var(--accent); }
.s-about-desc { font-size:14px; color:var(--subtext); line-height:1.65; margin:0; }
.s-about-stack { display:flex; flex-wrap:wrap; gap:8px; }
.s-about-chip { display:inline-flex; align-items:center; gap:5px; background:var(--panel); border:1px solid var(--border); border-radius:var(--radius); padding:4px 10px; font-size:12px; color:var(--subtext); }
.s-about-backends { display:flex; flex-wrap:wrap; gap:8px; margin-top:4px; }
.s-about-backend { display:inline-flex; align-items:center; gap:6px; border:1px solid var(--border); border-radius:var(--radius); padding:5px 10px; font-size:12px; color:var(--subtext); }
.s-about-backend.online { border-color:color-mix(in srgb,var(--green) 50%,transparent); color:var(--green); }
.s-about-backend.offline { opacity:.55; }
.s-about-backend .mdi { font-size:11px; }
/* Responsive */
@media (max-width:1100px) { .settings-grid.compact { grid-template-columns:1fr; } .settings-behavior-grid { grid-template-columns:1fr; } }
@media (max-width:900px) { .stt-settings-grid { grid-template-columns:1fr; } }
/* Accessibility helpers */
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.skip-link { position: fixed; left: 12px; top: 12px; z-index: 6000; transform: translateY(-160%); background: var(--accent); color: #fff; padding: 9px 13px; border-radius: 7px; font-weight: 800; box-shadow: var(--shadow); }
.skip-link:focus { transform: translateY(0); outline: 3px solid #fff; outline-offset: 2px; }
button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible, .nav-item:focus-visible, .nav-tree-item:focus-visible { outline: 3px solid color-mix(in srgb, var(--accent) 78%, white); outline-offset: 2px; }
/* ── Toast ──────────────────────────────────────────────────────────────── */
#toast { position: fixed; top: 50%; left: 50%; background: var(--surface); border: 2px solid var(--accent); border-left-width: 8px; color: var(--text); padding: 16px 20px; border-radius: 8px; font-size: 15px; font-weight: 700; opacity: 0; transform: translate(-50%, calc(-50% + 12px)) scale(.98); transition: opacity .18s, transform .18s; pointer-events: none; z-index: 5000; max-width: min(520px, calc(100vw - 40px)); min-width: min(360px, calc(100vw - 40px)); box-shadow: 0 20px 70px rgba(0,0,0,.35); text-align: center; }
#toast.show { opacity: 1; transform: translate(-50%, -50%) scale(1); }
#toast.success { border-color: var(--green); color: var(--green); }
#toast.error { border-color: var(--red); color: var(--red); }
#toast.info { border-color: var(--accent); color: var(--accent); }
/* ── Status bar ─────────────────────────────────────────────────────────── */
#status-bar {
background: var(--surface); border-top: 1px solid var(--border);
padding: 4px 18px; font-size: 12px; color: var(--subtext);
min-height: 24px; flex-shrink: 0;
display: flex; align-items: center; gap: 16px; min-width: 0;
}
#status-message { flex: 0 1 auto; min-width: 120px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#status-engines {
margin-left: auto; min-width: 0; display: flex; align-items: center;
justify-content: flex-end; gap: 16px; overflow: hidden;
}
.status-engine {
min-width: 0; display: inline-flex; align-items: center; gap: 5px;
white-space: nowrap; color: var(--subtext);
background: none; border: none; padding: 2px 4px; margin: 0; border-radius: 4px;
font: inherit; cursor: pointer;
}
.status-engine:hover { background: var(--panel); color: var(--text); }
.status-engine-caret { font-size: 13px; opacity: .55; }
.status-dot {
width: 11px; height: 11px; border-radius: 50%; flex: 0 0 auto;
background: var(--red); box-shadow: 0 0 0 2px color-mix(in srgb, var(--red) 14%, transparent);
}
.status-engine.ok .status-dot { background: var(--green); box-shadow: 0 0 0 2px color-mix(in srgb, var(--green) 16%, transparent); }
.status-engine-label { font-weight: 800; color: var(--text); }
.status-engine-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; max-width: min(34vw, 420px); }
.status-engine.bad .status-engine-value { color: var(--red); }
/* Fly-up menu opened by clicking a footer engine chip — quick-switch the
active LLM model / STT backend / TTS backend without opening Settings. */
.status-flyup {
position: fixed; z-index: 2000; min-width: 200px; max-width: 320px;
max-height: 320px; display: flex; flex-direction: column;
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
box-shadow: 0 -8px 24px rgba(0,0,0,.18); padding: 4px;
}
.status-flyup-search {
display: flex; align-items: center; gap: 6px; padding: 4px 8px 6px;
border-bottom: 1px solid var(--border); margin-bottom: 4px; flex-shrink: 0;
}
.status-flyup-search .mdi { font-size: 14px; color: var(--subtext); flex-shrink: 0; }
.status-flyup-search input {
flex: 1; min-width: 0; border: none; background: none; outline: none;
font-size: 12.5px; color: var(--text); font-family: inherit;
}
.status-flyup-list { overflow-y: auto; }
.status-flyup-item {
display: flex; align-items: center; gap: 6px; width: 100%; text-align: left;
padding: 7px 10px; border: none; background: none; border-radius: 6px;
font-size: 12.5px; color: var(--text); cursor: pointer;
}
.status-flyup-item:hover { background: var(--panel); }
.status-flyup-item.is-active { color: var(--accent); font-weight: 700; }
.status-flyup-item .mdi { font-size: 14px; flex-shrink: 0; }
.status-flyup-empty { padding: 10px 12px; font-size: 12px; color: var(--subtext); font-style: italic; }
@media (max-width: 820px) {
#status-bar { align-items: flex-start; flex-direction: column; gap: 4px; }
#status-engines { margin-left: 0; width: 100%; justify-content: flex-start; flex-wrap: wrap; gap: 8px 14px; }
.status-engine-value { max-width: 72vw; }
}
.info-box { background: var(--panel); border-radius: var(--radius); padding: 12px 16px; font-family: monospace; font-size: 13px; color: var(--accent); word-break: break-all; }
hr { border: none; border-top: 1px solid var(--border); }
.note { font-size: 13px; color: var(--subtext); line-height: 1.5; }
code { background: var(--panel); border-radius: 4px; padding: 1px 5px; font-family: monospace; font-size: 12px; }
/* ── Library ────────────────────────────────────────────────────────────── */
.lib-toolbar { display: flex; align-items: center; gap: 12px; min-height: 34px; margin-bottom: 6px; }
.lib-toolbar h2 { flex: 0 0 auto; }
.lib-toolbar .spacer { flex: 1 1 auto; }
.show-disabled-control { font-size: 13px; color: var(--subtext); display:flex; align-items:center; gap:7px; cursor:pointer; white-space:nowrap; }
.loading-panel { min-height: 170px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--border); border-radius: 6px; background: var(--panel); color: var(--subtext); padding: 18px; }
.loading-box { width: min(680px,100%); display: flex; flex-direction: column; gap: 13px; }
.loading-head { display: flex; align-items: center; gap: 10px; color: var(--text); font-weight: 700; font-size: 14px; }
.spinner { width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--border); border-top-color: var(--accent); animation: spin .8s linear infinite; flex: 0 0 auto; }
@keyframes spin { to { transform: rotate(360deg); } }
.loading-sub { font-size: 13px; line-height: 1.4; }
.skeleton-stack { display: flex; flex-direction: column; gap: 8px; }
.skeleton-row { height: 38px; border-radius: 6px; border: 1px solid var(--border); background: linear-gradient(90deg, var(--panel), rgba(37,99,235,.06), var(--panel)); background-size: 220% 100%; animation: skeletonSweep 1.15s ease-in-out infinite; }
@keyframes skeletonSweep { 0% { background-position: 120% 0; } 100% { background-position: -120% 0; } }
.library-benchmark-panel { display: none !important; }
.library-benchmark-panel .field { min-width: 0; }
#benchmark-sample-text { min-height: 62px; resize: vertical; background: var(--panel); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); padding: 10px 14px; font-size: 14px; font-family: inherit; width: 100%; }
.benchmark-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.volume-actions { align-items: flex-end; }
.target-db-field { display: flex; flex-direction: column; gap: 4px; flex: 0 0 112px; color: var(--subtext); font-size: 14px; text-transform: uppercase; letter-spacing: .06em; }
.target-db-field input { width: 112px; background: var(--panel); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); padding: 8px 10px; font-size: 14px; }
.play-mode-field select { width: 100%; }
.benchmark-progress { margin-top: 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); display: flex; flex-direction: column; gap: 7px; }
.benchmark-progress[hidden] { display: none; }
.benchmark-progress-head { display: flex; justify-content: space-between; gap: 12px; color: var(--subtext); font-size: 13px; }
#benchmark-progress-label { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.benchmark-progress-track { height: 8px; background: var(--bg); border-radius: 999px; overflow: hidden; border: 1px solid var(--border); }
#benchmark-progress-bar { height: 100%; width: 0%; background: var(--accent); transition: width .2s ease; }
.benchmark-live-stats { display: grid; grid-template-columns: repeat(6, minmax(72px,1fr)); gap: 6px; font-size: 12px; color: var(--subtext); }
.benchmark-live-stats span { border: 1px solid var(--border); border-radius: 5px; padding: 5px 7px; background: var(--bg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.benchmark-live-last { min-height: 1.3em; font-size: 12px; color: var(--subtext); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.library-insights { display: grid; grid-template-columns: repeat(6, minmax(100px,1fr)); gap: 6px; margin-top: 5px; }
.insight { border: 1px solid var(--border); border-radius: 6px; background: var(--panel); min-height: 30px; padding: 5px 9px; display:flex; align-items:baseline; gap:8px; }
.insight[data-filter] { cursor: pointer; }
.insight[data-filter]:hover, .insight.active { border-color: var(--accent); background: rgba(37,99,235,.08); }
.insight strong { display: block; color: var(--text); font-size: 14px; line-height: 1.1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width:0; }
.insight span { display: block; color: var(--subtext); font-size: 10px; text-transform: uppercase; letter-spacing: .06em; margin-top: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width:0; line-height: 1.1; }
.library-filter-note { border: 1px solid var(--border); border-radius: 6px; background: rgba(37,99,235,.05); color: var(--subtext); padding: 8px 10px; font-size: 13px; display: flex; justify-content: space-between; align-items: center; gap: 10px; margin: 8px 0; }
.library-filter-note strong { color: var(--text); }
.library-filter-note button { flex: 0 0 auto; }
.library-control-panel { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; align-items: end; padding: 12px; border: 1px solid var(--border); border-radius: 7px; background: rgba(37,99,235,.035); }
.library-control-panel .field { min-width: 0; }
.library-control-panel input, .library-control-panel select { width: 100%; background: var(--panel); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); padding: 8px 10px; }
.library-list-title { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 8px 2px 8px; color: var(--subtext); font-size: 12px; text-transform: uppercase; letter-spacing: .08em; font-weight: 800; }
.library-list-title strong { color: var(--text); font-size: 13px; }
.library-action-row { display: grid; grid-template-columns: auto 1fr auto auto; gap: 8px; align-items: center; margin: 8px 0 12px; }
.voice-action-group { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.voice-action-group button { min-height: 34px; padding: 7px 12px; white-space: nowrap; }
.action-add { grid-column: 1; }
.action-refresh { grid-column: 2; justify-content: flex-start; }
.action-refresh button { flex: 0 0 auto; }
.action-db { display: none; }
.action-benchmark { display: none; }
.action-copy { display: none; }
.action-show-disabled { grid-column: 4; justify-self: end; align-self: center; min-height: 34px; padding: 0 4px; margin: 0; }
.benchmark-confirm { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 10px 0 0 132px; padding: 10px 12px; max-width: 760px; border: 1px solid rgba(217,119,6,.45); border-radius: 7px; background: rgba(217,119,6,.07); color: var(--text); box-shadow: var(--shadow); }
.benchmark-confirm[hidden] { display: none; }
.benchmark-confirm strong { color: var(--yellow); font-size: 13px; }
.benchmark-confirm span { color: var(--subtext); font-size: 13px; line-height: 1.35; flex: 1 1 260px; }
.benchmark-confirm button { white-space: nowrap; }
.benchmark-confirm .benchmark-confirm-start { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.disabled-info { background: rgba(37,99,235,.06); border: 1px solid var(--border); border-radius: var(--radius); padding: 11px 15px; font-size: 13px; color: var(--subtext); line-height: 1.6; }
.disabled-info strong { color: var(--text); }
/* Voice list rows - Card grid layout */
.vl-grid { display: grid; grid-template-columns: repeat(2, minmax(320px, 1fr)); gap: 16px; padding: 12px 0; }
.vl-header { display: none; }
.vl-row { position: relative; padding: 16px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); transition: all .2s; display: flex; flex-direction: column; gap: 12px; }
.vl-row:hover { border-color: var(--accent); background: rgba(37,99,235,.02); box-shadow: 0 8px 24px rgba(37,99,235,.15); transform: translateY(-2px); }
.vl-row.vr-disabled { opacity: .42; }
.vl-row.edit-open { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(37,99,235,.15); }
.vr-main-row { display: flex; flex-direction: column; gap: 12px; width: 100%; }
.vr-photo { width: 100%; height: 200px; border-radius: 12px; overflow: hidden; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); position: relative; display: flex; align-items: center; justify-content: center; }
.vr-photo img { width: 100%; height: 100%; object-fit: cover; }
.vr-photo .ph-icon { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; font-size: 64px; color: white; font-weight: 700; }
.vr-photo:hover::after { content: ''; }
.vr-photo.drag-over { opacity: 0.8; outline: 3px dashed var(--accent); outline-offset: -4px; transition: all 0.2s; }
.vr-identity { display: flex; gap: 10px; align-items: center; min-width: 0; width: 100%; }
.vr-flag { display: none; }
.vr-flag .flag-emoji { font-size: 22px; line-height: 1; transition: transform .15s; }
.vr-flag .flag-code { font-size: 10px; font-family: monospace; font-weight: 700; color: var(--subtext); letter-spacing: .04em; }
.vr-flag:hover .flag-emoji { transform: scale(1.18); }
.flag-picker { display: none; }
.vr-gender { display: none; }
.gender-badge { display: inline-flex; align-items: center; gap: 5px; border-radius: 6px; padding: 4px 10px; background: rgba(37,99,235,.08); border: 1px solid rgba(37,99,235,.18); cursor: pointer; transition: border-color .15s, background .15s; font-size: 13px; font-weight: 600; }
.gender-badge:hover { background: rgba(37,99,235,.14); border-color: var(--accent); }
.gender-sym { font-size: 14px; line-height: 1; }
.gender-txt { font-size: 12px; font-weight: 600; letter-spacing: .01em; }
.g-f { color: #e91e8c; }
.g-m { color: #0ea5e9; }
.g-n { color: #8b5cf6; }
.vr-name { display: flex; align-items: center; gap: 4px; min-width: 0; flex: 1; }
.vr-name-text { font-weight: 800; color: var(--text); font-family: inherit; font-size: 15px; overflow: hidden; text-overflow: ellipsis; flex: 1; cursor: text; white-space: nowrap; }
.vr-name-input { flex: 1; background: var(--bg); border: 1px solid var(--accent); color: var(--text); border-radius: 4px; padding: 4px 8px; font-size: 13px; font-family: monospace; min-width: 0; }
.icon-btn { background: none; border: none; padding: 3px 5px; font-size: 14px; color: var(--subtext); border-radius: 4px; cursor: pointer; flex-shrink: 0; }
.icon-btn:hover { background: var(--border); color: var(--text); }
.rename-confirm { display: none; gap: 3px; }
.rename-confirm.show { display: flex; }
.vr-type { display: none; }
.vr-length { display: none; }
.vr-db { display: none; }
.vr-bench { display: none; }
.vr-edit { display: flex; justify-content: flex-end; }
.edit-audio-btn { width: 38px; height: 34px; border-radius: 7px; padding: 0; background: rgba(37,99,235,.10); border: 1px solid var(--border); color: var(--accent); font-size: 22px; line-height: 1; display: flex; align-items: center; justify-content: center; }
.edit-audio-btn:hover { border-color: var(--accent); background: rgba(37,99,235,.18); filter: none; }
.benchmark-one-btn { width: 26px; height: 26px; border-radius: 6px; padding: 0; font-size: 12px; }
.vr-rating { display: flex; gap: 2px; font-size: 18px; justify-content: flex-start; align-items: center; min-height: 31px; }
.star { cursor: pointer; color: var(--border); transition: color .1s; }
.star.on { color: var(--yellow); }
.vr-rating:hover .star { color: var(--yellow); }
.vr-rating:hover .star ~ .star { color: var(--border); }
.vr-play { display: flex; align-items: center; justify-content: flex-start; }
.vr-play-group { display: flex; gap: 8px; align-items: center; justify-content: flex-start; }
.vr-play button { width: 40px; height: 40px; border-radius: 50%; background: var(--accent); color: var(--on-accent); font-size: 13px; display: flex; align-items: center; justify-content: center; padding: 0; }
.vr-play-synth button { background: var(--teal); }
.vr-toggle { display: flex; justify-content: center; }
.toggle { position: relative; display: inline-block; width: 42px; height: 24px; }
.toggle input { opacity: 0; width: 0; height: 0; }
.t-slider { position: absolute; cursor: pointer; inset: 0; background: var(--border); border-radius: 24px; transition: .2s; }
.t-slider::before { position: absolute; content: ''; height: 18px; width: 18px; left: 3px; bottom: 3px; background: var(--bg); border-radius: 50%; transition: .2s; }
.toggle input:checked + .t-slider { background: var(--green); }
.toggle input:checked + .t-slider::before { transform: translateX(18px); }
.vr-delete { display: flex; justify-content: flex-end; }
.delete-btn { width: 30px; height: 30px; border-radius: 6px; padding: 0; background: none; border: 1px solid transparent; font-size: 15px; color: var(--subtext); display: flex; align-items: center; justify-content: center; transition: background .15s, border-color .15s, color .15s; }
.delete-btn:hover { background: rgba(220,38,38,.12); border-color: var(--red); color: var(--red); filter: none; }
.delete-confirm { position: absolute; right: 38px; top: 16px; z-index: 20; display: none; align-items: center; gap: 8px; min-width: 270px; max-width: min(380px, calc(100vw - 80px)); padding: 8px 9px; border: 1px solid rgba(220,38,38,.45); border-radius: 7px; background: var(--surface); color: var(--text); box-shadow: var(--shadow); }
.delete-confirm strong { font-size: 12px; color: var(--red); white-space: nowrap; }
.delete-confirm span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--subtext); }
.delete-confirm button { height: 28px; padding: 0 10px; border-radius: 6px; font-size: 12px; white-space: nowrap; }
.delete-confirm .delete-confirm-go { background: rgba(220,38,38,.12); border-color: rgba(220,38,38,.45); color: var(--red); }
.vl-row.delete-pending { border-color: rgba(220,38,38,.65); }
.vl-row.delete-pending .delete-confirm { display: flex; }
.vl-row.delete-pending .delete-btn { background: rgba(220,38,38,.12); border-color: var(--red); color: var(--red); }
.vr-detail-row { display: none; }
.vr-detail-active { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; min-height: 31px; }
.vr-detail-active .vr-active-tools { justify-content: flex-end; width: 100%; }
.vr-detail-delete { display: flex; align-items: start; justify-content: flex-end; min-height: 31px; padding-top: 18px; }
.vr-active-tools { display: flex; gap: 10px; align-items: center; }
.vr-ref, .vr-note, .vr-source { display: flex; flex-direction: column; align-items: stretch; gap: 2px; }
.vr-ref .vr-inline, .vr-note .vr-inline, .vr-source .vr-inline { display: flex; gap: 6px; align-items: center; min-width: 0; }
.vr-ref input { width: 100%; min-width: 0; background: transparent; border: none; border-bottom: 1px solid transparent; color: var(--subtext); font-size: 13px; padding: 3px 5px; font-family: inherit; outline: none; }
.vr-ref input:focus { border-bottom-color: var(--accent); color: var(--text); }
.vr-ref input::placeholder { color: var(--placehld); font-style: italic; }
.ref-transcribe-btn { width: 28px; height: 28px; padding: 0; border-radius: 6px; background: none; border: 1px solid transparent; color: var(--subtext); flex-shrink: 0; font-size: 14px; }
.ref-transcribe-btn:hover { background: var(--border); color: var(--text); filter: none; }
.vr-note input, .vr-source input { width: 100%; background: transparent; border: none; border-bottom: 1px solid var(--border); color: var(--text); font-size: 13px; padding: 3px 5px; font-family: inherit; outline: none; }
.vr-note input:focus, .vr-source input:focus { border-bottom-color: var(--accent); }
.vr-note input::placeholder, .vr-source input::placeholder { color: var(--placehld); }
.vr-row-subtle { color: var(--subtext); font-size: 14px; font-family: monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vr-optimizer { grid-column: auto; display: none; margin: 6px 0 0; width: 100%; box-sizing: border-box; }
.vl-row.edit-open .vr-optimizer { display: block; }
.optimizer-grid { display: grid; grid-template-columns: minmax(280px,1.2fr) minmax(280px,1fr); gap: 12px; align-items: start; }
.opt-group { box-shadow: var(--shadow); margin-top: 20px; margin-right: 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface); padding: 10px; min-width: 0; }
.opt-group-title { font-size: 14px; font-weight: 800; color: var(--accent); text-transform: uppercase; letter-spacing: .08em;}
.opt-group-note { font-size: 12px; color: var(--subtext); line-height: 1.4; margin-top: 7px; }
.opt-compare-panel { grid-column: 1 / -1; }
.opt-compare-grid { display: grid; grid-template-columns: repeat(2, minmax(240px,1fr)); gap: 10px; }
.opt-compare-card { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.opt-compare-card strong { font-size: 12px; color: var(--text); }
.opt-compare-card audio { width: 100%; }
.opt-style-panel { grid-column: 1 / -1; display: grid; grid-template-columns: minmax(280px,1fr) minmax(260px,.8fr); gap: 10px; }
.opt-style-preview-box { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.opt-style-audio { width: 100%; display: none; }
.backend-help { border: 1px solid var(--border); border-radius: 6px; background: rgba(37,99,235,.05); padding: 10px 12px; color: var(--subtext); font-size: 13px; line-height: 1.45; display: grid; gap: 7px; min-width: min(100%, 620px); }
.backend-help strong { color: var(--text); }
.backend-help-tags { display: flex; gap: 6px; flex-wrap: wrap; }
.backend-tag { border: 1px solid var(--border); border-radius: 4px; padding: 2px 6px; background: var(--panel); color: var(--subtext); font-size: 12px; }
.backend-tag.good { color: #166534; border-color: rgba(22,163,74,.35); } /* AA on light */
.backend-tag.warn { color: #92400E; border-color: rgba(217,119,6,.35); } /* AA on light */
.backend-metrics-row { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 2px; }
.backend-metric-tag { border: 1px solid rgba(99,102,241,.3); border-radius: 4px; padding: 1px 6px; background: rgba(99,102,241,.07); color: #1D4ED8; font-size: 11px; white-space: nowrap; }
.style-backend-warn {
margin-top: 6px; padding: 7px 10px; border-radius: 6px;
background: rgba(220,38,38,.07); border: 1px solid rgba(220,38,38,.25);
color: var(--red); font-size: 12px; line-height: 1.45;
}
.opt-wave { cursor: crosshair; touch-action: none; width: 100%; height: 86px; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; display: block; }
.opt-controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: end; margin-top: 8px; }
.crop-duration-hint { align-self: center; color: var(--subtext); font-size: 12px; padding: 7px 9px; border: 1px solid var(--border); border-radius: 6px; background: var(--panel); }
.crop-duration-hint.ok { color: var(--green); border-color: rgba(22,163,74,.35); }
.crop-duration-hint.warn { color: var(--yellow); border-color: rgba(217,119,6,.35); }
.optimizer-workflow { grid-column: 1 / -1; }
.opt-maintenance { grid-column: 1 / -1; }
.opt-field { display: flex; flex-direction: column; gap: 4px; }
.opt-field label { font-size: 10px; color: var(--subtext); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
.opt-field input { width: 74px; background: var(--bg); border: 1px solid var(--border); color: var(--text); border-radius: 5px; padding: 6px 8px; font-size: 12px; font-family: monospace; }
.opt-field select { background: var(--bg); border: 1px solid var(--border); color: var(--text); border-radius: 5px; padding: 6px 8px; font-size: 12px; font-family: monospace; }
.opt-field.wide { flex: 1 1 220px; }
.opt-field.wide input, .opt-field.wide select { width: 100%; min-width: 180px; }
.opt-transcript { width: 100%; min-height: 86px; background: var(--bg); border: 1px solid var(--border); color: var(--text); border-radius: 6px; padding: 8px 10px; font-size: 13px; resize: vertical; }
.opt-status { font-size: 12px; color: var(--subtext); min-height: 16px; margin-top: 6px; }
.opt-restart-note { font-size: 12px; color: var(--yellow); align-self: center; }
.opt-restart-note[hidden] { display: none; }
.opt-restart-needed .opt-restart-tts { border-color: var(--yellow); color: var(--yellow); }
/* ── Audio bar ──────────────────────────────────────────────────────────── */
#lib-audio-bar { background: var(--panel); border: 1px solid var(--accent); border-radius: var(--radius); padding: 10px 14px; }
#lib-audio-bar audio { width: 100%; }
#lib-audio-bar .lib-audio-label { font-size: 13px; color: var(--accent); font-family: monospace; margin-bottom: 5px; font-weight: 700; }
/* ── Library add panel ──────────────────────────────────────────────────── */
.lib-add-panel { display: none; border: 1px solid rgba(37,99,235,.3); border-radius: 8px; background: rgba(37,99,235,.04); padding: 16px; margin: 6px 0 12px; }
.lib-add-panel.open { display: block; }
.lib-add-stack { display: flex; flex-direction: column; gap: 16px; }
.lib-add-section { border: 1px solid rgba(37,99,235,.2); border-radius: 8px; background: var(--surface); padding: 16px; }
.lib-add-section > h2 { color: var(--accent); margin-bottom: 14px !important; letter-spacing: .08em; }
.lib-add-input-grid { display: grid; grid-template-columns: minmax(300px,.9fr) minmax(420px,1.1fr); gap: 12px; align-items: stretch; }
.lib-add-import-box { border: 1px solid rgba(37,99,235,.2); border-radius: 8px; background: var(--panel); padding: 14px; display: flex; flex-direction: column; gap: 14px; }
.lib-add-record-box { border: 1px solid rgba(37,99,235,.2); border-radius: 8px; background: var(--panel); padding: 14px; display: flex; flex-direction: column; gap: 10px; }
.lib-add-drop { border: 2px dashed rgba(37,99,235,.4); border-radius: 8px; min-height: 150px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; cursor: pointer; color: var(--subtext); text-align: center; padding: 16px; transition: border-color .15s, background .15s, color .15s; background: rgba(37,99,235,.03); }
.lib-add-drop.drag-over { border-color: var(--accent); background: rgba(37,99,235,.08); color: var(--accent); }
.lib-add-drop strong { color: var(--text); font-size: 16px; }
.lib-add-drop span { font-size: 12px; color: var(--subtext); }
.lib-add-source-box { display: flex; flex-direction: column; gap: 10px; }
.lib-add-source-box input[type=text] { width: 100%; background: var(--surface); border: 1px solid rgba(37,99,235,.22); color: var(--text); border-radius: var(--radius); padding: 9px 12px; font-size: 14px; }
.lib-add-source-preview { display: none; align-items: center; gap: 10px; border: 1px solid rgba(37,99,235,.25); border-radius: 8px; background: rgba(37,99,235,.06); padding: 8px 10px; min-width: 0; }
.lib-add-source-preview.open { display: flex; }
.lib-add-source-preview img { width: 44px; height: 44px; border-radius: 6px; object-fit: cover; border: 1px solid var(--border); background: var(--bg); }
.lib-add-source-preview strong { display: block; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lib-add-source-preview span { display: block; color: var(--subtext); font-size: 12px; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.record-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.record-head .note { font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--accent); }
.record-head-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.record-head-actions button { padding: 6px 10px; font-size: 12px; }
.lib-add-recorder-tools { display: flex; flex-direction: column; gap: 10px; }
.lib-add-mic-row { display: grid; grid-template-columns: minmax(240px,1fr) minmax(260px,.9fr); gap: 10px; align-items: stretch; }
.sample-read-box, .mic-monitor-box { border: 1px solid rgba(37,99,235,.18); border-radius: 6px; background: var(--surface); padding: 12px; }
.mic-monitor-box { padding: 10px; display: flex; flex-direction: column; gap: 8px; }
.sample-head, .mic-monitor-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 6px; }
.sample-head label, .mic-monitor-head span:first-child { font-size: 14px; font-weight: 700; color: var(--accent); text-transform: uppercase; letter-spacing: .06em; }
.sample-head select { background: var(--bg); border: 1px solid var(--border); color: var(--text); border-radius: 6px; padding: 6px 8px; font-size: 13px; min-width: 150px; }
.sample-sentence { width: 100%; min-height: 120px; font-size: 16px; line-height: 1.55; color: var(--text); background: var(--surface); border: 1px solid var(--border); border-left: 4px solid var(--accent); border-radius: 6px; padding: 10px 12px; resize: vertical; font-family: inherit; }
.sample-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.sample-actions button { padding: 6px 10px; font-size: 12px; }
.recording-tips { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.recording-tip { font-size: 14px; color: var(--subtext); border: 1px solid rgba(37,99,235,.25); border-radius: 999px; padding: 3px 8px; background: rgba(37,99,235,.07); }
.meter-readout { font-family: monospace; color: var(--subtext); font-size: 12px; white-space: nowrap; }
.mic-meter { display: grid; grid-template-columns: repeat(18, 1fr); gap: 3px; height: 24px; align-items: end; margin-bottom: 8px; }
.mic-meter .bar { height: 7px; border-radius: 3px; background: var(--border); transition: height .08s linear, background .08s linear, opacity .08s linear; opacity: .55; }
.mic-meter .bar.on { opacity: 1; background: var(--green); }
.mic-meter .bar.hot { background: var(--yellow); }
.mic-meter .bar.clip { background: var(--red); }
.mic-live-wave { width: 100%; height: 52px; border-radius: 4px; display: block; background: rgba(0,0,0,.06); margin-bottom: 4px; }
[data-theme="dark"] .mic-live-wave { background: rgba(17,17,27,.6); }
.mic-buttons { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px,1fr)); gap: 8px; align-content: start; min-width: 0; }
.mic-buttons button { padding-left: 10px; padding-right: 10px; min-height: 44px; }
.mic-timer { font-family: monospace; font-size: 13px; color: var(--subtext); }
.mic-gain-row { display: grid; grid-template-columns: auto minmax(120px,1fr) 42px; gap: 8px; align-items: center; }
.mic-gain-row label { font-size: 12px; color: var(--accent); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
.mic-gain-row input[type=range] { width: 100%; accent-color: var(--accent); }
.mic-gain-value { font-family: monospace; color: var(--text); font-size: 12px; text-align: right; }
.mic-help-panel { display: none; border: 1px solid var(--border); border-radius: 6px; background: rgba(37,99,235,.06); padding: 10px; color: var(--subtext); font-size: 12px; line-height: 1.45; }
.mic-help-panel.open { display: block; }
.mic-help-panel strong { color: var(--text); }
.mic-help-panel ul { margin: 7px 0 0 18px; }
.mic-help-panel li { margin: 4px 0; }
.lib-add-audio-row { display: grid; grid-template-columns: minmax(240px,1fr) auto; gap: 10px; align-items: center; margin-top: 14px; }
.lib-add-panel audio { width: 100%; }
.lib-add-panel .opt-wave { cursor: crosshair; touch-action: none; }
.lib-add-panel textarea { width: 100%; min-height: 80px; background: var(--surface); border: 1px solid rgba(37,99,235,.22); color: var(--text); border-radius: 6px; padding: 8px 10px; font-size: 13px; resize: vertical; }
.lib-add-panel textarea.sample-sentence { min-height: 128px; font-size: 16px; line-height: 1.55; border-left: 3px solid var(--accent); padding: 10px 12px; }
.lib-add-name-grid { display: grid; grid-template-columns: 100px 100px minmax(240px,1fr); gap: 8px; align-items: end; }
.lib-add-name-grid .opt-field input, .lib-add-name-grid .opt-field select { width: 100%; }
#lib-add-status { border-radius: 6px; background: rgba(37,99,235,.07); padding: 8px 10px; color: var(--subtext); font-size: 12px; }
/* ── Design preset library ──────────────────────────────────────────────── */
.design-preset-library { display: flex; flex-direction: column; gap: 6px; }
.design-preset-row { display: grid; grid-template-columns: minmax(120px,.8fr) 70px 90px minmax(180px,1.5fr) minmax(180px,1.4fr) 220px; gap: 8px; align-items: center; border: 1px solid var(--border); border-radius: 6px; background: var(--panel); padding: 8px 10px; font-size: 13px; }
.design-preset-row .preset-desc, .design-preset-row .preset-transcript { color: var(--subtext); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.design-preset-row .preset-actions { display: flex; gap: 6px; justify-content: flex-end; }
/* ── Get voices ─────────────────────────────────────────────────────────── */
.getvoices-source-editor { display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: stretch; }
.getvoices-source-editor textarea { width: 100%; min-height: 96px; resize: vertical; background: var(--panel); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); padding: 10px 12px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }
.getvoices-source-buttons { display: flex; flex-direction: column; gap: 8px; min-width: 132px; }
.getvoices-toolbar { display: grid; grid-template-columns: minmax(160px,1fr) 170px 150px 130px 120px auto; gap: 8px; align-items: center; margin-top: 10px; }
.getvoices-toolbar input, .getvoices-toolbar select { width: 100%; background: var(--panel); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); padding: 9px 12px; }
.getvoices-summary { display: grid; grid-template-columns: repeat(4, minmax(130px,1fr)); gap: 8px; }
.getvoices-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px,1fr)); gap: 12px; }
.voice-source-card { border: 1px solid var(--border); border-radius: 7px; background: var(--surface); padding: 12px; display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.voice-source-head { display: flex; gap: 12px; align-items: flex-start; min-width: 0; }
.voice-source-thumb { width: 72px; height: 72px; border-radius: 7px; object-fit: cover; background: var(--bg); border: 1px solid var(--border); flex: 0 0 auto; }
.voice-source-title { min-width: 0; flex: 1; }
.voice-source-title strong { display: block; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voice-source-title span { display: block; color: var(--subtext); font-size: 12px; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voice-source-desc { color: var(--subtext); font-size: 13px; line-height: 1.4; min-height: 2.8em; }
.voice-source-card audio { width: 100%; min-height: 32px; }
.voice-source-actions { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; }
.voice-source-actions a, .voice-source-actions button { font-size: 12px; padding: 7px 9px; min-height: 32px; }
.voice-source-pill { border: 1px solid var(--border); color: var(--subtext); border-radius: 999px; padding: 3px 7px; font-size: 12px; }
.vs-import-footer { display: flex; justify-content: flex-end; padding-top: 4px; margin-top: -4px; border-top: 1px solid var(--border); }
.vs-import-footer .btn-primary { font-size: 12px; padding: 7px 12px; }
/* ── Integrations ───────────────────────────────────────────────────────── */
.integration-toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.integration-grid { display: flex; flex-direction: column; gap: 12px; }
.integration-card { border: 1px solid var(--border); border-radius: 6px; background: var(--surface); padding: 13px; display: flex; flex-direction: column; gap: 10px; width: 100%; }
.integration-card h3 { font-size: 15px; color: var(--text); margin: 0; display: flex; align-items: center; gap: 7px; cursor: pointer; user-select: none; }
.integration-card h3:hover { opacity: .8; }
.icard-logo { width: 16px; height: 16px; flex-shrink: 0; border-radius: 2px; object-fit: contain; }
.icard-icon { font-size: 16px; flex-shrink: 0; color: var(--accent); line-height: 1; }
.icard-chev { display: inline-flex; align-items: center; justify-content: center; margin-left: auto; flex-shrink: 0; width: 16px; height: 16px; border-radius: 4px; background: var(--panel); border: 1px solid var(--border); color: var(--accent); font-size: 10px; line-height: 1; transition: transform .2s; }
.icard-chev::before { content: '▾'; }
.integration-card.icard-closed .icard-chev { transform: rotate(-90deg); }
.icard-body { display: flex; flex-direction: column; gap: 10px; }
.integration-card p { font-size: 13px; color: var(--subtext); line-height: 1.5; margin: 0; }
.integration-card pre { background: var(--panel); border: 1px solid var(--border); border-radius: 6px; color: var(--text); padding: 10px 12px; font-size: 12px; line-height: 1.45; overflow: auto; min-height: 118px; max-height: 360px; white-space: pre-wrap; }
.integration-card code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; background: none; padding: 0; border-radius: 0; }
.integration-card-wide { border-left: 3px solid var(--accent); }
.integration-card-wide pre { max-height: 480px; }
.btn-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
/* ── Routing ────────────────────────────────────────────────────────────── */
.routing-toolbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.routing-grid { display: grid; grid-template-columns: 42px minmax(104px,.7fr) minmax(92px,.55fr) 82px minmax(112px,.6fr) minmax(140px,1fr) 96px minmax(120px,.65fr) minmax(120px,.65fr) 42px; gap: 8px; align-items: center; }
.route-speed-cell { display: flex; align-items: center; gap: 4px; }
.route-speed-cell input { width: 100%; min-width: 0; text-align: center; }
.route-speed-preview { flex-shrink: 0; width: 30px; height: 30px; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
.routing-header { padding: 8px 10px 10px; border-bottom: 1px solid var(--border); }
.routing-header div { font-size: 14px; font-weight: 700; color: var(--subtext); text-transform: uppercase; letter-spacing: .07em; }
.routing-row { border: 1px solid var(--border); border-radius: 6px; background: var(--surface); padding: 8px 10px; }
.routing-row input, .routing-row select { width: 100%; min-width: 0; background: var(--bg); border: 1px solid var(--border); color: var(--text); border-radius: 6px; padding: 7px 8px; font-size: 13px; }
.route-sound-cell { display: grid; grid-template-columns: minmax(0,1fr) auto auto; gap: 5px; align-items: center; }
.route-sound-cell .route-sound-upload, .route-sound-cell .route-sound-pick { min-height: 32px; padding: 6px 8px; font-size: 12px; }
.routing-row .toggle { justify-self: center; }
.routing-delete { width: 34px; height: 32px; padding: 0; }
.routing-help { border: 1px solid var(--border); border-radius: 6px; background: rgba(37,99,235,.05); padding: 12px; color: var(--subtext); font-size: 13px; line-height: 1.55; }
.routing-url-warning { display: none; margin-top: 7px; color: var(--yellow); }
.routing-url-warning.show { display: block; }
.routing-test-row { margin-top: 12px; display: grid; grid-template-columns: minmax(120px,.35fr) minmax(110px,.3fr) minmax(220px,1fr) auto; gap: 8px; align-items: stretch; }
.routing-test-row input, .routing-test-row textarea { width: 100%; min-width: 0; background: var(--panel); border: 1px solid var(--border); color: var(--text); border-radius: 6px; padding: 8px 10px; font-size: 13px; font-family: inherit; }
.routing-test-row textarea { min-height: 38px; resize: vertical; }
.routing-test-result { margin-top: 8px; font-size: 13px; color: var(--subtext); line-height: 1.45; }
.routing-test-result.warn { color: var(--yellow); }
.routing-test-result.ok { color: var(--green); }
.routing-log-head { display:flex; justify-content:space-between; align-items:flex-start; gap:12px; flex-wrap:wrap; }
.routing-log-actions { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.routing-log-filter { min-height:36px; border:1px solid var(--border); border-radius:6px; background:var(--panel); color:var(--text); padding:0 10px; font:inherit; min-width:170px; }
.routing-log-list { display:flex; flex-direction:column; gap:7px; max-height:340px; overflow:auto; padding-right:4px; }
.routing-log-empty { color:var(--subtext); font-size:13px; padding:10px; border:1px dashed var(--border); border-radius:6px; background:var(--panel); }
.routing-log-entry { display:grid; grid-template-columns: 78px 92px minmax(120px,.75fr) minmax(180px,1.1fr) minmax(150px,.8fr) minmax(220px,1.2fr); gap:8px; align-items:center; border:1px solid var(--border); border-radius:6px; background:var(--surface); padding:8px 10px; font-size:12px; min-width: 860px; }
.routing-log-entry .log-time { color:var(--subtext); font-family:monospace; }
.routing-log-entry .log-app, .routing-log-entry .log-voice { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.routing-log-entry .log-meta, .routing-log-entry .log-text { color:var(--subtext); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.routing-log-badge { justify-self:start; border:1px solid var(--border); border-radius:999px; padding:3px 8px; font-size:11px; font-weight:800; text-transform:uppercase; letter-spacing:.06em; color:var(--subtext); background:rgba(37,99,235,.06); }
.routing-log-entry.status-ok .routing-log-badge, .routing-log-entry.status-matched .routing-log-badge, .routing-log-entry.status-streaming .routing-log-badge { color:var(--green); }
.routing-log-entry.status-no_match .routing-log-badge { color:var(--yellow); }
.routing-log-entry.status-error .routing-log-badge { color:var(--red); }
.routing-log-scroll { overflow-x:auto; }
.routing-sound-browser-head { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; flex-wrap:wrap; }
.routing-sound-browser-actions { display:flex; gap:8px; flex-wrap:wrap; }
.routing-sound-list { display:flex; flex-direction:column; gap:6px; max-height:320px; overflow:auto; padding-right:4px; }
.routing-sound-search { width:100%; background:var(--panel); border:1px solid var(--border); color:var(--text); border-radius:6px; padding:8px 10px; }
.routing-sound-item { display:grid; grid-template-columns:44px minmax(220px,1fr) 90px 96px; gap:8px; align-items:center; border:1px solid var(--border); background:var(--surface); border-radius:6px; padding:8px; }
.routing-sound-item .sound-path { overflow:hidden; white-space:nowrap; text-overflow:ellipsis; font-family:monospace; font-size:12px; }
.routing-sound-item .sound-meta { color:var(--subtext); font-size:12px; }
.routing-sound-item button { min-height:32px; padding:6px 9px; font-size:12px; }
.routing-sound-preview { width:100%; margin-top:8px; }
/* ── Section dividers between subsections ───────────────────────────────── */
.subsection-head {
display: flex; align-items: center; gap: 8px;
padding: 16px 0 8px; border-bottom: 1px solid var(--border); margin-bottom: 12px;
}
.subsection-head h3 {
font-size: 14px; font-weight: 700; color: var(--subtext);
text-transform: uppercase; letter-spacing: .06em; margin: 0;
}
/* ── Responsive ─────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
.vl-grid { grid-template-columns: 1fr; }
.getvoices-source-editor, .getvoices-toolbar, .getvoices-summary { grid-template-columns: 1fr; }
.getvoices-source-buttons { flex-direction: row; min-width: 0; }
.design-sample-grid { grid-template-columns: 1fr; }
.qwen-sample-actions { justify-content: flex-start; }
.design-preset-row, .routing-grid { grid-template-columns: 1fr; }
}
/* Mobile top bar — hidden on desktop */
#mobile-topbar {
display: none;
}
/* Sidebar backdrop (mobile drawer overlay) */
#sidebar-backdrop {
display: none;
position: fixed; inset: 0; z-index: 199;
background: rgba(0,0,0,0.45);
backdrop-filter: blur(2px);
}
#sidebar-backdrop.open { display: block; }
/* ── Mobile (≤ 767px) ─────────────────────────────────────────────────────── */
@media (max-width: 767px) {
/* Top bar */
#mobile-topbar {
display: flex; align-items: center; gap: 10px;
height: 52px; padding: 0 14px;
background: var(--surface); border-bottom: 1px solid var(--border);
position: sticky; top: 0; z-index: 100;
flex-shrink: 0;
}
body { display: flex; flex-direction: column; }
#app-shell { flex: 1; overflow: hidden; }
#sidebar-toggle {
background: none; border: 1px solid var(--border);
border-radius: 7px; width: 36px; height: 36px;
display: flex; align-items: center; justify-content: center;
cursor: pointer; color: var(--text); font-size: 18px; flex-shrink: 0;
}
#sidebar-toggle:active { background: var(--panel); }
.mobile-brand { font-size: 15px; font-weight: 800; color: var(--accent); }
/* Sidebar: slide-in drawer */
#sidebar {
position: fixed; top: 0; left: -240px; bottom: 0;
width: 240px !important; z-index: 200;
transition: left 0.22s ease;
box-shadow: 4px 0 24px rgba(0,0,0,0.18);
overflow-y: auto;
}
#sidebar.open { left: 0; }
/* Main content full width, top-padded by topbar height */
#main-content { padding: 0 12px 60px; }
/* Section headings */
.section-header { flex-wrap: wrap; gap: 8px; }
.section-search { width: 100% !important; max-width: 100%; box-sizing: border-box; }
/* Toast: full width on small screens */
#toast { left: 50%; right: auto; max-width: calc(100vw - 24px); min-width: calc(100vw - 24px); }
.toast-item { max-width: 100%; }
/* ── Voice workbench ──────────────────────────────────────────────────── */
.voices-workbench {
flex-direction: column;
height: auto !important;
min-height: 0 !important;
}
.voices-list-pane {
width: 100% !important;
flex-shrink: 0;
}
.vl-card-list {
max-height: 55vh;
}
.voices-inspector-pane {
flex: none;
min-height: 60vh;
}
/* When a voice is selected on mobile, hide the list and show inspector full-height */
.voices-workbench.mobile-inspector-open .voices-list-pane { display: none; }
.voices-workbench.mobile-inspector-open .voices-inspector-pane { min-height: calc(100dvh - 52px); }
/* Inspector back button (injected by JS) */
.insp-mobile-back {
display: flex; align-items: center; gap: 6px;
padding: 10px 14px; font-size: 13px; font-weight: 600;
color: var(--accent); cursor: pointer;
border-bottom: 1px solid var(--border);
background: var(--surface);
}
.insp-mobile-back .mdi { font-size: 18px; }
/* ── Conversation ─────────────────────────────────────────────────────── */
.conv-config-row { flex-direction: column; gap: 10px; }
.conv-config-group--actions { margin-left: 0; }
.conv-url-inp { width: 100% !important; box-sizing: border-box; }
.conv-main { flex-direction: column; }
.conv-stats-panel { width: 100% !important; flex-shrink: 0; }
/* ── Routing log ──────────────────────────────────────────────────────── */
.routing-log-entry {
min-width: 0 !important;
grid-template-columns: auto 1fr !important;
grid-template-rows: auto auto auto;
}
.routing-log-entry .log-duration,
.routing-log-entry .log-meta,
.routing-log-entry .log-text { display: none; }
/* ── Try It Out ───────────────────────────────────────────────────────── */
.preview-match-panel { grid-template-columns: 1fr !important; }
/* ── Clone / Design section toolbar ──────────────────────────────────── */
.vl-toolbar { gap: 5px; }
/* ── Settings ─────────────────────────────────────────────────────────── */
.settings-grid { grid-template-columns: 1fr !important; }
.settings-cluster-grid { grid-template-columns: 1fr !important; }
/* ── Generic helpers ──────────────────────────────────────────────────── */
.vl-grid { grid-template-columns: 1fr; }
.section-toolbar { flex-wrap: wrap; gap: 6px; }
select, input[type="text"], input[type="url"], input[type="number"], textarea {
font-size: 16px; /* prevent iOS auto-zoom */
}
}
@media (max-width: 1100px) {
.library-control-panel { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.library-insights { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.settings-cluster-grid { grid-template-columns: 1fr; }
.lib-add-input-grid, .lib-add-mic-row { grid-template-columns: 1fr; }
}
/* ── Voices empty state ──────────────────────────────────────────────────── */
.voices-empty-state { padding: 32px 8px; }
.voices-empty-cases {
display: flex; align-items: stretch; gap: 0;
border: 1px solid var(--border); border-radius: var(--radius);
background: var(--surface); overflow: hidden;
}
.voices-empty-case {
flex: 1; padding: 28px 24px; display: flex; flex-direction: column; gap: 10px;
}
.voices-empty-case:first-child { border-right: 1px solid var(--border); }
.voices-empty-case-icon { font-size: 32px; line-height: 1; }
.voices-empty-case h4 { font-size: 15px; font-weight: 700; color: var(--text); margin: 0; }
.voices-empty-case p { font-size: 13px; line-height: 1.6; color: var(--subtext); margin: 0; }
.voices-empty-case code {
background: var(--panel); border: 1px solid var(--border);
border-radius: 4px; padding: 1px 5px; font-size: 12px;
}
.voices-empty-divider {
display: flex; align-items: center; justify-content: center;
width: 40px; flex-shrink: 0;
font-size: 14px; font-weight: 700; color: var(--subtext);
text-transform: uppercase; letter-spacing: .08em;
background: var(--panel); border-left: 1px solid var(--border); border-right: 1px solid var(--border);
}
.voices-folder-row { display: flex; gap: 8px; margin-top: 4px; }
.voices-folder-input {
flex: 1; min-width: 0; background: var(--bg); border: 1px solid var(--border);
border-radius: var(--radius); padding: 8px 10px; font-size: 13px;
color: var(--text); font-family: monospace;
}
.voices-folder-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,.12); }
.voices-empty-hint { font-size: 14.5px; color: var(--subtext); opacity: .75; line-height: 1.7; margin-top: 2px; }
/* Directory browser */
.vef-dir-browser { margin-top: 8px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); overflow: hidden; }
.vef-breadcrumb { display: flex; align-items: center; flex-wrap: wrap; gap: 0; padding: 6px 10px; background: var(--panel); border-bottom: 1px solid var(--border); font-size: 12px; }
.vef-crumb-btn { background: none; border: none; color: var(--accent); cursor: pointer; font-size: 12px; padding: 1px 3px; font-family: monospace; }
.vef-crumb-btn:hover { text-decoration: underline; }
.vef-crumb-cur { font-family: monospace; font-size: 12px; font-weight: 700; color: var(--text); padding: 1px 3px; }
.vef-sep { color: var(--subtext); font-size: 12px; padding: 0 1px; }
.vef-dir-list { max-height: 160px; overflow-y: auto; padding: 4px 0; }
.vef-dir-item { display: flex; align-items: center; gap: 6px; width: 100%; text-align: left; padding: 5px 12px; font-size: 12px; font-family: monospace; background: none; border: none; color: var(--text); cursor: pointer; transition: background .1s; }
.vef-dir-item:hover { background: var(--panel); color: var(--accent); }
.vef-loading, .vef-empty, .vef-error { display: block; padding: 12px 12px; font-size: 12px; color: var(--subtext); }
.vef-error { color: #e53e3e; }
.vef-browser-actions { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-top: 1px solid var(--border); background: var(--panel); }
.vef-selected-path { flex: 1; font-family: monospace; font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--accent); }
.vef-browser-actions .btn-primary { font-size: 12px; padding: 5px 12px; flex-shrink: 0; }
.voices-empty-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.voices-empty-action-btn { width: 100%; }
/* ── Cross-workflow pipeline stepper (Reader/Casting/Characters/Rehearser) ──
PDF → Text → Cast Audiobook → Cast Characters (optional) → Script Rehearser
→ Generate MP3s → Audiobook. Every reachable stop is clickable in either
direction; state lives wherever it was created (readerState/_audiobook/
rehState), so jumping around never destroys it. */
.wf-stepper { display: flex; flex-direction: column; gap: 10px; padding: 14px 20px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 14px; }
.wf-stepper-row1 { display: flex; align-items: center; gap: 0; }
.wf-stepper-row2 { display: flex; align-items: flex-start; gap: 0; overflow-x: auto; padding-top: 10px; border-top: 1px solid var(--border); }
.wf-nav-btn {
align-self: center; display: inline-flex; align-items: center; justify-content: center;
width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
border: 1px solid var(--border); background: var(--surface); color: var(--text);
cursor: pointer; font-size: 16px; margin: 0 6px;
}
.wf-nav-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); background: rgba(37,99,235,.08); }
.wf-nav-btn:disabled { opacity: .35; cursor: not-allowed; }
.wf-stepper-row2 .wf-nav-prev { margin: 0 10px 0 0; }
.wf-stepper-row2 .wf-nav-next { margin-left: auto; }
.wf-stepper-title { align-self: center; font-weight: 700; color: var(--text); font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wf-step {
display: flex; flex-direction: column; align-items: center; gap: 5px;
background: none; border: none; padding: 2px 16px; border-radius: 10px; cursor: pointer;
white-space: nowrap; color: var(--subtext); font-size: 11.5px; font-weight: 600;
transition: background .15s, color .15s; flex-shrink: 0;
}
.wf-step:hover:not(:disabled) { background: rgba(37,99,235,.08); color: var(--accent); }
.wf-step:disabled { opacity: .4; cursor: not-allowed; }
.wf-step-num {
display: inline-flex; align-items: center; justify-content: center;
width: 30px; height: 30px; border-radius: 50%;
background: var(--surface); border: 2px solid var(--border); color: var(--subtext);
font-size: 13px; font-weight: 800; flex-shrink: 0;
transition: background .15s, border-color .15s, color .15s, transform .15s;
}
.wf-step.is-done { color: var(--text); }
.wf-step.is-done .wf-step-num { background: rgba(37,99,235,.12); border-color: var(--accent); color: var(--accent); }
.wf-step.is-current { color: var(--accent); }
.wf-step.is-current .wf-step-num {
background: var(--accent); border-color: var(--accent); color: #fff;
transform: scale(1.15); box-shadow: 0 0 0 4px rgba(37,99,235,.16);
}
.wf-step.is-optional .wf-step-num { border-style: dashed; }
.wf-step small { display: block; font-weight: 500; font-size: 9.5px; opacity: .7; margin-top: -2px; }
/* Connecting line between steps, like a wizard progress rail. */
.wf-step-arrow { color: var(--border); font-size: 20px; flex-shrink: 0; margin: 0 -3px; align-self: flex-start; padding-top: 4px; }
.wf-step-arrow.is-done { color: var(--accent); opacity: .5; }
/* ── Voices workbench ────────────────────────────────────────────────────── */
.voices-workbench {
display: flex; height: calc(100vh - 148px); min-height: 420px;
gap: 10px; background: transparent; overflow: visible;
}
/* List pane — flex column wrapper; visual card appearance is on .vl-card children */
.voices-list-pane {
width: 380px; flex-shrink: 0;
display: flex; flex-direction: column; gap: 8px;
overflow: visible;
}
/* The two cards inside the list pane */
.vl-card {
border: 1px solid var(--border); border-radius: var(--radius);
background: var(--surface); overflow: hidden;
box-shadow: var(--shadow);
}
.vl-card-list {
display: flex; flex-direction: column;
flex: 1; min-height: 0; overflow: hidden;
}
.vl-toolbar {
display: flex; flex-wrap: wrap; gap: 4px;
padding: 8px 10px 7px; border-bottom: 1px solid var(--border);
}
.vl-tb-btn { padding: 3px 8px !important; font-size: 12px !important; flex: 0 0 auto; }
.vl-filters {
display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
padding: 7px 10px; border-bottom: 1px solid var(--border);
}
.vl-search {
flex: 1; min-width: 60px; padding: 5px 8px; font-size: 12.5px;
border: 1px solid var(--border); border-radius: var(--radius);
background: var(--bg); color: var(--text);
}
.vl-search input::placeholder {
color: var(--placehld);
}
.vl-search:focus { outline: none; border-color: var(--accent); }
.vl-filters select {
padding: 4px 5px; font-size: 12px; border: 1px solid var(--border);
border-radius: var(--radius); background: var(--bg); color: var(--text); max-width: 80px;
}
.vl-disabled-label { font-size: 14.5px; color: var(--subtext); white-space: nowrap; cursor: pointer; gap: 3px; display: flex; align-items: center; }
/* Sort bar */
.vl-sort-bar {
display: flex; align-items: center; gap: 5px;
padding: 5px 10px; border-bottom: 1px solid var(--border);
background: var(--panel);
}
/* Search fills the left; the Sort controls sit on the right */
.vl-search-main { flex: 1; min-width: 80px; }
.vl-sort-label {
font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
color: var(--subtext); flex-shrink: 0; margin-right: 1px; margin-left: auto;
}
#voice-sort-field {
flex: 0 0 auto; padding: 3px 6px; font-size: 12px;
border: 1px solid var(--border); border-radius: var(--radius);
background: var(--surface); color: var(--text); cursor: pointer;
min-width: 0;
}
#voice-sort-field:focus { outline: none; border-color: var(--accent); }
.vl-sort-dir-btn {
flex-shrink: 0; width: 26px; height: 26px; padding: 0;
display: flex; align-items: center; justify-content: center;
border: 1px solid var(--border); border-radius: var(--radius);
background: var(--surface); color: var(--subtext); cursor: pointer;
font-size: 14px; transition: background .1s, color .1s;
}
.vl-sort-dir-btn:hover { background: var(--accent); color: #fff; border-color: var(--accent); }
.vl-sort-dir-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); }
#voice-list { flex: 1; overflow-y: auto; min-height: 0; }
/* Virtual tag folders in the voice list */
.vl-tag-group { border-bottom: 1px solid var(--border); }
.vl-tag-head {
width: 100%; display: flex; align-items: center; gap: 7px; padding: 8px 12px;
background: var(--panel); border: none; border-top: 1px solid var(--border);
color: var(--text); font-size: 13px; font-weight: 600; cursor: pointer;
position: sticky; top: 0; z-index: 2; font-family: inherit; text-align: left;
}
.vl-tag-head:hover { background: var(--border); }
.vl-tag-head .mdi { font-size: 16px; color: var(--accent); flex-shrink: 0; }
.vl-tag-caret { color: var(--subtext) !important; font-size: 15px !important; }
.vl-tag-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vl-tag-count { font-size: 11px; font-weight: 700; color: var(--subtext); background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 1px 8px; }
.vl-tag-body { display: flex; flex-direction: column; }
/* ── Voice groups bar ──────────────────────────────────────────────────── */
/* ── Bulk-edit toolbar ──────────────────────────────────────────────────── */
.vl-bulk-bar {
display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
padding: 7px 10px; border-bottom: 2px solid rgba(37,99,235,.35);
background: rgba(37,99,235,.06); position: sticky; top: 0; z-index: 10;
}
.vl-bulk-bar[hidden] { display: none; }
.vl-bulk-count {
font-size: 12px; font-weight: 700; color: var(--accent); white-space: nowrap; min-width: 64px;
}
.vl-bulk-btn {
display: inline-flex; align-items: center; gap: 4px;
font-size: 11px; padding: 3px 9px; border-radius: 6px;
border: 1px solid var(--border); background: var(--card-bg, var(--panel));
color: var(--text); cursor: pointer; white-space: nowrap; transition: background .12s;
}
.vl-bulk-btn:hover { background: var(--panel); border-color: var(--accent); }
.vl-bulk-danger { color: var(--red, #ef4444); border-color: rgba(239,68,68,.3); }
.vl-bulk-danger:hover { background: rgba(239,68,68,.1); border-color: var(--red, #ef4444); }
.vl-bulk-sep { width: 1px; height: 18px; background: var(--border); margin: 0 2px; flex-shrink: 0; }
.vl-bulk-tag-inp, .vl-bulk-rating-sel {
height: 26px; padding: 0 8px; border: 1px solid var(--accent); border-radius: 6px;
background: var(--input-bg, var(--panel)); color: var(--text); font-size: 12px; outline: none;
}
/* Bulk delete confirmation — centered modal */
.vl-bdc-overlay {
position: fixed; inset: 0; z-index: 2000; background: rgba(0,0,0,.45);
display: flex; align-items: center; justify-content: center; padding: 20px;
animation: reh-cdp-in .12s ease-out;
}
.vl-bdc-modal {
background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
box-shadow: 0 18px 50px rgba(0,0,0,.3); padding: 20px; width: 440px; max-width: 100%;
max-height: 82vh; display: flex; flex-direction: column; gap: 12px;
}
.vl-bdc-title { font-size: 17px; font-weight: 800; color: var(--text); display: flex; align-items: center; gap: 9px; }
.vl-bdc-title .mdi { color: var(--red, #ef4444); font-size: 22px; }
.vl-bdc-sub { font-size: 13px; color: var(--subtext); margin: 0; line-height: 1.45; }
.vl-bdc-list { display: flex; flex-wrap: wrap; gap: 5px; overflow-y: auto; max-height: 220px; padding: 2px; }
.vl-bdc-id {
font-size: 12px; font-family: monospace; padding: 2px 8px; border-radius: 5px;
background: rgba(239,68,68,.1); color: var(--red,#ef4444); border: 1px solid rgba(239,68,68,.25);
white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.vl-bdc-more { font-size: 12px; color: var(--subtext); align-self: center; padding: 0 4px; }
.vl-bdc-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; flex-wrap: wrap; }
.vl-bdc-actions button {
padding: 9px 16px; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer;
font-family: var(--font); border: 1px solid var(--border); background: var(--panel); color: var(--text);
}
.vl-bdc-cancel:hover { border-color: var(--accent); }
.vl-bdc-go { background: var(--red, #ef4444) !important; color: #fff !important; border-color: var(--red, #ef4444) !important; display: inline-flex; align-items: center; gap: 6px; }
.vl-bdc-go:hover { filter: brightness(.95); }
.vl-bdc-go:disabled { opacity: .75; cursor: default; }
@media (max-width: 600px) { .vl-bdc-actions button { flex: 1; } }
/* Bulk checkbox on each row */
.vl-bulk-cb {
width: 15px; height: 15px; cursor: pointer; flex-shrink: 0; margin-right: 4px;
accent-color: var(--accent); align-self: center;
}
.vl-row.vl-bulk-selected { background: rgba(37,99,235,.06); }
/* ── Benchmark statuses ──────────────────────────────────────────────────── */
.vl-row.benchmarking-pending { background: rgba(245, 158, 11, 0.08); border-color: rgba(245, 158, 11, 0.4); transition: background 0.3s; }
.vl-row.benchmarking-active { background: rgba(37, 99, 235, 0.12); border-color: var(--accent); box-shadow: 0 0 0 2px rgba(37,99,235,0.2); transition: background 0.3s; }
.vl-row.benchmarking-done { background: rgba(34, 197, 94, 0.08); border-color: rgba(34, 197, 94, 0.4); transition: background 0.8s; }
[data-theme="dark"] .vl-row.benchmarking-pending { background: rgba(245, 158, 11, 0.15); border-color: rgba(245, 158, 11, 0.5); }
[data-theme="dark"] .vl-row.benchmarking-active { background: rgba(37, 99, 235, 0.25); box-shadow: 0 0 0 2px rgba(37,99,235,0.4); }
[data-theme="dark"] .vl-row.benchmarking-done { background: rgba(34, 197, 94, 0.15); border-color: rgba(34, 197, 94, 0.5); }
.voice-groups-bar {
display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
padding: 7px 10px; border-bottom: 1px solid var(--border);
background: rgba(245,158,11,.05);
}
.vg-label { font-size: 11px; font-weight: 700; color: var(--subtext); display: inline-flex; align-items: center; gap: 4px; margin-right: 4px; }
.vg-chip {
display: inline-flex; align-items: center; gap: 5px;
font-size: 12px; padding: 3px 6px 3px 10px; border-radius: 12px;
background: var(--card-bg, var(--panel)); border: 1px solid var(--border);
color: var(--text); cursor: pointer; transition: border-color .15s, background .15s;
}
.vg-chip:hover { border-color: #f59e0b; }
.vg-chip.active { border-color: #f59e0b; background: rgba(245,158,11,.12); font-weight: 600; }
.vg-count { font-size: 10px; background: rgba(0,0,0,.1); border-radius: 8px; padding: 0 5px; font-weight: 700; }
.vg-del {
border: none; background: none; cursor: pointer; color: var(--subtext);
font-size: 15px; line-height: 1; padding: 0 2px; border-radius: 4px;
}
.vg-del:hover { color: var(--red, #ef4444); background: rgba(239,68,68,.12); }
.vg-clear { border: none; background: none; cursor: pointer; color: var(--accent); font-size: 12px; font-weight: 600; padding: 2px 8px; }
.vl-footer {
padding: 7px 10px; border-top: 1px solid var(--border);
font-size: 14.5px; color: var(--subtext);
display: flex; align-items: center; justify-content: space-between; gap: 6px;
}
.vl-add-btn { padding: 4px 9px !important; font-size: 11.5px !important; }
/* Compact voice row — override original card-style .vl-row */
.voices-list-pane .vl-row {
display: flex !important; flex-direction: row !important; align-items: center !important;
gap: 9px !important; padding: 7px 10px !important; cursor: pointer;
border: none !important; border-left: 3px solid transparent !important;
border-bottom: 1px solid var(--border) !important;
border-radius: 0 !important; box-shadow: none !important;
transform: none !important; transition: background .1s; user-select: none;
background: var(--surface) !important;
}
.voices-list-pane .vl-row:last-child { border-bottom: none !important; }
.voices-list-pane .vl-row:hover { background: var(--panel) !important; }
.voices-list-pane .vl-row.vr-selected { background: rgba(37,99,235,.07) !important; border-left-color: var(--accent) !important; }
.voices-list-pane .vl-row.benchmarking-pending { background: rgba(245, 158, 11, 0.08) !important; border-left-color: rgba(245, 158, 11, 0.8) !important; }
.voices-list-pane .vl-row.benchmarking-active { background: rgba(37, 99, 235, 0.15) !important; border-left-color: var(--accent) !important; }
.voices-list-pane .vl-row.benchmarking-done { background: rgba(34, 197, 94, 0.08) !important; border-left-color: rgba(34, 197, 94, 0.8) !important; }
[data-theme="dark"] .voices-list-pane .vl-row.benchmarking-pending { background: rgba(245, 158, 11, 0.15) !important; }
[data-theme="dark"] .voices-list-pane .vl-row.benchmarking-active { background: rgba(37, 99, 235, 0.25) !important; }
[data-theme="dark"] .voices-list-pane .vl-row.benchmarking-done { background: rgba(34, 197, 94, 0.15) !important; }
.voices-list-pane .vl-row.vr-disabled { opacity: .5; }
/* Hide everything except the compact div */
.voices-list-pane .vl-row .vr-main-row,
.voices-list-pane .vl-row .vr-detail-row,
.voices-list-pane .vl-row .vr-optimizer { display: none !important; }
/* Compact content block */
.vl-compact { display: flex; align-items: center; gap: 9px; width: 100%; min-width: 0; }
.vl-compact .vr-play-group { display: flex; gap: 4px; flex-shrink: 0; }
.vl-compact .vr-play-group button {
width: 26px; height: 26px; border-radius: 50%;
border: none; font-size: 9px; display: flex; align-items: center; justify-content: center;
padding: 0; cursor: pointer; transition: filter .15s;
}
.vl-compact .play-btn-orig { background: var(--accent); color: #fff; }
.vl-compact .play-btn-synth { background: var(--teal); color: #fff; }
.vl-compact .vr-play-group button:hover { filter: brightness(1.12); }
/* Avatar: rounded square, supports photo / flag-icon / initial */
.vl-avatar {
width: 42px; height: 42px; border-radius: var(--radius); flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
overflow: hidden;
}
.vl-avatar-photo { padding: 0; }
.vl-avatar-img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius); }
.vl-avatar-flag { background: transparent; }
.vl-avatar-flag .fi { display: block; width: 100%; height: 100%; background-size: cover; background-position: center; border-radius: var(--radius); }
.vl-avatar-initial { background: transparent; }
.vl-avatar-letter { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; font-size: 17px; font-weight: 800; border-radius: var(--radius); }
/* Voice info block (name + type badge + gender chip) */
.vl-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.vl-name { font-size: 12.5px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vl-row.vr-selected .vl-name { color: var(--accent); }
.vl-meta { display: flex; align-items: center; gap: 6px; }
/* Type label — no background, just colored text */
.vl-type-label { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; }
.vl-type-clone { color: var(--accent); }
.vl-type-design { color: var(--mauve); }
/* Separator dot between type and gender */
.vl-type-label + .vl-gender-label::before { content: '·'; color: var(--border); margin-right: 6px; font-weight: 400; }
/* Gender label — no background, just colored symbol + text */
.vl-gender-letter {
display: inline-flex; align-items: center; justify-content: center;
width: 16px; height: 16px; border-radius: 4px;
font-weight: 800; font-size: 11px;
}
.vl-gender-letter.g-f { background: rgba(236, 72, 153, 0.15); color: #ec4899; }
.vl-gender-letter.g-m { background: rgba(59, 130, 246, 0.15); color: #3b82f6; }
.vl-gender-letter.g-n { background: rgba(156, 163, 175, 0.15); color: #9ca3af; }
.vl-flag { font-size: 14px; color: var(--subtext); }
.vl-meta .vr-rating {
font-size: 13px;
min-height: unset;
gap: 0;
}
/* Benchmark speed chip — compact list row + inspector header */
.vl-meta .vl-bench-chip { margin-left: 2px; }
.vl-bench-chip {
display: inline-flex; align-items: center; gap: 2px;
font-size: 10px; font-weight: 600; font-variant-numeric: tabular-nums;
padding: 1px 5px; border-radius: 4px;
background: rgba(20,184,166,.12); color: var(--subtext);
}
.vl-bench-chip .mdi { font-size: 10px; }
.insp-bench-chip {
display: inline-flex; align-items: center; gap: 3px;
font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
color: var(--subtext);
}
.insp-bench-chip .mdi { font-size: 11px; }
.bench-ok { color: var(--green, #22c55e) !important; }
.bench-warn{ color: var(--yellow, #eab308) !important; }
.bench-bad { color: var(--red, #ef4444) !important; }
.vl-bench-chip.bench-ok { background: rgba(34,197,94,.1); }
.vl-bench-chip.bench-warn{ background: rgba(234,179,8,.1); }
.vl-bench-chip.bench-bad { background: rgba(239,68,68,.1); }
.vl-dbfs { display: none; }
/* Table View mode */
.vl-tbl-lang, .vl-tbl-gender, .vl-tbl-type, .vl-tbl-bench, .vl-tbl-dbfs, .vl-tbl-len, .vl-tbl-dur, .vl-tbl-factor, .vl-tbl-time, .vl-tbl-wpm, .vl-tbl-rating, .vl-tbl-source, .vl-tbl-seed, .vl-tbl-note, .vl-tbl-tag, .vl-tbl-active { display: none; }
/* len, dur, time hidden in table view — full detail lives in Setup → Benchmark */
.vl-table-header { display: none; }
.voices-workbench.table-view .voices-list-pane { width: 100% !important; max-width: 100%; }
.voices-workbench.table-view .voices-inspector-pane { display: none !important; }
.voices-workbench.table-view .vl-table-header {
display: grid;
grid-template-columns: 24px 32px 60px minmax(140px, 1.2fr) 55px 65px 55px 55px 50px 65px 55px 85px 65px minmax(80px, 1fr) minmax(120px, 1fr) 50px;
gap: 8px;
align-items: center;
padding: 8px 10px;
font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--subtext);
border-bottom: 1px solid var(--border);
background: var(--surface);
position: sticky; top: 0; z-index: 5;
}
.vl-th-sortable { cursor: pointer; display: flex; align-items: center; gap: 3px; transition: color .15s; }
.vl-th-sortable:hover { color: var(--text); }
.vl-th-sortable .mdi { font-size: 12px; opacity: .6; }
.vl-th-sortable:hover .mdi { opacity: 1; color: var(--accent); }
.vl-th-info { font-size: 11px !important; opacity: .5; cursor: help; margin-left: 1px; }
.vl-th-info:hover { opacity: 1; color: var(--accent); }
.voices-workbench.table-view .vl-compact {
display: grid;
grid-template-columns: 24px 32px 60px minmax(140px, 1.2fr) 55px 65px 55px 55px 50px 65px 55px 85px 65px minmax(80px, 1fr) minmax(120px, 1fr) 50px;
gap: 8px;
align-items: center;
}
.voices-workbench.table-view .vl-bulk-cb { order: 0; margin: 0; justify-self: center; }
.voices-workbench.table-view .vl-info { display: contents; }
.voices-workbench.table-view .vl-meta { display: none; }
.voices-workbench.table-view .vl-avatar { order: 1; width: 32px; height: 32px; }
.voices-workbench.table-view .vr-play-group { order: 2; flex-shrink: 0; }
.voices-workbench.table-view .vl-name,
.voices-workbench.table-view .vl-name-input { order: 3; display: block; font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.voices-workbench.table-view .vl-tbl-lang { display: block; order: 4; font-size: 12px; }
.voices-workbench.table-view .vl-tbl-gender { display: block; order: 5; font-size: 12px; }
.voices-workbench.table-view .vl-tbl-factor { display: block; order: 6; font-size: 12px; font-family: monospace; font-weight: 600; }
.voices-workbench.table-view .vl-tbl-wpm { display: block; order: 7; font-size: 12px; font-family: monospace; }
.voices-workbench.table-view .vl-tbl-seed { display: block; order: 8; font-size: 12px; font-family: monospace; }
.voices-workbench.table-view .vl-tbl-dbfs { display: block; order: 9; font-size: 12px; font-family: monospace; }
.voices-workbench.table-view .vl-tbl-type { display: block; order: 10; font-size: 12px; }
.voices-workbench.table-view .vl-tbl-source { display: block; order: 11; font-size: 12px; overflow: hidden; text-overflow: ellipsis; }
.voices-workbench.table-view .vl-tbl-rating { display: flex; order: 12; font-size: 14px; color: var(--subtext); }
.voices-workbench.table-view .vl-tbl-rating .star.on { color: #f59e0b; }
.voices-workbench.table-view .vl-tbl-tag { display: block; order: 13; font-size: 12px; color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.voices-workbench.table-view .vl-tbl-note { display: block; order: 14; font-size: 12px; color: var(--subtext); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-style: italic; }
.voices-workbench.table-view .vl-tbl-active { display: block; order: 15; font-size: 16px; text-align: center; }
.voices-workbench.table-view .vl-tbl-factor.bench-ok { color: var(--success, #16a34a); }
.voices-workbench.table-view .vl-tbl-factor.bench-warn { color: #d97706; }
.voices-workbench.table-view .vl-tbl-factor.bench-bad { color: var(--error, #dc2626); }
.voices-workbench.table-edit-mode .vl-compact {
background: rgba(37,99,235,0.03);
border-bottom: 1px solid var(--border);
}
.vl-inline-edit {
background: var(--surface-light);
border: 1px solid var(--border);
color: var(--text);
font-family: inherit;
font-size: 12px;
padding: 2px 4px;
border-radius: 4px;
outline: none;
transition: border-color 0.15s;
}
.vl-inline-edit:focus {
border-color: var(--accent);
}
.vl-inline-edit.vl-name-input {
font-size: 13px;
font-weight: 600;
width: 100%;
}
/* Synth mode panel (segmented control + preview input) */
.vl-synth-panel { background: var(--surface); }
.vl-synth-mode-row { display: flex; align-items: center; gap: 7px; padding: 5px 8px 5px; }
.vl-synth-icon { font-size: 9px; color: var(--teal); flex-shrink: 0; }
.vl-synth-label { font-size: 14px; font-weight: 700; color: var(--subtext); white-space: nowrap; flex-shrink: 0; }
.vl-synth-seg { display: flex; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; flex-shrink: 0; }
.vl-synth-seg-btn {
background: var(--panel); border: none; padding: 3px 9px;
font-size: 14.5px; font-weight: 600; color: var(--subtext);
cursor: pointer; transition: background .12s, color .12s; white-space: nowrap;
border-right: 1px solid var(--border);
}
.vl-synth-seg-btn:last-child { border-right: none; }
.vl-synth-seg-btn.active { background: var(--teal); color: #fff; }
.vl-synth-seg-btn:not(.active):hover { background: var(--border); color: var(--text); }
.vl-preview-text-wrap { padding: 0 8px 6px; }
.vl-preview-row { display: flex; align-items: flex-start; gap: 6px; }
.vl-preview-lang-btn {
flex-shrink: 0; width: 34px; height: 34px; margin-top: 1px;
border: 1px solid var(--border); border-radius: 6px;
background: var(--surface); padding: 0; cursor: pointer;
display: flex; align-items: center; justify-content: center;
transition: border-color .15s, box-shadow .15s;
}
.vl-preview-lang-btn:hover { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(37,99,235,.12); filter: none; }
.vl-preview-lang-btn .fi { width: 22px; height: 16px; background-size: cover; background-position: center; border-radius: 2px; display: block; }
.vl-preview-input {
flex: 1; min-width: 0; display: block; box-sizing: border-box;
font-size: 16px; line-height: 1.5;
background: var(--bg); border: 1px solid var(--border); border-radius: 5px;
color: var(--text); padding: 5px 7px; font-family: var(--font);
resize: vertical; min-height: 42px;
}
.vl-preview-input:focus { outline: none; border-color: var(--accent); }
.vl-preview-text-wrap.hidden { display: none; }
/* Inspector pane */
.voices-inspector-pane {
flex: 1; min-width: 0;
background: var(--bg);
display: flex; flex-direction: column; overflow: hidden;
}
.inspector-placeholder {
height: 100%; display: flex; flex-direction: column;
align-items: center; justify-content: center; gap: 10px;
color: var(--placehld); text-align: center; padding: 24px;
}
.inspector-placeholder span { font-size: 40px; opacity: .4; }
.inspector-placeholder p { font-size: 13px; line-height: 1.6; color: var(--subtext); }
/* ── Inspector header ────────────────────────────────────────────────────── */
.inspector-header {
background: var(--surface);
border-bottom: 1px solid var(--border);
flex-shrink: 0;
border-top-left-radius: var(--radius);
border-top-right-radius: var(--radius);
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
margin-right: 30px; /* cause of the scrollbar */
}
/* Header top: [avatar 72px] + [title-stack flex:1] */
.insp-hd-top {
display: flex; align-items: flex-start; gap: 12px;
padding: 12px 14px 8px;
}
/* Avatar — compact square */
.inspector-avatar {
width: 120px; height: 120px; border-radius: var(--radius); flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
font-size: 26px; font-weight: 700; color: #fff; overflow: hidden;
}
.insp-avatar-photo { padding: 0; }
.insp-avatar-img { width: 100%; height: 100%; object-fit: cover; }
.inspector-avatar .fi { display: block; width: 100%; height: 100%; background-size: cover; background-position: center; }
.insp-avatar-clickable { cursor: pointer; transition: opacity .15s; }
.insp-avatar-clickable:hover { opacity: .75; }
/* Title stack — all right-side rows stacked vertically */
.insp-title-stack { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; padding-top: 1px; }
/* Row 1: name + save button */
.insp-hd-row1 { display: flex; align-items: center; gap: 8px; }
.insp-disp-name {
flex: 1; min-width: 0;
font-size: 18px; font-weight: 600; color: var(--text); margin: 0; line-height: 1.3;
cursor: default; user-select: text; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.insp-disp-name:hover { color: var(--accent); }
.insp-name-edit {
flex: 1; min-width: 0;
font-size: 16px; font-weight: 600; color: var(--text);
border: none; border-bottom: 2px solid var(--accent); background: transparent;
outline: none; padding: 0; line-height: 1.3;
}
.insp-actions-save { flex-shrink: 0; }
/* Row 2: voice ID + copy + active toggle */
.insp-hd-row2 { display: flex; align-items: center; gap: 5px; }
.insp-id-block { display: flex; align-items: center; gap: 4px; flex: 1; min-width: 0; }
.insp-full-id {
font-size: 14px; color: var(--subtext); font-family: monospace; font-weight: 400;
cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.insp-full-id:hover { color: var(--accent); text-decoration: underline dotted; }
.insp-copy-id-btn, .insp-edit-id-btn {
background: none; border: 1px solid var(--border); color: var(--subtext);
font-size: 9px; cursor: pointer; padding: 1px 4px; border-radius: 3px;
transition: color .15s, border-color .15s; flex-shrink: 0; white-space: nowrap;
}
.insp-copy-id-btn:hover, .insp-edit-id-btn:hover { color: var(--accent); border-color: var(--accent); }
.insp-edit-id-btn .mdi { font-size: 11px; }
/* ── Clone: transcription in-progress feedback ────────────────────────────── */
@keyframes clone-tr-pulse {
0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 30%, transparent); }
50% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 8%, transparent); }
}
#transcript-area.transcribing {
border-color: var(--accent) !important;
animation: clone-tr-pulse 1.2s ease-in-out infinite;
}
.clone-tr-status { font-size: 13px; display: inline-flex; align-items: center; gap: 6px; }
.clone-tr-status.working { color: var(--accent); font-weight: 600; }
.clone-tr-status.done { color: var(--green); font-weight: 600; }
.clone-tr-status.error { color: var(--red); }
.clone-tr-status .mdi { font-size: 15px; }
.insp-actions-active { display: flex; align-items: center; flex-shrink: 0; }
.insp-actions-active .vr-detail-active { display: contents; align-items: center; gap: 5px; }
.insp-actions-active .vr-detail-active > label:first-child { padding-right: 10px; font-weight: 500; color: var(--subtext); }
.insp-actions-active .toggle { width: 32px; height: 18px; }
.insp-actions-active .t-slider::before { height: 12px; width: 12px; left: 3px; bottom: 3px; }
.insp-actions-active .toggle input:checked + .t-slider::before { transform: translateX(14px); }
/* Divider between ID row and subtitle */
.insp-hd-divider { height: 1px; background: var(--border); margin: 2px 0; }
/* Note + delete bottom row */
.insp-note-delete-row { display: flex; align-items: center; min-width: 0; }
.insp-note-slot { flex: 1; min-width: 0; display: flex; }
.insp-note-slot .vr-note { display: flex; flex: 1; }
.insp-note-slot .vr-note label { display: none; }
.insp-note-slot .vr-note .vr-inline { display: flex; flex: 1; }
.insp-note-slot .vr-note .vr-inline input {
width: 100%; padding: 2px 0; font-size: 14px; font-style: italic; font-family: inherit;
border: none; background: transparent; color: var(--text); outline: none; transition: color .15s;
}
.insp-note-slot .vr-note .vr-inline input::placeholder { color: var(--placehld); opacity: .6; }
.insp-note-slot .vr-note .vr-inline input:focus { font-style: normal; }
.insp-note-slot .ref-transcribe-btn { display: none !important; }
.insp-actions-delete { flex-shrink: 0; display: flex; align-items: center; padding-left: 20px; margin-right: 20px }
.insp-actions-delete .vr-detail-delete { display: flex; align-items: center; }
.insp-actions-delete .delete-btn {
background: none; border: none; color: var(--subtext); font-size: 10.5px;
cursor: pointer; padding: 0; text-decoration: underline dotted;
text-underline-offset: 2px; transition: color .15s; white-space: nowrap;
}
.insp-actions-delete .delete-btn:hover { color: var(--red); }
.insp-actions-delete .delete-confirm {
position: static; min-width: auto; max-width: none; box-shadow: none;
display: none; align-items: center; gap: 4px; font-size: 10.5px;
}
.insp-actions-delete .vr-detail-delete.delete-pending .delete-confirm { display: flex; }
.insp-actions-delete .vr-detail-delete.delete-pending .delete-btn { display: none; }
/* Subtitle: pipe-separated info bar */
.insp-subtitle {
display: flex; align-items: center; gap: 0; overflow: hidden;
}
.insp-subtitle > * {
padding: 0 6px; flex-shrink: 0;
border-right: 1px solid var(--border);
white-space: nowrap; line-height: 1;
}
.insp-subtitle > *:first-child { padding-left: 0; }
.insp-subtitle > *:last-child { border-right: none; flex: 1; flex-shrink: 1; min-width: 0; }
/* Flag (small inline icon, dblclick → picker) */
.insp-flag { display: flex; align-items: center; cursor: pointer; gap: 3px; }
.insp-flag-icon { display: flex; align-items: center; line-height: 1; }
.insp-flag-icon .fi { width: 22px; height: 16px; background-size: cover; background-position: center; border-radius: 2px; display: inline-block; flex-shrink: 0; }
.insp-flag-sel {
font-size: 14px; padding: 1px 4px; border: 1px solid var(--accent);
border-radius: 4px; background: var(--surface); color: var(--text); outline: none;
}
/* Lang wrap — dblclick to edit language */
.insp-lang-wrap { display: flex; align-items: center; cursor: default; }
.insp-lang-code { font-size: 14.5px; font-weight: 600; color: var(--subtext); }
.insp-lang-sel {
font-size: 14px; padding: 1px 4px; border: 1px solid var(--accent);
border-radius: 4px; background: var(--surface); color: var(--text); outline: none;
}
/* Gender label — click to cycle */
.insp-gender-label {
font-size: 14.5px; color: var(--subtext); cursor: pointer; user-select: none;
}
.insp-gender-label:hover { color: var(--text); }
/* Stars */
.insp-stars-wrap { display: flex; align-items: center; gap: 2px; cursor: pointer; }
.insp-stars { display: flex; gap: 0; }
.insp-star { font-size: 12px; color: var(--border); cursor: pointer; transition: color .1s; line-height: 1; }
.insp-star.on { color: #f59e0b; }
.insp-rating-label { font-size: 10px; color: var(--subtext); font-weight: 600; opacity: .75; }
/* Tag input — inline last item in subtitle */
.insp-tag-input {
border: none; background: transparent; color: var(--subtext);
font-size: 14.5px; font-family: inherit; outline: none;
padding: 0 6px; min-width: 50px;
transition: background .15s, color .15s;
}
.insp-tag-input::placeholder { color: var(--placehld); opacity: .5; font-style: italic; }
.insp-tag-input:hover { color: var(--text); }
.insp-tag-input:focus { background: var(--panel); color: var(--text); }
/* Tag autocomplete dropdown */
.tag-suggest {
position: fixed; z-index: 9998;
background: var(--surface); border: 1px solid var(--border);
border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,0.12);
max-height: 220px; overflow-y: auto; padding: 3px 0;
}
.tag-suggest-item {
display: block; width: 100%; text-align: left;
padding: 5px 12px; font-size: 12px; font-family: inherit;
background: none; border: none; color: var(--text);
cursor: pointer; white-space: nowrap; border-radius: 0;
transition: background .1s;
}
.tag-suggest-item:hover { background: var(--panel); filter: none; }
.insp-save-btn { white-space: nowrap; font-size: 12px; padding: 4px 10px; }
/* ── Searchable picker (flag / language) ─────────────────────────────────── */
.insp-picker {
position: fixed; z-index: 9999;
background: var(--surface); border: 1px solid var(--border);
border-radius: var(--radius); box-shadow: 0 4px 20px rgba(0,0,0,0.14);
width: 244px; max-height: 290px;
display: flex; flex-direction: column; overflow: hidden;
}
.insp-picker-search {
padding: 8px 10px; border: none; border-bottom: 1px solid var(--border);
font-size: 12px; font-family: inherit; background: var(--panel);
color: var(--text); outline: none; flex-shrink: 0;
}
.insp-picker-search::placeholder { color: var(--placehld); opacity: .65; }
.insp-picker-list { flex: 1; overflow-y: auto; padding: 3px 0; }
.insp-picker-item {
display: flex; align-items: center; width: 100%; gap: 8px;
padding: 5px 10px; background: none; border: none; border-radius: 0;
font-size: 12px; font-family: inherit; color: var(--text);
cursor: pointer; text-align: left; white-space: nowrap;
transition: background .1s;
}
.insp-picker-item:hover { background: var(--panel); filter: none; }
.insp-picker-item .ipi-code {
font-family: monospace; font-weight: 700; font-size: 14px;
color: var(--accent); min-width: 28px; flex-shrink: 0;
}
.insp-picker-empty { padding: 10px; font-size: 12px; color: var(--subtext); text-align: center; }
/* ── Inspector body ───────────────────────────────────────────────────────── */
.inspector-body { display: flex; flex-direction: column; gap: 10px; flex: 1; overflow-y: auto;}
/* Optimizer: grid becomes transparent so opt-groups become flex children */
.inspector-body .vr-optimizer { display: block !important; }
.inspector-body .optimizer-grid { display: contents; }
.inspector-body .opt-status { display: none !important; }
/* Each opt-group as a collapsible card — same visual language as .card */
.inspector-body .opt-group {
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
/* no overflow:hidden here — it clips title text at rounded corners */
}
/* Title row — mirrors .card-collapse-h2 */
.inspector-body .opt-group-title {
display: flex; align-items: center; gap: 8px;
padding: 12px 14px; font-size: 11px; font-weight: 700; letter-spacing: .08em;
text-transform: uppercase; color: var(--subtext);
cursor: pointer; user-select: none; transition: background .15s;
border-radius: calc(var(--radius) - 1px); /* match inner corner */
}
.inspector-body .opt-group-title:hover { background: var(--panel); }
.inspector-body .opt-group.open > .opt-group-title {
border-bottom: 1px solid var(--border);
border-bottom-left-radius: 0; border-bottom-right-radius: 0;
}
/* Chevron — identical to .card-chev */
.opt-chevron {
display: inline-block; flex-shrink: 0; width: 16px; height: 16px;
border-radius: 4px; background: var(--panel); border: 1px solid var(--border);
color: var(--accent); font-size: 10px; line-height: 16px; text-align: center;
transition: transform .2s;
}
.opt-chevron::before { content: '▾'; }
.inspector-body .opt-group:not(.open) .opt-chevron { transform: rotate(-90deg); }
.inspector-body .opt-group.open .opt-chevron { transform: none; }
/* Title text fills the rest of the row */
.opt-title-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Subtitle — visible only when expanded, indented to align with title text */
.inspector-body .opt-group-subtitle {
font-size: 12px; color: var(--subtext); padding: 0 14px 10px 38px; line-height: 1.5;
}
.inspector-body .opt-group:not(.open) > .opt-group-subtitle { display: none; }
/* Body — hidden when collapsed */
.opt-group-body { overflow: hidden; }
.inspector-body .opt-group:not(.open) > .opt-group-body { display: none; }
.opt-group-footer { display: flex; justify-content: flex-end; padding: 8px 14px 12px; }
.inspector-body .opt-group canvas.opt-wave { display: block; width: 100%; height: 72px; background: var(--bg); }
.inspector-body .opt-group .opt-group-body > .opt-controls { padding: 10px 14px; display: flex; flex-wrap: wrap; gap: 7px; align-items: center; }
.inspector-body .opt-group .opt-group-body > textarea {
display: block; width: 100%; box-sizing: border-box; padding: 10px 14px; margin: 0;
background: transparent; border: none; outline: none; resize: vertical;
font-size: 16px; color: var(--text); font-family: inherit; min-height: 80px;
}
/* Section order */
.inspector-body .opt-trim-panel { order: 10; }
.inspector-body .opt-maintenance { order: 20; }
.inspector-body .opt-text-panel { order: 30; }
.inspector-body .opt-compare-panel { order: 40; }
.inspector-body .opt-style-panel { order: 50; }
/* vr-main-row in inspector — metadata grid (lang, gender, rating, rename) */
.inspector-body .vr-main-row {
order: 55;
display: flex !important; flex-wrap: wrap; gap: 8px; align-items: center;
padding: 10px 14px;
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
}
.inspector-body .vr-main-row .vr-photo,
.inspector-body .vr-main-row .vr-type,
.inspector-body .vr-main-row .vr-length,
.inspector-body .vr-main-row .vr-db,
.inspector-body .vr-main-row .vr-bench,
.inspector-body .vr-main-row .vr-edit,
.inspector-body .vr-main-row .vr-play-group { display: none !important; }
.inspector-body .vr-main-row .vr-identity { display: flex; gap: 8px; align-items: center; flex: 1; min-width: 0; }
.inspector-body .vr-main-row .vr-rating { display: flex; gap: 2px; align-items: center; }
/* vr-detail-row in inspector — Note only (transcript is in opt-text-panel) */
.inspector-body .vr-detail-row {
order: 60;
display: flex !important; flex-direction: column; gap: 0;
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden;
}
.inspector-body .vr-detail-row .vr-detail-active,
.inspector-body .vr-detail-row .vr-detail-delete { display: none !important; }
.inspector-body .vr-detail-row .vr-ref { display: none !important; }
.inspector-body .vr-note, .inspector-body .vr-source { padding: 10px 14px; display: flex; flex-direction: column; gap: 5px; }
.inspector-body .vr-note label, .inspector-body .vr-source label {
font-size: 10px; font-weight: 700; color: var(--subtext);
text-transform: uppercase; letter-spacing: .07em;
}
.inspector-body .vr-note input, .inspector-body .vr-source input {
background: transparent; border: none; outline: none;
font-size: 13.5px; color: var(--text); width: 100%; padding: 0;
}
.inspector-body .vr-inline { display: flex; align-items: center; gap: 8px; }
.opt-group-meta {
font-size: 14px; font-weight: 600; color: var(--accent);
text-transform: none; letter-spacing: 0; flex-shrink: 0;
}
/* vr-main-row in inspector: always hidden (metadata shown in header grid) */
.inspector-body .vr-main-row { display: none !important; }
.inspector-avatar.drag-over {
opacity: 0.8;
outline: 3px dashed var(--accent);
outline-offset: -4px;
transition: all 0.2s;
}
.vl-avatar.drag-over {
opacity: 0.8;
outline: 2px dashed var(--accent);
outline-offset: -2px;
transition: all 0.2s;
}
/* ── AI Backends / LLMs section ──────────────────────────────────────────── */
/* Category pill tabs */
.llm-cat-tabs {
display: flex; gap: 6px; margin-bottom: 22px; flex-wrap: wrap;
}
.llm-cat-tab {
padding: 6px 18px; font-size: 13px; font-weight: 600;
border: 1.5px solid var(--border); border-radius: 20px;
background: var(--surface); color: var(--subtext);
cursor: pointer; transition: all .15s; line-height: 1.4;
}
.llm-cat-tab:hover { border-color: var(--accent); color: var(--accent); filter: none; }
.llm-cat-tab.active {
background: var(--accent); color: var(--on-accent);
border-color: var(--accent); box-shadow: 0 2px 10px rgba(37,99,235,.28);
}
/* Animated section reveal */
.llm-section { animation: llm-fadein .18s ease; }
@keyframes llm-fadein { from { opacity:0; transform:translateY(5px); } to { opacity:1; transform:none; } }
/* Section header row */
.llm-sec-header {
display: flex; align-items: flex-start; justify-content: space-between;
gap: 16px; margin-bottom: 18px; flex-wrap: wrap;
}
.engines-page-head {
align-items: stretch;
flex-direction: column;
gap: 12px;
padding: 18px 20px;
}
.engines-head-main {
display: flex;
align-items: center;
gap: 14px;
min-width: 0;
}
.engines-head-context {
align-items: center;
justify-content: space-between;
gap: 16px;
padding-top: 12px;
border-top: 1px solid var(--border);
}
.engines-context-copy {
min-width: 0;
}
.engines-context-copy .llm-sec-note {
max-width: none;
}
.engines-context-actions {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
justify-content: flex-end;
flex-shrink: 0;
}
@media (max-width: 900px) {
.engines-head-context {
align-items: flex-start;
flex-direction: column;
}
.engines-context-actions {
justify-content: flex-start;
}
}
.llm-sec-title { font-size: 15px; font-weight: 700; color: var(--text); margin: 0 0 4px; }
.llm-sec-note { font-size: 13px; color: var(--subtext); margin: 0; line-height: 1.5; max-width: 640px; }
.llm-free-badge {
font-size: 14px; font-weight: 700; letter-spacing: .02em;
color: #166534; background: rgba(22,163,74,.10); border: 1px solid rgba(22,163,74,.22);
border-radius: 12px; padding: 3px 12px; white-space: nowrap; flex-shrink: 0; align-self: flex-start;
}
.llm-free-local { color: #115E59; background: rgba(13,148,136,.10); border-color: rgba(13,148,136,.22); }
/* ── Active Language Model (global picker) ─────────────── */
.llm-active-panel {
padding: 16px 18px; margin-bottom: 18px;
border: 1px solid rgba(13,148,136,.30);
background: linear-gradient(135deg, rgba(13,148,136,.06), transparent 60%);
}
.llm-active-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 14px; }
.llm-active-icon {
display: inline-flex; align-items: center; justify-content: center;
width: 32px; height: 32px; border-radius: 9px; flex-shrink: 0;
color: var(--teal); background: rgba(13,148,136,.12); font-size: 18px;
}
.llm-active-title { font-size: 14px; font-weight: 700; color: var(--text); margin: 0 0 2px; }
.llm-active-sub { font-size: 12px; color: var(--subtext); margin: 0; line-height: 1.45; }
.llm-active-controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.llm-active-lbl {
display: inline-flex; align-items: center; gap: 5px;
font-size: 12px; font-weight: 600; color: var(--subtext); white-space: nowrap;
}
.llm-active-controls select { height: 32px; min-width: 160px; max-width: 260px; }
.llm-active-url-inp { height: 32px; min-width: 260px; max-width: 420px; flex: 1 1 260px; }
.llm-active-status { font-size: 12px; color: var(--subtext); margin-left: 4px; }
.llm-active-status.ok { color: var(--green); }
.llm-active-status.err { color: var(--red); }
/* ── Cloud service cards grid ─────────────────────────── */
.llm-service-grid {
display: grid; grid-template-columns: repeat(auto-fill, minmax(440px, 1fr)); gap: 14px;
margin-bottom: 8px;
}
.llm-card {
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
padding: 16px 18px; display: flex; flex-direction: column; gap: 11px;
transition: box-shadow .2s, border-color .2s, transform .15s;
}
.llm-card:hover { box-shadow: 0 4px 18px rgba(37,99,235,.11); border-color: rgba(37,99,235,.28); transform: translateY(-1px); }
.llm-card-highlight {
border-color: var(--accent); border-width: 1.5px;
background: linear-gradient(135deg, rgba(37,99,235,.03) 0%, var(--surface) 100%);
}
/* Card head: icon bubble + name block + tier badge */
.llm-card-head { display: flex; align-items: center; gap: 11px; }
.llm-card-icon {
font-size: 20px; flex-shrink: 0; line-height: 1;
width: 42px; height: 42px; border-radius: 10px;
display: flex; align-items: center; justify-content: center;
background: var(--panel); border: 1px solid var(--border);
}
.llm-card-name { font-size: 14px; font-weight: 700; color: var(--text); line-height: 1.2; }
.llm-card-sub { font-size: 14px; color: var(--subtext); margin-top: 2px; line-height: 1.35; }
.llm-tier-badge {
margin-left: auto; flex-shrink: 0;
font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
padding: 3px 9px; border-radius: 10px;
}
.llm-tier-free { color: var(--green); background: rgba(22,163,74,.10); border: 1px solid rgba(22,163,74,.22); }
.llm-tier-demo { color: var(--yellow); background: rgba(217,119,6,.10); border: 1px solid rgba(217,119,6,.22); }
.llm-tier-paid { color: var(--mauve); background: rgba(124,58,237,.10); border: 1px solid rgba(124,58,237,.22); }
/* Quick-stat chips */
.llm-card-stats { display: flex; gap: 5px; flex-wrap: wrap; }
.llm-card-stats span {
font-size: 14px; color: var(--subtext);
background: var(--panel); border: 1px solid var(--border);
padding: 2px 9px; border-radius: 10px; white-space: nowrap;
}
/* API key row */
.llm-field-row { display: flex; align-items: center; gap: 7px; }
.llm-label { font-size: 14px; font-weight: 600; color: var(--subtext); white-space: nowrap; flex-shrink: 0; }
.llm-input {
flex: 1; min-width: 0; font-size: 12px; font-family: monospace;
padding: 5px 10px; border: 1px solid var(--border); border-radius: 6px;
background: var(--panel); color: var(--text); outline: none; transition: border-color .15s, background .15s;
}
.llm-input:focus { border-color: var(--accent); background: var(--surface); box-shadow: 0 0 0 3px rgba(37,99,235,.10); }
.llm-link {
font-size: 14px; color: var(--accent); text-decoration: none; white-space: nowrap;
flex-shrink: 0; font-weight: 600; transition: opacity .15s;
}
.llm-link:hover { opacity: .75; }
/* Endpoint display */
.llm-endpoint {
display: flex; align-items: center; gap: 8px;
padding: 5px 10px; background: var(--panel); border-radius: 6px;
border: 1px solid var(--border); font-size: 14px; overflow: hidden;
}
.llm-endpoint-label { color: var(--subtext); font-weight: 600; white-space: nowrap; flex-shrink: 0; }
.llm-endpoint code {
font-family: monospace; font-size: 14px; color: var(--teal);
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
/* Model tags */
.llm-models { display: flex; gap: 5px; flex-wrap: wrap; }
.llm-model-tag {
font-size: 10.5px; font-family: monospace; color: var(--accent);
background: rgba(37,99,235,.07); border: 1px solid rgba(37,99,235,.18);
padding: 2px 8px; border-radius: 4px; white-space: nowrap;
}
/* Info / tip box */
.llm-info-box {
font-size: 12px; color: var(--subtext); line-height: 1.55;
background: var(--panel); border-radius: 7px; padding: 10px 13px;
border-left: 3px solid var(--yellow);
}
.llm-link-inline { color: var(--accent); text-decoration: none; font-weight: 600; }
.llm-link-inline:hover { text-decoration: underline; }
.llm-info-note { font-size: 14px; color: var(--subtext); font-style: italic; }
.llm-info-note code { font-family: monospace; color: var(--teal); font-style: normal; }
/* ── Local services ────────────────────────────────────── */
.llm-local-cat {
font-size: 14px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
color: var(--subtext); margin: 0 0 10px;
padding-bottom: 7px; border-bottom: 1px solid var(--border);
}
.llm-local-grid {
display: grid; grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); gap: 14px;
margin-bottom: 6px;
}
.llm-local-card {
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
padding: 14px 16px; display: flex; flex-direction: column; gap: 9px;
transition: box-shadow .2s, border-color .2s, background .2s;
}
.llm-local-card:hover { box-shadow: 0 4px 16px rgba(13,148,136,.12); border-color: rgba(13,148,136,.35); }
.llm-local-card-running { border-color: var(--teal); background: rgba(13,148,136,.025); }
.llm-local-card-online { border-color: rgba(22,163,74,.6); background: rgba(22,163,74,.04); }
.llm-local-card-offline { border-color: rgba(220,38,38,.4); background: rgba(220,38,38,.03); }
.llm-local-head { display: flex; align-items: center; gap: 8px; }
.llm-local-icon { font-size: 20px; flex-shrink: 0; width: 26px; text-align: center; line-height: 1; }
.llm-local-name { font-size: 13.5px; font-weight: 700; color: var(--text); flex: 1; min-width: 0; }
.llm-local-compat {
font-size: 10px; font-weight: 600; color: var(--subtext);
background: var(--panel); border: 1px solid var(--border);
padding: 2px 8px; border-radius: 10px; white-space: nowrap;
}
.llm-compat-detected {
color: #115E59; background: rgba(13,148,136,.10); border-color: rgba(13,148,136,.28);
}
.llm-compat-running {
color: var(--green, #16a34a); background: rgba(22,163,74,.10); border-color: rgba(22,163,74,.30);
}
.llm-compat-stopped {
color: var(--red, #dc2626); background: rgba(220,38,38,.08); border-color: rgba(220,38,38,.25);
}
.llm-local-desc { font-size: 12px; color: var(--subtext); line-height: 1.5; margin: 0; }
.llm-local-url {
display: flex; align-items: center; gap: 7px; flex-wrap: nowrap;
font-size: 12px; font-weight: 600; color: var(--subtext);
background: var(--panel); padding: 4px 9px; border-radius: 5px; border: 1px solid var(--border);
transition: border-color .15s;
}
.llm-local-url:focus-within { border-color: var(--accent); }
.llm-local-url code { font-family: monospace; font-size: 14px; color: var(--teal); }
.llm-local-url-label { white-space: nowrap; flex-shrink: 0; }
.llm-local-url-inp {
flex: 1; min-width: 0; font-family: monospace; font-size: 13px; color: var(--teal);
background: transparent; border: none; outline: none; padding: 0;
}
.llm-local-url-inp::placeholder { color: var(--teal); opacity: .55; }
/* Code snippet block with dark theme */
.llm-local-snippet { background: #1b1f2e; border-radius: 8px; overflow: hidden; }
.llm-snippet-bar {
display: flex; align-items: center; justify-content: space-between;
padding: 5px 11px; background: rgba(255,255,255,.04); border-bottom: 1px solid rgba(255,255,255,.06);
font-size: 10.5px; color: rgba(255,255,255,.4); font-weight: 600; letter-spacing: .02em;
cursor: pointer; user-select: none; transition: background .12s;
}
.llm-snippet-bar:hover { background: rgba(255,255,255,.08); }
.llm-snip-chev { color: rgba(255,255,255,.45); margin-right: 5px; font-size: 9px; flex-shrink: 0; }
.llm-copy-btn {
font-size: 10px; padding: 2px 9px; border-radius: 4px;
background: rgba(255,255,255,.10); border: 1px solid rgba(255,255,255,.18);
color: rgba(255,255,255,.65); cursor: pointer; transition: background .15s; font-family: inherit;
}
.llm-copy-btn:hover { background: rgba(255,255,255,.2); filter: none; }
.llm-local-snippet pre {
margin: 0; padding: 10px 12px; color: #9ecfb0; font-family: monospace;
font-size: 14px; line-height: 1.65; overflow-x: auto; white-space: pre;
}
.llm-local-link {
font-size: 14.5px; color: var(--accent); text-decoration: none; font-weight: 600;
align-self: flex-start;
}
.llm-local-link:hover { text-decoration: underline; }
/* Metric chips inside AI Backend cards */
.llm-local-metrics { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 4px; }
.llm-metric-chip {
font-size: 10px; padding: 1px 6px; border-radius: 4px;
border: 1px solid rgba(99,102,241,.3); background: rgba(99,102,241,.07);
color: #1D4ED8; white-space: nowrap;
}
/* ── Engine card — unified control bar ──────────────────────────────────── */
.llm-local-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
/* Single row that holds Connect + Docker controls + Use-as in left→right order */
.dc-controls-row {
display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.dc-ctrl-group { display: flex; gap: 4px; flex-wrap: wrap; align-items: center; }
/* ── Connect / Disconnect — primary CTA, prominent blue ─────────────────── */
.llm-local-ping {
padding: 5px 12px; font-size: 11.5px; font-weight: 700; border-radius: 5px;
border: 1.5px solid #2563eb; background: #2563eb; color: #fff;
cursor: pointer; font-family: inherit;
display: inline-flex; align-items: center; gap: 5px;
white-space: nowrap; flex-shrink: 0;
transition: background .15s, border-color .15s, box-shadow .15s;
}
.llm-local-ping:hover:not(:disabled) {
background: #1d4ed8; border-color: #1d4ed8;
box-shadow: 0 2px 8px rgba(37,99,235,.35);
}
.llm-local-ping:disabled { opacity: .5; cursor: default; }
.llm-local-ping.ok {
background: rgba(22,163,74,.1); border-color: rgba(22,163,74,.55); color: #16a34a;
}
.llm-local-ping.ok:hover:not(:disabled) {
background: rgba(220,38,38,.07); border-color: var(--red); color: var(--red);
}
.llm-local-ping.err { border-color: var(--red); color: var(--red); background: rgba(220,38,38,.06); }
/* ── Docker action buttons (Stop / Start / Restart) ─────────────────────── */
.llm-use-btn {
font-size: 11.5px; padding: 5px 10px; border-radius: 5px;
border: 1.5px solid rgba(13,148,136,.4); background: rgba(13,148,136,.07);
color: #115E59; cursor: pointer; font-family: inherit; font-weight: 600;
transition: background .15s, border-color .15s;
display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; flex-shrink: 0;
}
.llm-use-btn:hover:not(:disabled) { background: rgba(13,148,136,.15); border-color: var(--teal); }
.llm-use-btn:active { background: rgba(13,148,136,.25); }
.llm-use-btn:disabled { opacity: .5; cursor: default; }
/* ── "Use as TTS / STT" — activate action, right-aligned, clearly distinct ─ */
.dc-use-btn {
margin-left: auto;
padding: 5px 12px; font-size: 11.5px; font-weight: 700; border-radius: 5px;
border: 1.5px solid #2563eb; background: #2563eb;
color: #fff; cursor: pointer; font-family: inherit;
display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; flex-shrink: 0;
transition: background .15s, border-color .15s, box-shadow .15s;
}
.dc-use-btn:hover:not(:disabled) {
background: #1d4ed8; border-color: #1d4ed8;
box-shadow: 0 2px 8px rgba(37,99,235,.35);
}
.dc-use-btn.active {
background: rgba(13,148,136,.22); border-color: var(--teal);
box-shadow: 0 0 0 2px rgba(13,148,136,.18);
}
.dc-use-btn:disabled { opacity: .5; cursor: default; }
/* Password show/hide toggle */
.llm-eye-btn {
background: none; border: 1px solid var(--border); border-radius: 5px;
padding: 3px 6px; font-size: 13px; cursor: pointer; color: var(--subtext);
flex-shrink: 0; transition: border-color .15s, opacity .15s; line-height: 1; opacity: .55;
}
.llm-eye-btn:hover { border-color: var(--accent); opacity: 1; filter: none; }
.llm-eye-btn.active { opacity: 1; border-color: var(--accent); }
/* "Key saved" indicator inside card head */
.llm-saved-badge {
margin-left: auto; font-size: 10px; font-weight: 700; letter-spacing: .02em;
color: var(--green); background: rgba(22,163,74,.10); border: 1px solid rgba(22,163,74,.22);
border-radius: 10px; padding: 2px 9px; white-space: nowrap; flex-shrink: 0;
}
/* Override margin-left:auto on tier badge when saved badge is also present */
.llm-card-head .llm-tier-badge { margin-left: auto; }
.llm-card-head .llm-saved-badge { margin-left: 0; }
/* How-to tip panel */
.llm-local-howto {
display: flex; align-items: flex-start; gap: 14px; margin-top: 20px;
background: var(--panel); border-radius: var(--radius); padding: 16px 18px;
border-left: 4px solid var(--accent);
}
.llm-howto-icon { font-size: 22px; flex-shrink: 0; margin-top: 1px; }
.llm-howto-body { font-size: 13px; line-height: 1.55; color: var(--text); }
.llm-howto-body strong { display: block; margin-bottom: 5px; }
.llm-howto-body p { margin: 0; color: var(--subtext); }
.llm-howto-body em { font-style: normal; font-weight: 600; color: var(--text); }
/* ── Add Custom Engine dialog ─────────────────────────────────────────────── */
.add-engine-dlg {
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
padding: 0; width: min(460px, 94vw); box-shadow: 0 8px 32px rgba(0,0,0,.28);
color: var(--text);
}
.add-engine-dlg::backdrop { background: rgba(0,0,0,.45); }
.add-engine-form { padding: 22px 24px; display: flex; flex-direction: column; gap: 14px; }
.add-engine-title { margin: 0 0 2px; font-size: 15px; font-weight: 700; }
.add-engine-field { display: flex; flex-direction: column; gap: 5px; }
.add-engine-field label { font-size: 12px; font-weight: 600; color: var(--subtext); }
.add-engine-opt { font-weight: 400; opacity: .65; }
.add-engine-field input, .add-engine-field select {
padding: 7px 10px; border: 1px solid var(--border); border-radius: 5px;
background: var(--bg); color: var(--text); font-family: inherit; font-size: 13px;
transition: border-color .15s;
}
.add-engine-field input:focus, .add-engine-field select:focus {
outline: none; border-color: var(--accent);
}
.add-engine-actions { display: flex; gap: 8px; justify-content: flex-end; padding-top: 4px; }
/* Delete button variant */
.dc-delete-btn { border-color: rgba(220,38,38,.35) !important; color: var(--red, #dc2626) !important; background: rgba(220,38,38,.05) !important; }
.dc-delete-btn:hover { background: rgba(220,38,38,.12) !important; border-color: var(--red, #dc2626) !important; }
/* ── ElevenLabs Voice Browser ──────────────────────────────────────────────── */
.el-browser { padding: 0; overflow: hidden; }
.el-head { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 14px; padding: 16px 20px 14px; border-bottom: 1px solid var(--border); }
.el-brand { display: flex; align-items: flex-start; gap: 12px; flex: 1; min-width: 200px; }
.el-brand-logo { display: flex; align-items: center; justify-content: center; width: 38px; height: 38px; border-radius: 9px; background: #131314; color: #fff; font-weight: 800; font-size: 13px; letter-spacing: -0.5px; flex-shrink: 0; margin-top: 3px; }
.el-brand h2 { margin: 0 0 3px; font-size: 14px; font-weight: 700; }
.el-brand p { margin: 0; font-size: 12px; }
.el-key-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.el-key-field { display: flex; gap: 6px; }
.el-key-field input { width: 230px; font-size: 12px; padding: 5px 9px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); color: var(--text); font-family: monospace; }
.el-key-btn { font-size: 12px; padding: 5px 12px; }
.el-key-status { font-size: 11px; font-weight: 600; }
.el-key-ok { color: #38a169; }
.el-key-none { color: var(--subtext); }
.el-cats { display: flex; flex-wrap: wrap; gap: 6px; padding: 11px 20px; border-bottom: 1px solid var(--border); }
.el-cat { padding: 4px 13px; border-radius: 20px; border: 1px solid var(--border); background: transparent; color: var(--text); font-size: 12px; cursor: pointer; transition: border-color .15s, color .15s, background .15s; white-space: nowrap; }
.el-cat:hover { border-color: var(--accent); color: var(--accent); }
.el-cat.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.el-filters { display: flex; flex-wrap: wrap; gap: 8px; padding: 10px 20px; border-bottom: 1px solid var(--border); align-items: center; }
.el-search { flex: 1; min-width: 130px; font-size: 13px; padding: 5px 9px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); color: var(--text); font-family: inherit; }
.el-filters select { font-size: 12px; padding: 5px 8px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text); font-family: inherit; }
.el-status-bar { padding: 6px 20px; background: var(--panel); border-bottom: 1px solid var(--border); font-size: 12px; color: var(--subtext); }
.el-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(272px, 1fr)); }
.el-grid > .el-loading,
.el-grid > .el-error,
.el-grid > .el-empty,
.el-grid > .el-idle { grid-column: 1/-1; padding: 36px 20px; text-align: center; color: var(--subtext); font-size: 13px; }
.el-spinner { display: inline-block; width: 13px; height: 13px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: elSpin .75s linear infinite; vertical-align: middle; margin-right: 6px; }
@keyframes elSpin { to { transform: rotate(360deg); } }
.el-error { color: #e53e3e !important; }
.el-card-voice { display: flex; align-items: stretch; gap: 10px; padding: 11px 13px 0; border-bottom: 1px solid var(--border); border-right: 1px solid var(--border); transition: background .12s; flex-wrap: wrap; }
.el-card-voice:hover { background: var(--panel); }
.el-vc-av { flex-shrink: 0; width: 34px; height: 34px; border-radius: 50%; background: hsl(var(--elh, 220), 52%, 52%); color: #fff; font-weight: 700; font-size: 15px; display: flex; align-items: center; justify-content: center; margin-top: 3px; }
.el-vc-body { flex: 1; min-width: 0; padding-bottom: 10px; }
.el-vc-name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 4px; }
.el-vc-tags { display: flex; flex-wrap: wrap; gap: 3px; margin-bottom: 4px; }
.el-tag { font-size: 10px; padding: 1px 5px; border-radius: 3px; background: var(--panel); border: 1px solid var(--border); color: var(--subtext); white-space: nowrap; }
.el-lang { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 700; }
.el-uc { color: var(--accent); border-color: var(--accent); background: transparent; }
.el-free { color: #38a169; border-color: #38a169; background: transparent; }
/* ── Get Voices Online — source tabs ──────────────────────────────────────── */
.gvo-tabs { display: flex; gap: 4px; flex-wrap: wrap; align-items: flex-end; margin: 0 0 14px; padding: 0; border-bottom: 1px solid var(--border); }
.gvo-tab { display: inline-flex; align-items: center; justify-content: center; gap: 7px; padding: 11px 18px; border: 1px solid transparent; border-bottom: none; background: transparent; color: var(--subtext); font-size: 14px; font-weight: 600; border-radius: 10px 10px 0 0; cursor: pointer; transition: background .15s, color .15s, border-color .15s; font-family: inherit; position: relative; bottom: -1px; }
.gvo-tab:hover { background: var(--surface); color: var(--text); }
.gvo-tab.active { background: var(--panel); color: var(--accent); border-color: var(--border); border-bottom-color: var(--panel); }
.gvo-tab.active::after { content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 2px; background: var(--accent); border-radius: 2px 2px 0 0; }
.gvo-tab .mdi { font-size: 18px; }
.gvo-tab-sub { font-size: 11px; font-weight: 500; color: var(--subtext); }
.gvo-eleven-logo { background: #111; color: #fff; font-weight: 800; font-size: 11px; width: 20px; height: 20px; border-radius: 5px; display: inline-flex; align-items: center; justify-content: center; }
.gvo-tab.active .gvo-eleven-logo { background: var(--accent); color: #fff; }
.fa-pop-close { background: none; border: none; color: var(--subtext); cursor: pointer; font-size: 18px; padding: 0 2px; line-height: 1; }
.fa-pop-close:hover { color: var(--text); }
/* ── Fish.audio voice browser (fish.audio-style cards w/ hover actions) ────── */
.fa-toolbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding: 12px 20px; border-bottom: 1px solid var(--border); }
.fa-search-wrap { flex: 1; min-width: 200px; position: relative; display: flex; align-items: center; }
.fa-search-icon { position: absolute; left: 13px; color: var(--subtext); font-size: 18px; pointer-events: none; }
.fa-search-big { width: 100%; padding: 9px 14px 9px 38px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); color: var(--text); font-family: inherit; font-size: 13px; }
.fa-search-big:focus { outline: none; border-color: var(--accent); }
.fa-pill-select { font-size: 13px; padding: 8px 12px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); color: var(--text); font-family: inherit; cursor: pointer; }
.fa-browse-btn { border-radius: 999px; padding: 8px 18px; }
.fa-filter-anchor { position: relative; }
.fa-filter-btn { position: relative; width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--border); background: var(--surface); color: var(--text); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font-size: 18px; transition: all .12s; }
.fa-filter-btn:hover, .fa-filter-btn.active { border-color: var(--accent); color: var(--accent); }
.fa-filter-badge { position: absolute; top: -4px; right: -4px; min-width: 17px; height: 17px; padding: 0 4px; border-radius: 9px; background: var(--accent); color: #fff; font-size: 10px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; }
/* Popover */
.fa-filter-pop { position: fixed; z-index: 1000; width: 320px; max-width: 90vw; background: var(--card-bg, var(--panel)); border: 1px solid var(--border); border-radius: 14px; box-shadow: 0 12px 36px rgba(0,0,0,.25); padding: 16px; display: flex; flex-direction: column; gap: 13px; overflow-y: auto; }
/* author `display` overrides the UA [hidden] rule — restore it so the popover/badge can hide */
.fa-filter-pop[hidden], .fa-filter-badge[hidden] { display: none; }
.fa-pop-head { display: flex; align-items: center; justify-content: space-between; }
.fa-pop-head strong { font-size: 15px; }
.fa-pop-reset { background: none; border: none; color: var(--subtext); font-size: 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; }
.fa-pop-reset:hover { color: var(--accent); }
.fa-pop-group { display: flex; flex-direction: column; gap: 7px; }
.fa-pop-group > label { font-size: 12px; font-weight: 700; color: var(--text); }
.fa-pchips { display: flex; flex-wrap: wrap; gap: 6px; }
.fa-pchip { font-size: 12px; padding: 5px 12px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface); color: var(--subtext); cursor: pointer; transition: all .12s; font-family: inherit; }
.fa-pchip:hover { color: var(--text); border-color: var(--accent); }
.fa-pchip.active { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
.fa-pop-tag { width: 100%; padding: 7px 11px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--text); font-family: inherit; font-size: 12px; }
.fa-pop-tag:focus { outline: none; border-color: var(--accent); }
.fa-pop-apply { width: 100%; border-radius: 999px; padding: 9px; margin-top: 2px; }
@media (max-width: 560px) { .fa-filter-pop { right: auto; left: 0; } }
.fa-card { display: flex; gap: 11px; padding: 12px 14px; border-bottom: 1px solid var(--border); border-right: 1px solid var(--border); position: relative; transition: background .12s; }
.fa-card:hover { background: var(--panel); }
.fa-card-disabled { opacity: .62; }
.fa-card-avatar { position: relative; width: 48px; height: 48px; border-radius: 10px; overflow: hidden; flex-shrink: 0; background: linear-gradient(135deg, #0ea5e9, #6366f1); }
.fa-avatar { width: 100%; height: 100%; object-fit: cover; display: block; }
.fa-avatar-fallback::after { content: "🐟"; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 22px; }
.fa-play { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,.45); color: #fff; border: none; cursor: pointer; font-size: 22px; opacity: 0; transition: opacity .12s; }
.fa-card:hover .fa-play, .fa-card-playing .fa-play { opacity: 1; }
.fa-card-playing .fa-play .mdi::before { content: "\F03E4"; } /* pause glyph */
.fa-card-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.fa-card-top { display: flex; align-items: baseline; gap: 5px; min-width: 0; }
.fa-card-name { font-size: 13.5px; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fa-card-author { font-size: 11px; color: var(--subtext); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex-shrink: 1; }
.fa-card-desc { font-size: 12px; color: var(--subtext); line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.fa-card-meta { display: flex; flex-wrap: wrap; gap: 4px; }
.fa-meta-chip { font-size: 10px; padding: 1px 7px; border-radius: 999px; background: var(--surface); border: 1px solid var(--border); color: var(--subtext); white-space: nowrap; }
.fa-card-foot { display: flex; align-items: center; gap: 12px; margin-top: 2px; }
.fa-stat { font-size: 11px; color: var(--subtext); display: inline-flex; align-items: center; gap: 3px; }
.fa-import { margin-left: auto; padding: 3px 11px; font-size: 12px; opacity: 0; transition: opacity .12s; }
.fa-card:hover .fa-import, .fa-card-imported .fa-import { opacity: 1; }
.fa-card-imported .fa-import { background: #16a34a; border-color: #16a34a; }
@media (hover: none) { .fa-play, .fa-import { opacity: 1 !important; } }
.el-feat { color: #d69e2e; border-color: #d69e2e; background: transparent; }
.el-clones { opacity: .7; }
.el-vc-desc { font-size: 11px; color: var(--subtext); line-height: 1.4; margin-bottom: 6px; }
.el-vc-meta { margin-top: 4px; }
.el-play { border: 1px solid var(--border); border-radius: 5px; background: var(--surface); color: var(--text); font-size: 11px; padding: 4px 10px; cursor: pointer; white-space: nowrap; transition: border-color .15s, color .15s; font-family: inherit; }
.el-play:hover { border-color: var(--accent); color: var(--accent); }
.el-vc-footer { width: 100%; display: flex; justify-content: flex-end; padding: 6px 0 10px; border-top: 1px solid var(--border); margin-top: 4px; }
.el-clone { border: 1px solid var(--accent); border-radius: 5px; background: var(--accent); color: #fff; font-size: 12px; padding: 5px 12px; cursor: pointer; white-space: nowrap; transition: opacity .15s; font-family: inherit; font-weight: 600; }
.el-clone:hover { opacity: .85; }
.el-pager { display: flex; align-items: center; gap: 12px; padding: 12px 20px; border-top: 1px solid var(--border); }
.el-pager-info { flex: 1; text-align: center; font-size: 12px; color: var(--subtext); }
/* Bottom action buttons */
/* ── Card subtitle & opt-group subtitle ─────────────────────────────────── */
.card-subtitle { font-size: 12px; color: var(--subtext); line-height: 1.5; margin: 2px 0 6px; }
.opt-group-subtitle { font-size: 11px; color: var(--subtext); padding: 0 14px 6px; line-height: 1.4; }
/* ── Docker container grid ──────────────────────────────────────────────── */
.dc-section-head {
display: flex; align-items: flex-start; justify-content: space-between;
gap: 12px; margin: 0 0 12px;
}
.dc-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(440px, 1fr));
gap: 14px;
margin-bottom: 8px;
}
.dc-loading {
grid-column: 1 / -1; padding: 18px 0; text-align: center;
font-size: 13px; color: var(--subtext);
}
.stt-test-panel {
background: var(--surface2);
border: 1px solid var(--border);
border-radius: 10px;
padding: 10px 14px;
margin-bottom: 18px;
display: flex;
flex-direction: column;
gap: 8px;
}
.stt-test-row {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.stt-test-label {
font-size: 12px;
font-weight: 600;
color: var(--subtext);
text-transform: uppercase;
letter-spacing: .04em;
white-space: nowrap;
}
.stt-test-select {
font-size: 13px;
padding: 4px 8px;
border-radius: 6px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
flex: 1;
min-width: 160px;
max-width: 320px;
}
.stt-test-mic {
width: 34px; height: 34px;
border-radius: 50%;
border: none;
background: var(--accent);
color: #fff;
font-size: 16px;
cursor: pointer;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
transition: background .15s, transform .1s;
}
.stt-test-mic:hover { background: var(--accent-hover, #0060d0); }
.stt-test-mic.recording { background: #e53e3e; animation: stt-pulse 1s infinite; }
.stt-test-mic.busy { background: var(--subtext); cursor: not-allowed; }
@keyframes stt-pulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.1); } }
.stt-test-status {
font-size: 12px;
color: var(--subtext);
min-width: 60px;
}
.stt-test-result {
font-size: 13px;
color: var(--text);
background: var(--surface);
border: 1px solid var(--border);
border-radius: 6px;
padding: 8px 10px;
white-space: pre-wrap;
word-break: break-word;
min-height: 32px;
}
.dc-load-err { color: var(--red) !important; }
/* ── Engine card skeleton ────────────────────────────────────────────────── */
.dc-skel-card {
background: var(--surface); border: 1px solid var(--border);
border-radius: 10px; padding: 14px 16px; display: flex; flex-direction: column; gap: 10px;
min-height: 120px;
}
.dc-skel-line {
border-radius: 5px; height: 13px;
background: linear-gradient(90deg, var(--panel), rgba(37,99,235,.08), var(--panel));
background-size: 220% 100%; animation: skeletonSweep 1.15s ease-in-out infinite;
}
.dc-skel-line.wide { width: 70%; }
.dc-skel-line.medium { width: 45%; }
.dc-skel-line.short { width: 28%; }
.dc-skel-line.tall { height: 20px; width: 55%; }
.dc-card {
background: var(--surface); border: 1px solid var(--border);
border-radius: var(--radius); padding: 14px 16px;
display: flex; flex-direction: column; gap: 6px;
transition: border-color .15s, box-shadow .15s;
}
.dc-card:hover { box-shadow: var(--shadow); border-color: rgba(37,99,235,.3); }
.dc-card-running { border-color: rgba(22,163,74,.45); background: rgba(22,163,74,.025); }
.dc-card-head {
display: flex; align-items: center; gap: 8px; margin-bottom: 2px;
}
.dc-icon { font-size: 20px; flex-shrink: 0; width: 26px; text-align: center; line-height: 1; }
.dc-dot {
width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
}
.dc-running { background: var(--green); box-shadow: 0 0 0 3px rgba(22,163,74,.18); }
.dc-stopped { background: var(--yellow); }
.dc-absent { background: var(--border); }
.dc-name { font-size: 13px; font-weight: 700; color: var(--text); flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dc-badges { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.dc-role {
font-size: 10px; font-weight: 700; padding: 1px 5px; border-radius: 3px;
background: var(--accent); color: #fff; white-space: nowrap;
}
.dc-port {
font-size: 10px; font-weight: 600; padding: 1px 5px; border-radius: 3px;
background: var(--panel); border: 1px solid var(--border); color: var(--subtext);
font-family: monospace;
}
.dc-status-label { font-size: 11px; color: var(--subtext); margin-bottom: 2px; }
.dc-desc { font-size: 12px; color: var(--subtext); line-height: 1.45; margin: 0; flex: 1; }
.dc-metrics { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 4px; }
.dc-metric-chip {
font-size: 10px; padding: 1px 6px; border-radius: 4px;
border: 1px solid rgba(99,102,241,.3); background: rgba(99,102,241,.07);
color: var(--accent); white-space: nowrap;
}
.dc-actions { margin-top: 6px; display: flex; gap: 6px; flex-wrap: wrap; }
.dc-btn { font-size: 11.5px; padding: 4px 12px; }
/* ── Performance benchmark ──────────────────────────────────────────────── */
.perf-table-wrap { overflow-x: auto; margin-top: 12px; }
.perf-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.perf-table th, .perf-table td { padding: 7px 10px; border-bottom: 1px solid var(--border); text-align: left; white-space: nowrap; }
.perf-table th { color: var(--subtext); font-size: 11px; text-transform: uppercase; letter-spacing: .05em; }
.perf-th-sort { cursor: pointer; user-select: none; }
.perf-th-sort:hover { color: var(--text); }
.perf-th-sort::after { content: ' ⇅'; opacity: .35; font-size: 10px; }
.perf-th-sort.perf-sort-asc::after { content: ' ↑'; opacity: 1; color: var(--accent); }
.perf-th-sort.perf-sort-desc::after { content: ' ↓'; opacity: 1; color: var(--accent); }
.perf-row-error td { color: var(--subtext); }
.perf-ok { color: var(--green); font-weight: 600; }
.perf-err { color: var(--red); }
.perf-summary { display: flex; flex-wrap: wrap; gap: 10px 18px; padding: 10px 0 4px; font-size: 13px; }
.perf-stat { display: flex; align-items: center; gap: 5px; }
.perf-good { color: var(--green); }
.perf-slow { color: var(--yellow); }
.perf-trend-row { display: flex; align-items: center; gap: 10px; padding: 6px 0 2px; flex-wrap: wrap; font-size: 13px; }
.perf-trend-label { color: var(--subtext); }
.perf-trend-badge { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; padding: 2px 8px; border-radius: 12px; font-size: 12px; }
.perf-trend-better { background: rgba(var(--green-rgb,72,199,116),.15); color: var(--green); }
.perf-trend-worse { background: rgba(var(--red-rgb,255,91,91),.15); color: var(--red); }
.perf-trend-stable { background: var(--panel); color: var(--subtext); }
.perf-sparkline-wrap { display: flex; align-items: center; }
.perf-sparkline { width: 120px; height: 32px; display: block; }
.bench-history-toolbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 8px; }
.bench-history-filter { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--subtext); cursor: pointer; }
.perf-history-list { display: flex; flex-direction: column; gap: 0; overflow-x: auto; }
.perf-history-empty { font-size: 13px; color: var(--subtext); padding: 16px 0; }
.perf-history-row { display: grid; grid-template-columns: 118px minmax(96px,.8fr) 34px 72px 72px minmax(190px,1.4fr) 92px 82px 68px 70px 24px; min-width: 1010px; gap: 0 10px; padding: 7px 4px; border-bottom: 1px solid var(--border); font-size: 12px; align-items: center; }
.perf-history-row:last-child { border-bottom: none; }
.perf-history-head { font-size: 11px; color: var(--subtext); text-transform: uppercase; letter-spacing: .05em; font-weight: 600; }
.perf-history-sort { display: inline-flex; align-items: center; gap: 3px; max-width: 100%; padding: 0; border: 0; background: transparent; color: inherit; font: inherit; text-transform: inherit; letter-spacing: inherit; cursor: pointer; text-align: left; }
.perf-history-sort:hover, .perf-history-sort.active { color: var(--accent); }
.perf-history-sort .mdi { font-size: 13px; line-height: 1; }
.perf-history-avatar { width: 24px; height: 24px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; overflow: hidden; color: #fff; font-size: 11px; font-weight: 700; }
.perf-history-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.perf-history-avatar-icon { width: 24px !important; height: 24px !important; }
.perf-history-avatar-init { flex-shrink: 0; }
.perf-history-ts { color: var(--subtext); font-size: 11px; }
.perf-history-del { cursor: pointer; color: var(--subtext); font-size: 11px; text-align: right; }
.perf-history-del:hover { color: var(--red); }
.batch-voice-toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.batch-search-wrap { display: flex; align-items: center; gap: 7px; min-width: min(300px, 100%); flex: 1 1 260px; height: 34px; padding: 0 10px; border: 1px solid var(--border); border-radius: 7px; background: var(--panel); color: var(--subtext); }
.batch-search-wrap input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--text); font-size: 13px; }
.batch-voice-list { display: flex; flex-direction: column; gap: 0; max-height: 320px; overflow-y: auto; border: 1px solid var(--border); border-radius: 7px; background: var(--panel); }
.batch-voice-item { display: grid; grid-template-columns: auto auto minmax(0,1fr) auto auto auto; align-items: center; gap: 9px; padding: 7px 10px; cursor: pointer; font-size: 13px; border-bottom: 1px solid var(--border); transition: background .1s; }
.batch-voice-item:last-child { border-bottom: none; }
.batch-voice-item:hover { background: var(--hover); }
.batch-voice-item.is-selected { background: rgba(37,99,235,.08); }
.batch-voice-item.is-active .batch-voice-name { font-weight: 700; }
.batch-voice-avatar { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; color: #fff; font-size: 12px; font-weight: 700; }
.batch-voice-main { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.batch-voice-name, .batch-voice-id { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.batch-voice-name { color: var(--text); font-weight: 600; }
.batch-voice-id { color: var(--subtext); font-size: 11px; font-family: monospace; }
.batch-voice-meta { font-size: 11px; color: var(--subtext); white-space: nowrap; }
.batch-voice-stats { font-size: 11px; color: var(--subtext); font-variant-numeric: tabular-nums; white-space: nowrap; }
.batch-voice-tag { font-size: 10px; padding: 1px 6px; border-radius: 10px; background: rgba(var(--accent-rgb,99,102,241),.15); color: var(--accent); font-weight: 600; white-space: nowrap; }
@media (max-width: 700px) { .batch-voice-item { grid-template-columns: auto auto minmax(0,1fr); } .batch-voice-stats, .batch-voice-tag { grid-column: 3; justify-self: start; } }
.batch-progress { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.batch-progress-head { display: flex; justify-content: space-between; font-size: 12px; color: var(--subtext); }
.batch-progress-track { height: 6px; border-radius: 3px; background: var(--border); overflow: hidden; }
.batch-progress-bar { height: 100%; border-radius: 3px; background: var(--accent); transition: width .3s; width: 0%; }
.bench-tabs {
display: flex; gap: 4px; flex-wrap: wrap; align-items: flex-end;
margin: 0; padding: 0 0 0 0; border-bottom: none;
}
.bench-tab {
display: inline-flex; align-items: center; justify-content: center; gap: 7px;
padding: 11px 18px; border: 1px solid transparent; border-bottom: none;
background: transparent; color: var(--subtext); font-size: 14px; font-weight: 700;
border-radius: 10px 10px 0 0; cursor: pointer; font-family: inherit;
position: relative; bottom: -1px;
}
.bench-tab:hover { background: var(--surface); color: var(--text); filter: none; }
.bench-tab.active { background: var(--surface); color: var(--accent); border-color: var(--border); border-bottom-color: var(--surface); }
.bench-tab.active::after { content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 2px; background: var(--accent); border-radius: 2px 2px 0 0; }
.bench-tab .mdi { font-size: 18px; }
.bench-tab span:last-child { font-size: 11px; font-weight: 600; color: var(--subtext); }
.bench-pane { display: none; }
.bench-pane.active { display: flex; flex-direction: column; gap: 14px; margin-top: 0; }
.bench-pane.active > .card:first-child { border-top-left-radius: 0; }
.bench-card { gap: 14px; }
.bench-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.bench-card-head h3 { margin: 0; font-size: 15px; color: var(--text); }
.bench-card-head p { margin: 4px 0 0; font-size: 13px; color: var(--subtext); line-height: 1.45; max-width: 920px; }
.bench-input-grid { align-items: end; }
.bench-library-source { margin: 2px 0 4px; max-width: 760px; }
.bench-source-row { display: flex; gap: 8px; align-items: center; }
.bench-source-row select { flex: 1; min-width: 220px; }
.bench-source-note { margin-top: 5px; color: var(--subtext); font-size: 12px; }
.bench-source-row .bvp-root { flex: 1 1 360px; min-width: min(360px, 100%); }
.bvp-root { position: relative; display: inline-flex; flex-direction: column; min-width: 260px; flex: 1 1 300px; }
.bvp-trigger {
width: 100%; min-height: 34px; display: flex; align-items: center; justify-content: space-between; gap: 8px;
padding: 0 10px; cursor: pointer; background: var(--input-bg, var(--panel)); color: var(--text);
border: 1px solid var(--border); border-radius: var(--radius, 8px); text-align: left; user-select: none;
}
.bvp-trigger:hover, .bvp-trigger.open { border-color: var(--accent); filter: none; }
.bvp-trigger-content { min-width: 0; flex: 1; display: flex; align-items: center; gap: 8px; overflow: hidden; }
.bvp-trigger-main { min-width: 0; display: flex; flex-direction: column; line-height: 1.15; }
.bvp-trigger-name { min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; color: var(--text); }
.bvp-trigger-stats { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; color: var(--subtext); font-variant-numeric: tabular-nums; }
.bvp-placeholder { font-size: 13px; color: var(--subtext); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bvp-chevron { color: var(--subtext); flex-shrink: 0; transition: transform .15s; }
.bvp-trigger.open .bvp-chevron { transform: rotate(180deg); }
.bvp-avatar { flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; }
.bvp-drop[hidden] { display: none !important; }
.bvp-drop {
position: absolute; z-index: 245; top: calc(100% + 4px); left: 0; right: 0; min-width: min(520px, 92vw);
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius, 8px);
box-shadow: 0 10px 28px rgba(0,0,0,.18); overflow: hidden;
}
.bvp-search-wrap { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-bottom: 1px solid var(--border); color: var(--subtext); background: var(--panel); }
.bvp-search { flex: 1; min-width: 0; border: none; outline: none; background: transparent; color: var(--text); font-size: 13px; }
.bvp-list { max-height: 340px; overflow-y: auto; padding: 4px; }
.bvp-item {
width: 100%; display: flex; align-items: center; gap: 9px; padding: 7px 8px;
border: 0; border-radius: 6px; background: transparent; color: var(--text); text-align: left; cursor: pointer;
}
.bvp-item:hover, .bvp-item:focus { background: var(--hover); outline: none; filter: none; }
.bvp-item.selected { background: rgba(37,99,235,.12); color: var(--accent); }
.bvp-item-main { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 1px; }
.bvp-item-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 600; }
.bvp-item-sub { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; color: var(--subtext); }
.bvp-item-stats { flex-shrink: 0; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; color: var(--subtext); font-variant-numeric: tabular-nums; }
.bvp-empty { padding: 14px 12px; text-align: center; color: var(--subtext); font-size: 12px; }
.bench-inline-controls .bvp-root { min-width: min(340px, 100%); flex: 1 1 340px; }
@media (max-width: 700px) { .bench-source-row { flex-direction: column; align-items: stretch; } .bvp-drop { min-width: 100%; } .bvp-item-stats { max-width: 110px; } }
.bench-engine-panel { border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); overflow: hidden; }
.bench-engine-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 12px; border-bottom: 1px solid var(--border); font-size: 13px; }
.bench-engine-head span { color: var(--subtext); }
.bench-engine-list { max-height: 420px; min-height: 180px; overflow: auto; display: flex; flex-direction: column; resize: vertical; }
.bench-engine-empty, .bench-empty { color: var(--subtext); font-size: 13px; padding: 16px; text-align: left; }
.bench-engine-item {
display: grid; grid-template-columns: auto minmax(180px, 1fr) auto minmax(160px, .45fr);
gap: 10px; align-items: center; padding: 9px 12px; border-bottom: 1px solid var(--border);
cursor: pointer; background: var(--surface);
}
.bench-engine-item:last-child { border-bottom: none; }
.bench-engine-item:hover { background: color-mix(in srgb, var(--panel) 70%, var(--surface)); }
.bench-engine-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.bench-engine-main strong { font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bench-engine-main small { font-size: 11px; color: var(--subtext); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: monospace; }
.bench-engine-state { font-size: 11px; font-weight: 700; padding: 2px 7px; border-radius: 999px; background: var(--panel); color: var(--subtext); border: 1px solid var(--border); }
.bench-engine-item.is-online .bench-engine-state { color: var(--green); background: rgba(22,163,74,.09); border-color: rgba(22,163,74,.28); }
.bench-engine-item.is-offline .bench-engine-state { color: var(--red); background: rgba(220,38,38,.07); border-color: rgba(220,38,38,.24); }
.bench-engine-model { min-width: 0; }
.bench-model-picker { position: relative; min-width: 0; }
.bench-model-trigger {
width: 100%; min-height: 32px; display: flex; align-items: center; justify-content: space-between; gap: 8px;
background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 5px;
padding: 6px 8px; font-family: monospace; font-size: 12px; cursor: pointer; text-align: left;
}
.bench-model-trigger.open, .bench-model-trigger:hover { border-color: var(--accent); filter: none; }
.bench-model-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bench-model-menu {
position: absolute; z-index: 240; top: calc(100% + 4px); left: 0; right: 0;
background: var(--surface); border: 1px solid var(--border); border-radius: 7px; box-shadow: var(--shadow);
overflow: hidden; min-width: min(520px, 90vw);
}
.bench-model-menu[hidden] { display: none !important; }
.bench-model-search-row { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-bottom: 1px solid var(--border); color: var(--subtext); }
.bench-model-search { flex: 1; min-width: 0; border: none; outline: none; background: transparent; color: var(--text); font-size: 13px; }
.bench-model-options { max-height: 260px; overflow: auto; padding: 4px; }
.bench-model-option { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 9px; border: 0; border-radius: 5px; background: transparent; color: var(--text); font-family: monospace; font-size: 12px; cursor: pointer; text-align: left; }
.bench-model-option:hover, .bench-model-option.selected { background: var(--hover); filter: none; }
.bench-model-option.selected { color: var(--accent); font-weight: 700; }
.bench-model-empty { color: var(--subtext); font-size: 12px; padding: 12px; }
.bench-status { font-size: 13px; color: var(--subtext); }
.bench-summary { display: flex; gap: 10px 18px; flex-wrap: wrap; min-height: 20px; }
.bench-table td strong { display: block; }
.bench-table td small { display: block; color: var(--subtext); font-size: 11px; font-family: monospace; max-width: 280px; overflow: hidden; text-overflow: ellipsis; }
.bench-output { max-width: 680px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bench-device { display: inline-flex; align-items: center; padding: 2px 7px; border-radius: 999px; background: var(--panel); border: 1px solid var(--border); color: var(--subtext); font-size: 11px; font-weight: 700; }
.bench-device.gpu { color: var(--green); background: rgba(22,163,74,.09); border-color: rgba(22,163,74,.28); }
.bench-device.cpu { color: var(--yellow); background: rgba(217,119,6,.09); border-color: rgba(217,119,6,.28); }
.bench-device.cloud { color: var(--accent); background: rgba(37,99,235,.08); border-color: rgba(37,99,235,.24); }
.bench-inline-controls { display: flex; gap: 6px; min-width: min(620px, 100%); }
.bench-inline-controls input, .bench-inline-controls select { min-width: 0; }
.bench-turn-main .bench-turn-log { min-height: 440px; overflow-y: auto; padding: 16px; }
.bench-turn-log audio { width: min(520px, 100%); margin: 8px 0 0; }
@media (max-width: 900px) {
.bench-engine-item { grid-template-columns: auto minmax(0, 1fr); }
.bench-engine-state, .bench-engine-model { grid-column: 2; }
.bench-inline-controls { flex-wrap: wrap; min-width: 0; }
.bench-inline-controls input, .bench-inline-controls select, .bench-inline-controls .bvp-root { flex: 1 1 180px; }
}
@media (max-width: 560px) {
.bench-tab span:not(.mdi) { display: none; }
.bench-tab { padding: 9px 12px; }
}
/* ── Chunked TTS toggle ──────────────────────────────────────────────────── */
.chunk-toggle-label {
display: inline-flex; align-items: center; gap: 6px;
font-size: 13px; color: var(--subtext); cursor: pointer; user-select: none;
}
.chunk-toggle-label input { cursor: pointer; }
.chunk-progress {
font-size: 12px; color: var(--accent); padding: 6px 0 0;
display: flex; align-items: center; gap: 6px;
}
.chunk-progress::before { content: '⏳'; font-size: 13px; }
/* ── Effects panel ───────────────────────────────────────────────────────── */
.effects-preset-row {
display: flex; align-items: center; gap: 10px;
flex-wrap: wrap; margin-bottom: 16px;
}
.field-label-sm { font-size: 12px; font-weight: 600; color: var(--subtext); white-space: nowrap; }
.effects-grid { display: flex; flex-direction: column; gap: 14px; }
.fx-row { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.fx-toggle {
display: flex; align-items: center; gap: 6px;
font-size: 13px; font-weight: 600; color: var(--text);
min-width: 120px; flex-shrink: 0; cursor: pointer; user-select: none;
padding: 4px 0;
}
.fx-toggle input { cursor: pointer; }
.fx-sliders {
display: flex; flex-wrap: wrap; gap: 8px 20px; flex: 1; min-width: 0;
}
.fx-sliders label {
display: flex; align-items: center; gap: 8px;
font-size: 12px; color: var(--subtext); white-space: nowrap;
}
.fx-sliders input[type=range] { width: 110px; cursor: pointer; }
.fx-sliders span { font-size: 11px; color: var(--text); font-variant-numeric: tabular-nums; min-width: 44px; }
/* ── History panel ───────────────────────────────────────────────────────── */
.history-list { display: flex; flex-direction: column; gap: 8px; }
.history-empty { font-size: 13px; color: var(--subtext); padding: 12px 0; }
/* ── Voice Picker ───────────────────────────────────────────────────────── */
.vp-root { position: relative; display: inline-flex; flex-direction: column; min-width: 200px; flex: 1 1 200px; }
.vp-trigger {
display: flex; align-items: center; justify-content: space-between; gap: 8px;
padding: 0 10px; height: 34px; cursor: pointer;
background: var(--input-bg, var(--panel)); border: 1px solid var(--border);
border-radius: var(--radius, 8px); user-select: none;
transition: border-color .15s;
}
.vp-trigger:hover, .vp-trigger.open { border-color: var(--accent); }
.vp-trigger-content { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; overflow: hidden; }
.vp-trigger-name { font-size: 13px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.vp-trigger-meta {
margin-left: auto; flex-shrink: 0; color: var(--subtext); font-size: 12px;
font-variant-numeric: tabular-nums; letter-spacing: 0;
}
.vp-trigger-placeholder { font-size: 13px; color: var(--subtext); }
.vp-chevron { font-size: 16px; color: var(--subtext); flex-shrink: 0; transition: transform .15s; }
.vp-trigger.open .vp-chevron { transform: rotate(180deg); }
.vp-avatar { flex-shrink: 0; }
.vp-flag { font-size: 13px; flex-shrink: 0; }
.vp-drop[hidden] { display: none !important; }
/* attachTextPicker's floating variant — appended to <body> and positioned in
JS (next to whatever text input it's browsing for), not inside a .vp-root. */
.vp-drop-floating { position: fixed; z-index: 2001; }
.route-output-wrap { position: relative; display: inline-flex; align-items: center; width: 100%; }
.route-output-wrap .route-output { flex: 1; min-width: 0; padding-right: 24px; }
.vp-text-browse {
position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
border: none; background: none; color: var(--subtext); cursor: pointer;
padding: 2px; line-height: 1; border-radius: 4px;
}
.vp-text-browse:hover { color: var(--accent); background: var(--panel); }
.vp-drop {
position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 200;
background: var(--card-bg, var(--panel)); border: 1px solid var(--border);
border-radius: var(--radius, 8px); box-shadow: 0 8px 24px rgba(0,0,0,.18);
display: flex; flex-direction: column; max-height: 320px; overflow: hidden;
}
.vp-search-wrap { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-bottom: 1px solid var(--border); flex-shrink: 0; }
.vp-search-icon { color: var(--subtext); font-size: 15px; }
.vp-search { flex: 1; background: none; border: none; outline: none; font-size: 13px; color: var(--text); }
.vp-list { overflow-y: auto; flex: 1; padding: 4px 0; }
.vp-item {
display: flex; align-items: center; gap: 8px;
padding: 6px 12px; cursor: pointer; font-size: 13px; color: var(--text);
}
.vp-item:hover, .vp-item:focus { background: rgba(37,99,235,.08); outline: none; }
.vp-item.selected { background: rgba(37,99,235,.13); font-weight: 600; }
.vp-item-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.vp-item-meta {
margin-left: auto; flex: 0 0 auto; min-width: 42px; text-align: right;
color: var(--subtext); font-size: 12px; font-weight: 600; letter-spacing: 0;
font-variant-numeric: tabular-nums;
}
.vp-empty { padding: 12px; text-align: center; font-size: 12px; color: var(--subtext); }
/* ── Generation History ─────────────────────────────────────────────────── */
.hist-avatar {
width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex-shrink: 0;
}
.hist-avatar-init {
display: inline-flex; align-items: center; justify-content: center;
font-size: 12px; font-weight: 700; color: #fff;
}
.hist-del-btn {
margin-left: auto; background: none; border: none; cursor: pointer;
color: var(--subtext); font-size: 14px; padding: 2px 4px; border-radius: 4px;
display: flex; align-items: center; opacity: .6; transition: opacity .15s, color .15s;
}
.hist-del-btn:hover { opacity: 1; color: var(--red, #ef4444); }
.history-item {
background: var(--panel); border: 1px solid var(--border);
border-radius: var(--radius); padding: 10px 12px;
display: flex; flex-direction: column; gap: 5px;
transition: border-color .15s;
}
.history-item:hover { border-color: rgba(37,99,235,.3); }
.history-item-row1 { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; }
.history-voice {
font-size: 12px; font-weight: 700; color: var(--accent);
background: rgba(37,99,235,.07); border: 1px solid rgba(37,99,235,.2);
border-radius: 4px; padding: 1px 7px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 200px;
}
.history-backend { font-size: 11px; color: var(--subtext); white-space: nowrap; }
.history-time { font-size: 11px; color: var(--subtext); font-variant-numeric: tabular-nums; white-space: nowrap; }
.history-item-text { font-size: 12px; color: var(--text); line-height: 1.4; }
.history-item-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.btn-xs {
font-size: 11px; padding: 3px 9px; border-radius: 5px;
}
/* ── Playlist panel ──────────────────────────────────────────────────────── */
.playlist-list { display: flex; flex-direction: column; gap: 6px; }
.playlist-item {
display: flex; align-items: center; gap: 10px;
background: var(--panel); border: 1px solid var(--border);
border-radius: var(--radius); padding: 8px 12px;
transition: border-color .15s;
}
.playlist-item:hover { border-color: rgba(37,99,235,.3); }
.playlist-num {
font-size: 12px; font-weight: 700; color: var(--subtext);
min-width: 18px; text-align: center;
}
.playlist-info { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.playlist-text { font-size: 12px; color: var(--subtext); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.playlist-item-actions { display: flex; gap: 4px; flex-shrink: 0; }
/* ── Refine panel ────────────────────────────────────────────────────────── */
.refine-config {
display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-start;
margin-bottom: 14px;
}
.refine-toggles {
display: flex; flex-wrap: wrap; gap: 8px 20px; margin-bottom: 4px;
}
.refine-toggle {
display: inline-flex; align-items: center; gap: 6px;
font-size: 13px; color: var(--text); cursor: pointer; user-select: none;
}
.refine-toggle input { cursor: pointer; }
/* ── Persona inspector panel ─────────────────────────────────────────────── */
.insp-persona-panel {
background: var(--panel); border: 1px solid var(--border);
border-radius: var(--radius); padding: 14px 16px;
margin: 12px 0; display: flex; flex-direction: column; gap: 10px;
}
.insp-persona-head { display: flex; flex-direction: column; gap: 3px; }
.insp-persona-title { font-size: 13px; font-weight: 700; color: var(--text); }
.insp-persona-hint { font-size: 11px; color: var(--subtext); line-height: 1.4; }
.insp-persona-input {
width: 100%; font-size: 13px; padding: 8px 10px;
border: 1px solid var(--border); border-radius: var(--radius);
background: var(--surface); color: var(--text);
font-family: var(--font); resize: vertical; min-height: 72px;
transition: border-color .15s;
}
.insp-persona-input:focus { border-color: var(--accent); outline: none; }
.insp-persona-actions { display: flex; align-items: center; gap: 10px; }
.insp-persona-status { font-size: 11px; color: var(--green); }
/* ── Preview persona button ──────────────────────────────────────────────── */
.preview-persona-btn {
font-size: 12px; padding: 4px 11px;
border: 1px solid var(--teal); color: var(--teal);
background: rgba(13,148,136,.06); border-radius: 5px;
cursor: pointer; font-family: var(--font); transition: background .15s;
}
.preview-persona-btn:hover { background: rgba(13,148,136,.12); }
.preview-persona-btn:disabled { opacity: .5; cursor: default; }
/* ── Seed Finder ─────────────────────────────────────────────────────────── */
.seed-finder-group { margin-top: 12px; }
.seed-finder-body { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 12px; }
.seed-finder-config { display: flex; flex-direction: column; gap: 10px; }
.seed-finder-row { display: flex; flex-direction: column; gap: 5px; }
.seed-finder-label { font-size: 12px; font-weight: 600; color: var(--subtext); }
.seed-finder-text {
width: 100%; font-size: 13px; padding: 8px 10px;
border: 1px solid var(--border); border-radius: var(--radius);
background: var(--surface); color: var(--text);
font-family: var(--font); resize: vertical; min-height: 68px;
transition: border-color .15s;
}
.seed-finder-text:focus { border-color: var(--accent); outline: none; }
.seed-finder-params { flex-direction: row; flex-wrap: wrap; align-items: flex-end; gap: 14px; }
.seed-finder-field { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text); }
.seed-finder-field input[type="number"] {
width: 64px; padding: 5px 7px; font-size: 13px;
border: 1px solid var(--border); border-radius: var(--radius);
background: var(--surface); color: var(--text); text-align: center;
}
.seed-finder-field select {
padding: 5px 8px; font-size: 13px;
border: 1px solid var(--border); border-radius: var(--radius);
background: var(--surface); color: var(--text);
}
.seed-finder-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.seed-finder-status { font-size: 12px; color: var(--subtext); }
.seed-finder-pin { margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--border); }
.seed-finder-pin-controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.seed-finder-pin-input { width: 90px; padding: 5px 8px; border: 1px solid var(--border); border-radius: 7px; background: var(--panel); color: var(--text); font-family: var(--font); }
.seed-finder-pin-status { font-size: 12px; color: var(--accent); font-weight: 600; }
.seed-finder-progress { display: flex; flex-direction: column; gap: 6px; }
.seed-finder-progress-head { display: flex; justify-content: space-between; font-size: 12px; color: var(--subtext); }
.seed-finder-bar { height: 100%; background: var(--accent); transition: width .2s ease; border-radius: 999px; }
.seed-finder-results { display: flex; flex-direction: column; gap: 6px; }
.seed-finder-result-row {
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
padding: 7px 10px; border-radius: var(--radius);
border: 1px solid var(--border); background: var(--surface);
font-size: 13px;
}
.seed-finder-result-row.sfr-active { border-color: var(--accent); background: rgba(var(--accent-rgb, 124,77,255),.07); }
.seed-finder-result-row.seed-finder-result-error { opacity: .6; }
.sfr-seed { font-weight: 700; min-width: 58px; color: var(--text); }
.sfr-dur { color: var(--subtext); font-size: 12px; min-width: 170px; flex: 1 1 210px; }
.sfr-play-btn { font-size: 12px; padding: 4px 10px; }
.sfr-use-btn { font-size: 12px; padding: 4px 10px; }
.sfr-saved { font-size: 12px; color: var(--green); font-weight: 600; }
.sfr-error { font-size: 12px; color: var(--red); }
.sfr-batch-header {
font-size: 12px; color: var(--subtext); font-style: italic;
padding: 4px 2px 2px;
}
.sfr-batch-tag { color: var(--accent); font-style: italic; }
.seed-finder-result-row.sfr-batch { background: rgba(var(--accent-rgb, 124,77,255),.03); }
/* ── Conversation Playground ─────────────────────────────────────────────── */
.conv-config-bar { padding: 14px 18px 10px; margin-bottom: 0; }
/* Conversation: stack STT · LLM · TTS · System prompt full-width, one per row */
.conv-config-bar .engine-setup-row { flex-direction: column; flex-wrap: nowrap; gap: 12px; }
.conv-config-bar .engine-setup-col {
flex: 1 1 auto; width: 100%; min-width: 0;
border-right: none; padding-right: 0;
border-bottom: 1px solid var(--border); padding-bottom: 12px;
}
.conv-config-bar .engine-setup-col:last-child { border-bottom: none; padding-bottom: 0; }
.conv-config-bar .conv-prompt-row { margin-top: 12px; }
.conv-config-bar .conv-system-textarea { width: 100%; }
/* ── Unified Engine Config Rows (used across tools) ───────────────── */
.engine-setup-row {
display: flex; gap: 16px; flex-wrap: wrap; align-items: flex-start;
margin-bottom: 16px; padding: 12px 14px; background: rgba(0,0,0,0.02);
border: 1px solid var(--border); border-radius: 8px;
}
.engine-setup-col {
flex: 1; min-width: 220px; display: flex; flex-direction: column; gap: 6px;
border-right: 1px solid var(--border); padding-right: 16px;
}
.engine-setup-col:last-child, .engine-setup-col.no-border {
border-right: none; padding-right: 0;
}
.engine-setup-label {
font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--subtext);
display: flex; align-items: center; gap: 6px; margin-bottom: 2px;
}
.engine-setup-label .mdi { font-size: 14px; }
.engine-setup-link {
color: var(--subtext); opacity: 0.6; transition: opacity 0.15s, color 0.15s;
margin-left: auto; /* Push gear to the right */
}
.engine-setup-link:hover { opacity: 1; color: var(--accent); }
.engine-setup-controls {
display: flex; gap: 6px; align-items: center; width: 100%; flex-wrap: wrap;
}
.engine-setup-controls select, .engine-setup-controls input[type="text"] {
flex: 1; min-width: 0;
background: var(--bg); border: 1px solid var(--border); color: var(--text);
border-radius: var(--radius); padding: 8px 12px; font-size: 14px;
}
.conv-config-row { display: flex; gap: 14px; flex-wrap: wrap; align-items: flex-end; }
.conv-config-group { display: flex; flex-direction: column; gap: 4px; }
.conv-config-group--actions { margin-left: auto; }
.conv-cfg-label { font-size: 11px; font-weight: 700; color: var(--subtext); text-transform: uppercase; letter-spacing: .06em; }
.conv-url-inp { width: 220px; padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 13px; background: var(--surface); color: var(--text); }
.conv-prompt-row { display: flex; align-items: flex-start; gap: 10px; margin-top: 10px; border-top: 1px solid var(--border); padding-top: 10px; }
.conv-prompt-row .conv-cfg-label { padding-top: 7px; white-space: nowrap; }
.conv-system-textarea { flex: 1; resize: vertical; min-height: 34px; max-height: 120px; padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 13px; font-family: var(--font); background: var(--surface); color: var(--text); }
/* Layout */
.conv-main { display: flex; gap: 14px; margin-top: 14px; }
/* Chat panel grows to fill remaining height; input bar stays pinned at bottom */
.conv-chat-panel {
flex: 1; display: flex; flex-direction: column; gap: 0; min-width: 0;
height: calc(100vh - 340px); min-height: 440px;
}
/* Collapsible engine/prompt config */
.conv-config-toggle {
display: flex; align-items: center; gap: 8px; cursor: pointer;
font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
color: var(--subtext); user-select: none; padding-bottom: 2px;
}
.conv-config-toggle:hover { color: var(--text); }
.conv-config-toggle .conv-config-chevron { margin-left: auto; transition: transform .18s ease; font-size: 18px; }
.conv-config-summary { font-weight: 500; text-transform: none; letter-spacing: 0; opacity: .8; font-size: 11.5px; }
.conv-config-body { margin-top: 10px; }
.conv-config-bar.collapsed .conv-config-body { display: none; }
.conv-config-bar.collapsed .conv-config-chevron { transform: rotate(180deg); }
.conv-config-bar.collapsed .conv-config-summary { display: inline; }
.conv-config-bar:not(.collapsed) .conv-config-summary { display: none; }
/* Desktop: make the Conversation fill the viewport height — no page scroll;
only the chat window scrolls internally. Collapsing the config frees space. */
@media (min-width: 768px) {
#s-conversation.is-active { display: flex; flex-direction: column; height: 100%; min-height: 0; }
#s-conversation .conv-main { flex: 1; min-height: 0; margin-top: 12px; }
#s-conversation .conv-chat-panel { height: auto; min-height: 0; }
#s-conversation .conv-stats-panel { overflow-y: auto; }
}
/* Read Aloud — fit the document area into the viewport height so the transport
+ synthesise bar below it stay visible (only the document scrolls). */
@media (min-width: 768px) {
#s-reader.is-active, #s-caststudio.is-active { display: flex; flex-direction: column; height: 100%; min-height: 0; }
#s-reader #tab-reader { flex: 1; min-height: 0; display: flex; flex-direction: column; }
#s-caststudio #tab-reader { flex: 1; min-height: 0; display: flex; flex-direction: column; }
#s-reader #reader-main-view { flex: 1; min-height: 0; display: flex; flex-direction: column; }
#s-caststudio #reader-main-view { flex: 1; min-height: 0; display: flex; flex-direction: column; }
#s-reader #reader-main-view[hidden] { display: none; }
#s-caststudio #reader-main-view[hidden] { display: none; }
#s-reader #reader-doc { flex: 1; min-height: 0; overflow-y: auto; }
#s-caststudio #reader-doc { flex: 1; min-height: 0; overflow-y: auto; }
}
.conv-stats-panel { width: 280px; flex-shrink: 0; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; display: flex; flex-direction: column; gap: 8px; }
/* Chat window fills the space above the input bar; warning box scrolls inside it */
.conv-chat-window { flex: 1; min-height: 0; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius) var(--radius) 0 0; padding: 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; }
.conv-chat-welcome { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; flex: 1; color: var(--subtext); text-align: center; }
/* Bubbles */
.conv-bubble-wrap { display: flex; flex-direction: column; max-width: 72%; }
.conv-bubble-wrap--user { align-self: flex-end; align-items: flex-end; }
.conv-bubble-wrap--assistant { align-self: flex-start; align-items: flex-start; }
.conv-bubble { padding: 10px 14px; border-radius: 16px; font-size: 14.5px; line-height: 1.55; word-break: break-word; }
.conv-bubble--user { background: var(--accent); color: #fff; border-bottom-right-radius: 4px; }
.conv-bubble--assistant { background: var(--panel); color: var(--text); border: 1px solid var(--border); border-bottom-left-radius: 4px; }
.conv-bubble--error { background: rgba(220,38,38,.08); color: var(--red); border: 1px solid rgba(220,38,38,.2); border-radius: 10px; padding: 8px 12px; font-size: 13px; }
.conv-bubble-meta { font-size: 11px; color: var(--subtext); margin-top: 3px; padding: 0 4px; }
/* Typing dots */
.conv-typing { display: inline-flex; gap: 4px; align-items: center; padding: 4px 2px; }
.conv-typing span { width: 7px; height: 7px; border-radius: 50%; background: var(--subtext); opacity: .4; animation: convDot 1.2s infinite; }
.conv-typing span:nth-child(2) { animation-delay: .2s; }
.conv-typing span:nth-child(3) { animation-delay: .4s; }
@keyframes convDot { 0%,80%,100% { transform: scale(.7); opacity:.3; } 40% { transform: scale(1); opacity:.9; } }
/* ── Collapsible "thinking" (reasoning) panel inside an assistant bubble ── */
.conv-think-wrap { border: 1px solid var(--border); border-radius: 10px; margin-bottom: 8px; background: var(--surface); overflow: hidden; }
.conv-think-toggle {
width: 100%; display: flex; align-items: center; gap: 6px; padding: 7px 10px;
background: none; border: none; cursor: pointer; font-family: inherit;
font-size: 12.5px; font-weight: 600; color: var(--subtext); text-align: left;
}
.conv-think-toggle:hover { color: var(--text); }
.conv-think-toggle .mdi { transition: transform .15s; font-size: 15px; }
.conv-think-toggle[aria-expanded="true"] .mdi { transform: rotate(90deg); }
.conv-think-body {
padding: 0 12px 10px; font-size: 12.5px; line-height: 1.5; color: var(--subtext);
max-height: 220px; overflow-y: auto; white-space: pre-wrap; word-break: break-word;
}
.conv-answer-text { white-space: pre-wrap; word-break: break-word; }
/* ── Conversation input bar (text field + send + mic) ───────────────────── */
.conv-input-bar {
background: var(--surface); border: 1px solid var(--border); border-top: none;
border-radius: 0 0 var(--radius) var(--radius); padding: 10px 16px 12px;
display: flex; flex-direction: column; gap: 8px;
}
.conv-mic-status { font-size: 13px; color: var(--subtext); min-height: 18px; }
.conv-text-row { display: flex; align-items: center; gap: 8px; }
.conv-text-inp {
flex: 1; min-width: 0; padding: 10px 14px; font-size: 14px; font-family: inherit;
border: 1.5px solid var(--border); border-radius: 22px;
background: var(--panel); color: var(--text); outline: none;
transition: border-color .15s;
}
.conv-text-inp:focus { border-color: var(--accent); }
.conv-text-inp::placeholder { color: var(--subtext); opacity: .7; }
.conv-send-btn {
flex-shrink: 0; width: 40px; height: 40px; border-radius: 50%;
border: none; background: var(--accent); color: #fff;
font-size: 17px; cursor: pointer; display: flex; align-items: center;
justify-content: center; transition: background .15s, transform .1s;
}
.conv-send-btn:hover:not(:disabled) { background: #1d4ed8; transform: scale(1.05); }
.conv-send-btn:disabled { opacity: .4; cursor: default; }
.conv-divider { width: 1px; height: 32px; background: var(--border); flex-shrink: 0; }
.conv-mic-btn {
flex-shrink: 0; width: 52px; height: 52px; border-radius: 50%;
border: 2px solid var(--accent); background: var(--accent); color: #fff;
font-size: 22px; cursor: pointer; display: flex; align-items: center;
justify-content: center; transition: background .15s, transform .1s, box-shadow .15s;
}
.conv-mic-btn:hover { background: #1d4ed8; }
.conv-mic-btn.live { background: var(--accent); border-color: var(--accent); box-shadow: 0 0 0 4px rgba(37,99,235,.16); }
.conv-mic-btn.live:not(.processing) { animation: convPulse 1.4s infinite; }
.conv-mic-btn.recording:not(.live) { background: var(--red); border-color: var(--red); animation: convPulse 1s infinite; }
.conv-mic-btn.processing { background: var(--yellow); border-color: var(--yellow); cursor: pointer; }
.conv-mic-btn.processing.live { background: var(--accent); border-color: var(--accent); }
@keyframes convPulse { 0%,100% { box-shadow: 0 0 0 0 rgba(220,38,38,.4); } 50% { box-shadow: 0 0 0 8px rgba(220,38,38,0); } }
.conv-mic-timer { font-size: 13px; font-variant-numeric: tabular-nums; color: var(--red); min-width: 36px; text-align: right; }
.conv-vad-label { display: flex; align-items: center; gap: 4px; font-size: 11px; color: var(--subtext); cursor: pointer; white-space: nowrap; user-select: none; }
.conv-vad-label input { cursor: pointer; accent-color: var(--accent); }
/* Noise gate row — grouped with the mic controls, not a full-width row */
.conv-gate-row { display: flex; align-items: center; gap: 6px; flex-shrink: 0; width: 96px; }
.conv-gate-label { font-size: 13px; color: var(--subtext); flex-shrink: 0; line-height: 1; }
.conv-gate-slider { flex: 1; min-width: 0; height: 3px; cursor: pointer; accent-color: var(--accent); }
.conv-level-wrap { position: relative; flex: 1; min-width: 0; height: 6px; background: var(--panel); border-radius: 3px; margin: 0; overflow: visible; display: none; }
.conv-level-wrap.active { display: block; }
.conv-level-fill { height: 100%; background: var(--red); border-radius: 3px; width: 0%; transition: width .07s linear; }
.conv-level-gate { position: absolute; top: -2px; bottom: -2px; width: 2px; background: var(--accent); border-radius: 1px; pointer-events: none; }
.conv-text-inp.listening { border-color: var(--red); font-style: italic; color: var(--subtext); }
/* Stats panel collapsible */
.conv-stats-toggle-row { display: flex; align-items: center; justify-content: space-between; }
.conv-stats-collapse-btn { background: none; border: none; cursor: pointer; color: var(--subtext); font-size: 16px; line-height: 1; padding: 2px; border-radius: 4px; }
.conv-stats-collapse-btn:hover { color: var(--text); background: var(--panel); }
.conv-stats-panel.collapsed { width: 0 !important; padding: 0; overflow: hidden; border: none; min-width: 0; }
.conv-stats-expand-btn {
align-items: center; justify-content: center;
width: 32px; height: 32px; border-radius: 50%; background: var(--surface);
border: 1px solid var(--border); cursor: pointer; color: var(--subtext); font-size: 16px;
flex-shrink: 0; align-self: flex-start; margin-top: 4px;
}
.conv-stats-expand-btn:hover { color: var(--text); background: var(--panel); }
/* Stats panel */
.conv-stats-head { font-size: 10px; font-weight: 800; color: var(--subtext); text-transform: uppercase; letter-spacing: .08em; }
.conv-pipeline { display: flex; flex-direction: column; gap: 8px; }
.conv-pipe-step { display: grid; grid-template-columns: 1fr auto; grid-template-rows: auto auto; gap: 2px 8px; }
.conv-pipe-label { grid-column: 1; font-size: 12px; color: var(--subtext); }
.conv-pipe-val { grid-column: 2; grid-row: 1 / 3; font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text); align-self: center; text-align: right; min-width: 52px; }
.conv-pipe-bar { grid-column: 1; height: 4px; background: var(--panel); border-radius: 2px; overflow: hidden; }
.conv-pipe-fill { height: 100%; background: var(--teal); border-radius: 2px; width: 0%; transition: width .4s ease; }
.conv-pipe-total .conv-pipe-label { font-weight: 700; color: var(--text); }
.conv-pipe-total .conv-pipe-val { color: var(--accent); font-size: 15px; }
/* Turn history */
.conv-turn-history { display: flex; flex-direction: column; gap: 5px; overflow-y: auto; max-height: 220px; }
.conv-history-empty { font-size: 12px; color: var(--subtext); font-style: italic; }
.conv-hist-item { display: flex; align-items: center; gap: 6px; font-size: 12px; padding: 4px 6px; border-radius: 5px; background: var(--panel); }
.conv-hist-num { font-weight: 700; color: var(--subtext); min-width: 20px; }
.conv-hist-time { font-variant-numeric: tabular-nums; font-weight: 700; margin-left: auto; }
.conv-hist-ok { color: var(--green); }
.conv-hist-err { color: var(--red); }
/* ── Script Rehearser ───────────────────────────────────────────────────── */
.reh-phase[hidden] { display: none; }
/* ── IMSDb browser modal ────────────────────────────────────────────────── */
.reh-imsdb-modal {
position: fixed; inset: 0; z-index: 1000;
background: rgba(0,0,0,.55); display: flex; align-items: center; justify-content: center;
padding: 24px;
}
.reh-imsdb-modal[hidden] { display: none; }
.reh-imsdb-box {
background: var(--bg); border: 1px solid var(--border); border-radius: 14px;
width: 100%; max-width: 1100px; height: 88vh; display: flex; flex-direction: column;
box-shadow: 0 20px 60px rgba(0,0,0,.4); overflow: hidden;
}
.reh-imsdb-head {
display: flex; align-items: center; gap: 12px; padding: 14px 18px;
border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.reh-imsdb-head h3 { margin: 0; font-size: 15px; display: flex; align-items: center; gap: 7px; white-space: nowrap; }
.reh-imsdb-url-row { display:flex; align-items:center; gap:8px; padding:10px 18px; border-bottom:1px solid var(--border); background:var(--panel); }
.reh-imsdb-url-row .reh-imsdb-url-input { flex:1; min-width:0; height:32px; padding:0 10px; border:1px solid var(--border); border-radius:7px; background:var(--surface); color:var(--text); font-size:13px; }
.reh-imsdb-search {
flex: 1; height: 34px; padding: 0 12px; border: 1px solid var(--border);
border-radius: 8px; background: var(--input-bg, var(--panel)); color: var(--text); font-size: 13px;
}
.reh-imsdb-count { font-size: 12px; color: var(--subtext); white-space: nowrap; }
.reh-imsdb-grid {
flex: 1; overflow-y: auto; padding: 16px;
display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 14px;
align-content: start;
}
.reh-imsdb-loading { grid-column: 1/-1; text-align: center; padding: 40px; color: var(--subtext); font-size: 13px; display: flex; align-items: center; justify-content: center; gap: 10px; }
.reh-imsdb-load-error { grid-column: 1/-1; margin-bottom: 8px; padding: 10px 12px; border: 1px solid var(--red); border-left-width: 5px; border-radius: 8px; color: var(--red); background: rgba(220,38,38,.08); font-size: 13px; font-weight: 700; }
.reh-scripts-link { white-space: nowrap; }
.reh-imsdb-card {
cursor: pointer; border-radius: 8px; overflow: hidden; background: var(--card-bg, var(--panel));
border: 1px solid var(--border); transition: transform .12s, box-shadow .12s, border-color .12s;
display: flex; flex-direction: column;
}
.reh-imsdb-card:hover { transform: translateY(-3px); box-shadow: 0 8px 20px rgba(0,0,0,.25); border-color: var(--accent); }
/* Poster image: use padding-bottom trick for guaranteed 2:3 ratio regardless of parent */
.reh-imsdb-poster-wrap {
position: relative; width: 100%; padding-bottom: 150%; /* 2:3 ratio */ overflow: hidden; flex-shrink: 0;
}
.reh-imsdb-poster {
position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block;
}
.reh-imsdb-fallback {
position: absolute; inset: 0; width: 100%; height: 100%;
display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: 6px; color: rgba(255,255,255,.85); font-size: 28px; padding: 10px; box-sizing: border-box;
}
.reh-imsdb-fallback-title {
font-size: 11px; font-weight: 700; text-align: center; line-height: 1.35;
color: rgba(255,255,255,.95); text-shadow: 0 1px 4px rgba(0,0,0,.5);
overflow: hidden; display: -webkit-box;
-webkit-line-clamp: 4; -webkit-box-orient: vertical;
word-break: break-word; padding: 0 4px; max-width: 100%;
}
.reh-imsdb-meta { padding: 7px 9px; display: flex; flex-direction: column; gap: 2px; }
.reh-imsdb-title { font-size: 12px; font-weight: 600; color: var(--text); line-height: 1.25;
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.reh-imsdb-year { font-size: 11px; color: var(--subtext); }
/* IMSDb list view */
.reh-imsdb-grid.list-view {
display: flex; flex-direction: column; gap: 4px; padding: 12px 16px;
}
.reh-imsdb-grid.list-view .reh-imsdb-card {
flex-direction: row; align-items: center; gap: 0; height: 48px; border-radius: 6px;
}
.reh-imsdb-grid.list-view .reh-imsdb-card:hover { transform: none; box-shadow: 0 2px 8px rgba(0,0,0,.15); }
.reh-imsdb-grid.list-view .reh-imsdb-poster-wrap {
width: 32px; min-width: 32px; height: 48px; padding-bottom: 0; flex-shrink: 0;
}
.reh-imsdb-grid.list-view .reh-imsdb-fallback {
font-size: 13px; gap: 0;
}
.reh-imsdb-grid.list-view .reh-imsdb-fallback-title { display: none; }
.reh-imsdb-grid.list-view .reh-imsdb-poster {
position: static; width: 32px; height: 48px; object-fit: cover;
}
.reh-imsdb-grid.list-view .reh-imsdb-meta {
flex-direction: row; align-items: center; gap: 8px; padding: 0 12px; flex: 1; min-width: 0;
}
.reh-imsdb-grid.list-view .reh-imsdb-title {
display:block; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text); -webkit-line-clamp: unset; font-size: 13px; flex: 1;
}
.reh-imsdb-grid.list-view .reh-imsdb-card { background:var(--surface); }
.reh-imsdb-grid.list-view .reh-imsdb-year { margin-left: auto; white-space: nowrap; font-size: 11px; }
/* View toggle buttons in modal header */
.reh-imsdb-view-btns {
display: flex; gap: 2px; flex-shrink: 0;
}
.reh-imsdb-view-btn {
background: none; border: 1px solid var(--border); border-radius: 6px;
padding: 4px 8px; cursor: pointer; color: var(--subtext); font-size: 15px;
transition: background .12s, color .12s;
}
.reh-imsdb-view-btn:hover { background: var(--panel); color: var(--text); }
.reh-imsdb-view-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; }
/* Loading spinner */
@keyframes reh-spin { to { transform: rotate(360deg); } }
.reh-imsdb-spinner {
display: inline-block; width: 16px; height: 16px; border-radius: 50%;
border: 2px solid var(--border); border-top-color: var(--accent);
animation: reh-spin .7s linear infinite; flex-shrink: 0;
}
/* ── Page break marker ──────────────────────────────────────────────────── */
.reh-block-pagebreak {
display: flex; align-items: center; justify-content: center;
padding: 6px 0; margin: 4px 0; gap: 10px;
}
.reh-block-pagebreak::before, .reh-block-pagebreak::after {
content: ''; flex: 1; height: 1px; background: var(--border);
}
.reh-pagebreak-label {
font-size: 10px; color: var(--subtext); white-space: nowrap; letter-spacing: .04em;
}
/* ── Scroll mode (no A4 paper) ──────────────────────────────────────────── */
.reh-page-wrap:not(.paginated) .reh-a4-page {
box-shadow: none; border: none; border-radius: 0; min-height: unset;
padding: 24px 32px;
}
/* ── Train Mode ─────────────────────────────────────────────────────────── */
.reh-train-panel {
display: flex; flex-direction: column; gap: 10px;
padding: 12px 16px 16px;
}
.reh-train-header {
display: flex; align-items: center; gap: 10px; flex-shrink: 0;
}
.reh-train-badge {
display: inline-flex; align-items: center; gap: 5px;
font-size: 11px; font-weight: 800; letter-spacing: .08em;
color: var(--accent); background: rgba(37,99,235,.1);
border: 1px solid rgba(37,99,235,.25); border-radius: 6px; padding: 3px 10px;
}
.reh-train-progress { font-size: 13px; color: var(--subtext); font-variant-numeric: tabular-nums; }
.reh-train-cue, .reh-train-myline, .reh-train-rec, .reh-train-result { flex-shrink: 0; }
.reh-train-cue.no-cue { border-style: dashed; opacity: .7; }
.reh-train-cue.no-cue .reh-train-cue-text { color: var(--subtext); font-style: italic; }
.reh-train-cue-head, .reh-train-myline-head {
display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
}
.reh-train-cue-avatar { display: inline-flex; flex-shrink: 0; }
.reh-train-cue-speaker { font-size: 13px; font-weight: 700; color: var(--text); }
.reh-train-cue-tag {
font-size: 10px; font-weight: 700; letter-spacing: .06em;
background: rgba(37,99,235,.1); color: var(--accent);
border-radius: 4px; padding: 1px 7px; margin-left: 2px;
}
.reh-train-me-tag { background: rgba(16,185,129,.1); color: var(--green); }
.reh-train-cue-state { margin-left: auto; font-size: 12px; }
.reh-train-cue-text { font-size: 14px; line-height: 1.55; }
.reh-train-cue-block { display: flex; flex-direction: column; gap: 2px; margin-bottom: 8px; }
.reh-train-cue-block:last-child { margin-bottom: 0; }
.reh-train-cue-who { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
.reh-train-cue-line { font-style: italic; color: var(--subtext); }
.reh-train-my-text { font-size: 16px; color: var(--text); line-height: 1.6; font-weight: 600; min-height: 2em; }
.reh-train-rec-head {
display: flex; align-items: center; gap: 10px; font-size: 13px; font-weight: 600;
color: var(--text); margin-bottom: 6px;
}
.reh-train-rec-state { flex: 1; }
.reh-train-rec-timer { font-variant-numeric: tabular-nums; color: var(--red); font-weight: 700; font-size: 13px; }
.reh-train-meters { margin-top: 6px; }
.reh-train-result-head {
display: flex; align-items: center; gap: 8px;
font-size: 13px; font-weight: 700; color: var(--text); margin-bottom: 10px;
}
.reh-train-score { margin-left: auto; font-size: 15px; }
.reh-train-compare-row { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; }
.reh-train-compare-lbl { font-size: 11px; font-weight: 700; color: var(--subtext); white-space: nowrap; min-width: 58px; }
.reh-train-compare-text { font-size: 14px; line-height: 1.7; flex: 1; }
.tw-ok { color: var(--green); }
.tw-miss { color: var(--red); text-decoration: line-through; }
.tw-extra{ color: #f59e0b; }
.reh-train-controls {
display: flex; align-items: center; justify-content: center; gap: 10px;
margin-top: 4px; flex-shrink: 0; padding: 8px 0;
border-top: 1px solid var(--border);
}
.reh-train-rec-btn { color: var(--red) !important; }
.reh-impex-cat { font-size: 13px; font-weight: 700; color: var(--subtext); text-transform: uppercase; letter-spacing: .05em; margin: 16px 0 10px; }
.reh-impex-note { font-size: 12px; color: var(--subtext); margin: -4px 0 10px; }
.reh-impex-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.reh-impex-btn {
display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
gap: 6px; padding: 14px 18px; min-width: 100px;
background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px;
color: var(--text); font-size: 12px; font-weight: 600; cursor: pointer;
transition: border-color .15s, background .15s; text-align: center;
}
.reh-impex-btn .mdi { font-size: 22px; color: var(--accent); }
.reh-impex-btn:hover { border-color: var(--accent); background: rgba(var(--accent-rgb),.07); }
.reh-impex-btn--accent { border-color: rgba(var(--accent-rgb),.35); }
/* Library */
.reh-lib-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.reh-lib-list { display: flex; flex-direction: column; gap: 8px; }
.reh-lib-empty { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 28px 0; color: var(--subtext); }
.reh-lib-empty .mdi { font-size: 36px; opacity: .4; }
.reh-lib-empty p { text-align: center; font-size: 13px; line-height: 1.5; margin: 0; }
.reh-lib-row { display: flex; align-items: center; gap: 12px; padding: 10px 12px; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; flex-wrap: wrap; }
/* Phase 2 backend row */
.reh-cast2-backend { display: flex; gap: 10px; align-items: flex-end; margin-bottom: 14px; flex-wrap: wrap; }
.reh-narrator-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; margin-bottom: 8px; border-top: 1px solid var(--border); flex-wrap: wrap; }
.reh-cast-instruct-wrap { padding: 0 12px 8px; margin-top: -4px; }
.reh-cast-instruct { width: 100%; font-size: 11px; padding: 4px 8px; border: 1px solid var(--border); border-radius: 4px; background: var(--surface); color: var(--subtext); font-family: var(--font); }
.reh-cast-instruct:focus { outline: none; border-color: var(--accent); color: var(--text); }
.reh-lib-current { border-color: var(--accent); background: rgba(137,180,250,.06); }
.reh-lib-row-main { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.reh-lib-avatars { display: flex; gap: 4px; flex-shrink: 0; }
.reh-lib-info { min-width: 0; flex: 1; }
.reh-lib-info strong { display: block; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.reh-lib-progress-wrap { height: 3px; background: var(--border); border-radius: 2px; overflow: hidden; margin-top: 5px; }
.reh-lib-progress { height: 100%; background: var(--accent); }
.reh-lib-row-actions { display: flex; gap: 6px; align-items: center; flex-shrink: 0; }
/* Phase 1 */
.reh-new-script-head {
display: flex; align-items: center; gap: 14px; margin-bottom: 6px; flex-wrap: wrap;
}
.reh-script-title-inline {
flex: 1; min-width: 160px; max-width: 360px;
height: 32px; padding: 0 10px; border: 1px solid var(--border); border-radius: 6px;
background: var(--input-bg, var(--surface)); color: var(--text); font-size: 14px;
font-weight: 600; transition: border-color .15s;
}
.reh-script-title-inline:focus { outline: none; border-color: var(--accent); }
.reh-input-row { display: grid; grid-template-columns: 1fr 200px; gap: 14px; align-items: start; }
.reh-input-row textarea { min-height: 220px; font-family: monospace; font-size: 13px; width: 100%; resize: vertical; background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 10px; color: var(--text); }
.reh-input-side { display: flex; flex-direction: column; gap: 8px; }
/* ── Cast list: toolbar + Card/List view toggle ───────────────────────────── */
.reh-cast-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
.reh-cast-count { font-size: 13px; color: var(--subtext); font-weight: 600; }
.reh-view-toggle { display: inline-flex; border: 1px solid var(--border); border-radius: 9px; overflow: hidden; background: var(--panel); }
.reh-view-btn { display: inline-flex; align-items: center; gap: 5px; padding: 7px 14px; border: none; background: transparent; color: var(--subtext); font-size: 13px; font-weight: 600; cursor: pointer; font-family: var(--font); transition: background .12s, color .12s; }
.reh-view-btn + .reh-view-btn { border-left: 1px solid var(--border); }
.reh-view-btn:hover { color: var(--text); }
.reh-view-btn.active { background: var(--accent); color: #fff; }
.reh-view-btn .mdi { font-size: 16px; }
.reh-cast-controls { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; flex: 1; min-width: 0; justify-content: center; }
.reh-cast-ctl { font-size: 13px; padding: 6px 9px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); color: var(--text); font-family: var(--font); }
.reh-cast-ctl:focus { outline: none; border-color: var(--accent); }
.reh-cast-search { min-width: 150px; flex: 1 1 150px; max-width: 240px; }
.reh-cast-sortdir { display: inline-flex; align-items: center; justify-content: center; width: 34px; padding: 6px; cursor: pointer; color: var(--subtext); }
.reh-cast-sortdir:hover { color: var(--accent); border-color: var(--accent); }
.reh-cast-sortdir .mdi { font-size: 17px; }
/* ── Cast cards (shared) ──────────────────────────────────────────────────── */
.reh-cast-card { background: var(--panel); border: 1px solid var(--border); border-radius: 14px; display: flex; flex-direction: column; transition: border-color .15s, opacity .15s, box-shadow .15s; }
.reh-cast-card.reh-cast-narrator { border-color: var(--accent); }
.reh-cast-card.reh-cast-ignored { opacity: .5; }
.reh-cast-card.reh-cast-hidden-c { outline: 1px dashed var(--border); }
.reh-cc-head { display: flex; gap: 12px; }
.reh-cc-avatar { flex-shrink: 0; }
/* rounded-square portrait (not a circle) — overrides the inline border-radius:50% */
.reh-cc-avatar .reh-char-img, .reh-cc-avatar span, .reh-cc-avatar img { width: 64px !important; height: 64px !important; font-size: 28px !important; border-radius: 12px !important; }
.reh-cc-titles { flex: 1; min-width: 0; }
.reh-cc-name { font-size: 16px; font-weight: 800; line-height: 1.15; white-space: normal; overflow-wrap: anywhere; word-break: break-word; }
.reh-cc-sub { font-size: 12px; color: var(--subtext); margin-top: 3px; line-height: 1.3; }
.reh-cc-voicechip { display: inline-flex; align-items: center; gap: 5px; margin-top: 7px; font-size: 11px; font-weight: 600; color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); padding: 3px 9px; border-radius: 999px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.reh-cc-voicechip.empty { color: var(--subtext); background: var(--surface); }
.reh-cc-sample-btn { margin-top: 7px; display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); color: var(--accent); cursor: pointer; font-family: var(--font); transition: background .12s; }
.reh-cc-sample-btn:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.reh-cc-sample-btn.playing { background: var(--accent); color: #fff; }
.reh-cc-sample-btn.loading { pointer-events: none; opacity: .8; }
.reh-cc-sample-btn.loading .mdi { animation: spin .8s linear infinite; }
.reh-cc-sample-btn .mdi { font-size: 13px; }
.reh-cc-voicechip .mdi { font-size: 13px; }
.reh-cc-occupation { font-size: 11.5px; color: var(--subtext); font-style: italic; margin-top: 2px; line-height: 1.3; }
.reh-cc-emotions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 7px; }
.reh-cc-emo-chip {
font-size: 10.5px; font-weight: 600; padding: 2px 7px; border-radius: 999px;
background: var(--panel); border: 1px solid var(--border); color: var(--text); white-space: nowrap;
}
.reh-cc-actions { display: flex; align-items: center; gap: 5px; }
.reh-cc-actions-spacer { flex: 1; }
.reh-cc-me-row { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--subtext); cursor: pointer; white-space: nowrap; }
.reh-cc-me-row:hover { color: var(--text); }
.reh-cc-me-row .mdi { font-size: 15px; }
.reh-cc-extra { display: flex; flex-direction: column; gap: 8px; }
/* ── Card view: "character card" look ─────────────────────────────────────── */
.reh-cast-view-card { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 16px; }
.reh-cast-view-card .reh-cast-card { overflow: hidden; }
.reh-cast-view-card .reh-cast-card:hover { box-shadow: 0 6px 22px rgba(0,0,0,.10); }
.reh-cast-view-card .reh-cc-head { flex-direction: column; align-items: center; text-align: center; gap: 10px; padding: 22px 18px 16px; background: linear-gradient(180deg, color-mix(in srgb, var(--cc-color, var(--accent)) 24%, var(--panel)), var(--panel)); border-bottom: 1px solid var(--border); }
.reh-cast-view-card .reh-cc-titles { flex: none; display: flex; flex-direction: column; align-items: center; }
.reh-cast-view-card .reh-cc-avatar .reh-char-img, .reh-cast-view-card .reh-cc-avatar span, .reh-cast-view-card .reh-cc-avatar img { width: 104px !important; height: 104px !important; font-size: 44px !important; border-width: 3px !important; box-shadow: 0 4px 14px rgba(0,0,0,.20); }
.reh-cast-view-card .reh-cc-name { font-size: 22px; }
.reh-cast-view-card .reh-cc-actions { padding: 10px 16px; border-bottom: 1px solid var(--border); }
.reh-cast-view-card .reh-cc-body { padding: 14px 16px 16px; gap: 10px; }
/* ── List view: compact rows ──────────────────────────────────────────────── */
.reh-cast-view-list { display: flex; flex-direction: column; gap: 8px; }
.reh-cast-view-list .reh-cast-card { flex-direction: row; align-items: center; flex-wrap: wrap; gap: 14px; padding: 10px 14px; border-radius: 10px; }
.reh-cast-view-list .reh-cc-head { flex: 1; min-width: 200px; align-items: center; gap: 12px; padding: 0; background: none; border: none; }
.reh-cast-view-list .reh-cc-avatar .reh-char-img, .reh-cast-view-list .reh-cc-avatar span, .reh-cast-view-list .reh-cc-avatar img { width: 52px !important; height: 52px !important; font-size: 22px !important; }
.reh-cast-view-list .reh-cc-titles { flex: 1; }
.reh-cast-view-list .reh-cc-name { font-size: 16px; }
.reh-cast-view-list .reh-cc-voicechip { margin-top: 4px; }
.reh-cast-view-list .reh-cc-body { order: 2; flex: 0 0 240px; padding: 0; }
.reh-cast-view-list .reh-cc-extra { display: none; } /* full editor lives in Card view */
.reh-cast-view-list .reh-cc-voice > label { display: none; }
.reh-cast-view-list .reh-cc-actions { order: 3; padding: 0; }
.reh-cast-view-list .reh-cc-actions-spacer { display: none; }
@media (max-width: 620px) {
.reh-cast-view-list .reh-cc-body { flex-basis: 100%; }
}
/* ── Online voice picker (try / alternatives / agree) ─────────────────────── */
.reh-cc-online { border: 1px solid var(--border); border-radius: 9px; background: var(--surface); padding: 9px; display: flex; flex-direction: column; gap: 7px; }
.reh-cc-online-head { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--subtext); display: flex; align-items: center; gap: 6px; }
.reh-vo-toggle { margin-left: auto; background: none; border: none; color: var(--accent); font-size: 11px; font-weight: 700; cursor: pointer; font-family: inherit; }
.reh-vo-list { display: flex; flex-direction: column; gap: 6px; }
.reh-vo-row { display: flex; align-items: center; gap: 8px; padding: 6px 7px; border-radius: 7px; border: 1px solid transparent; }
.reh-vo-row.current { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--surface)); }
.reh-vo-play { flex-shrink: 0; width: 30px; height: 30px; border-radius: 50%; border: 1px solid var(--border); background: var(--panel); color: var(--accent); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; transition: all .12s; }
.reh-vo-play:hover { border-color: var(--accent); }
.reh-vo-play.playing { background: var(--accent); color: #fff; border-color: var(--accent); }
.reh-vo-info { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.reh-vo-name { font-size: 13px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.reh-vo-meta { font-size: 10px; color: var(--subtext); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.reh-vo-badge { flex-shrink: 0; font-size: 11px; font-weight: 700; color: var(--accent); display: inline-flex; align-items: center; gap: 3px; }
.reh-vo-use { flex-shrink: 0; }
.reh-vo-play.loading { pointer-events: none; }
.reh-vo-play.loading .mdi { animation: spin .8s linear infinite; }
/* change-voice tools (library / online search) */
.reh-vo-tools { display: flex; gap: 6px; }
.reh-vo-tool { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 6px 8px; font-size: 12px; font-weight: 600; border: 1px solid var(--border); border-radius: 7px; background: var(--panel); color: var(--subtext); cursor: pointer; font-family: inherit; transition: all .12s; }
.reh-vo-tool:hover { color: var(--text); border-color: var(--accent); }
.reh-vo-tool.active { color: var(--accent); border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--panel)); }
.reh-vo-tool-panel { display: flex; flex-direction: column; gap: 7px; }
.reh-vo-search-row { display: flex; gap: 6px; }
.reh-vo-search-row .reh-vo-search-input { flex: 1; }
.reh-vo-local-input, .reh-vo-search-input { width: 100%; padding: 7px 9px; font-size: 12px; border: 1px solid var(--border); border-radius: 7px; background: var(--panel); color: var(--text); font-family: inherit; }
.reh-vo-local-input:focus, .reh-vo-search-input:focus { outline: none; border-color: var(--accent); }
.reh-vo-results { display: flex; flex-direction: column; gap: 6px; max-height: 230px; overflow-y: auto; }
.reh-vo-hint { font-size: 11px; color: var(--subtext); padding: 4px 2px; display: flex; align-items: center; gap: 6px; }
.reh-cc-iconbtn { width: 28px; height: 28px; border-radius: 6px; border: 1px solid var(--border); background: var(--surface); color: var(--subtext); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font-size: 15px; transition: all .12s; }
.reh-cc-iconbtn:hover { color: var(--text); border-color: var(--accent); }
.reh-cc-iconbtn.active { background: var(--accent); color: #fff; border-color: var(--accent); }
.reh-cc-del:hover { color: var(--red); border-color: var(--red); }
.reh-cc-body { display: flex; flex-direction: column; gap: 8px; }
.reh-cc-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
.reh-cc-field { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.reh-cc-field > label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--subtext); }
.reh-cc-field select, .reh-cc-field input { width: 100%; min-width: 0; font-size: 12px; padding: 5px 7px; border: 1px solid var(--border); border-radius: 5px; background: var(--surface); color: var(--text); font-family: var(--font); }
.reh-cc-voice .vp-root { width: 100%; min-width: 0; flex: 1 1 auto; }
.reh-cc-voice .vp-trigger { min-height: 30px; font-size: 12px; }
.reh-cc-voice .vp-drop { max-height: 310px; z-index: 80; }
.reh-cc-field select:focus, .reh-cc-field input:focus { outline: none; border-color: var(--accent); }
.reh-cc-soul { border-top: 1px solid var(--border); padding-top: 6px; }
.reh-cc-soul > summary { font-size: 11px; font-weight: 600; color: var(--subtext); cursor: pointer; display: flex; align-items: center; gap: 6px; list-style: none; }
.reh-cc-soul > summary::-webkit-details-marker { display: none; }
.reh-cc-develop { margin-left: auto; padding: 2px 8px; font-size: 11px; }
.reh-cc-soul-text { width: 100%; margin-top: 6px; min-height: 64px; resize: vertical; font-size: 12px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 5px; background: var(--surface); color: var(--text); font-family: var(--font); line-height: 1.45; }
.reh-cc-soul-text:focus { outline: none; border-color: var(--accent); }
.reh-cc-more { border-top: 1px solid var(--border); padding-top: 8px; margin-top: 2px; }
/* Cast card reusing the exact Library card (_charCardHtml) — no extra
border/shadow around it, its own 16px-radius styling already stands
alone; the Rehearser-only controls strip sits directly under it. */
.reh-cast-card-libcard { background: none; border: none; box-shadow: none; }
.reh-cast-card-libcard .lib-char-card { cursor: pointer; }
.reh-cast-card-libcard .lib-char-select { display: none; }
.reh-cast-card-libcard > .reh-cc-body { padding: 12px 4px 4px; }
.reh-cc-controls { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.reh-cc-more > summary { font-size: 11.5px; font-weight: 700; color: var(--subtext); cursor: pointer; display: flex; align-items: center; gap: 6px; list-style: none; }
.reh-cc-more > summary::-webkit-details-marker { display: none; }
.reh-cc-more[open] > summary { color: var(--accent); margin-bottom: 8px; }
.reh-cc-more .reh-cc-extra { margin-top: 8px; }
.reh-tb-btn { width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--border); background: var(--panel); color: var(--text); cursor: pointer; font-size: 16px; display: flex; align-items: center; justify-content: center; transition: background .15s; }
.reh-tb-btn:hover { background: var(--border); }
.reh-tb-play { background: var(--accent); color: #fff; border-color: var(--accent); font-size: 18px; }
.reh-tb-play:hover { opacity: .85; }
.reh-btn-active { background: var(--accent) !important; color: #fff !important; border-color: var(--accent) !important; }
.reh-tb-progress-wrap { flex: 1; height: 4px; background: var(--border); border-radius: 2px; overflow: hidden; }
.reh-tb-progress { height: 100%; background: var(--accent); width: 0%; transition: width .3s ease; }
.reh-tb-label { font-size: 12px; color: var(--subtext); white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Stage: script page + character sidebar (same .ab-cv-side look Read Aloud's
Casting view uses). The sidebar sticks in place while the script scrolls. */
.reh-stage-area { display: flex; gap: 12px; align-items: flex-start; transition: none; }
.reh-stage-area .reh-page-wrap { flex: 1; min-width: 0; }
.reh-stage-area .ab-cv-side {
width: 220px; flex-shrink: 0; position: sticky; top: 12px;
max-height: calc(100vh - 160px);
}
.reh-stage-area.side-collapsed .ab-cv-side { width: 44px; }
.reh-stage-area .ab-cv-side .ab-cv-chars { flex: 1; overflow-y: auto; }
@media (max-width: 767px) {
/* The sidebar was a fixed 220px column next to the script page — on a
phone-width viewport that left almost no room for the page itself.
Stack the sidebar above the page instead, collapsible the same way it
already is on desktop, just full-width instead of a narrow rail. */
.reh-stage-area { flex-direction: column; }
.reh-stage-area .ab-cv-side { width: 100%; position: static; max-height: 220px; order: -1; }
.reh-stage-area.side-collapsed .ab-cv-side { width: 100%; max-height: 44px; overflow: hidden; }
.reh-page-wrap { padding: 16px 10px; }
.reh-a4-page { padding: 20px 14px; }
}
/* A4 page */
.reh-page-wrap { padding: 24px 16px; background: var(--panel); min-height: 60vh; }
.reh-a4-page {
width: min(1180px, 96%); min-height: 400px;
background: #fff; color: #1a1a2e;
padding: 56px 72px;
box-shadow: 0 4px 24px rgba(0,0,0,.18);
margin: 0 auto;
font-family: 'Georgia', 'Times New Roman', serif;
border-radius: 2px;
}
[data-theme="dark"] .reh-a4-page { background: #f8f8f2; color: #1a1a2e; }
.reh-page-title { font-size: 22px; font-weight: 700; text-align: center; margin-bottom: 36px; letter-spacing: .04em; text-transform: uppercase; color: #1a1a2e; border-bottom: 2px solid #1a1a2e; padding-bottom: 12px; }
.reh-script-lines { display: flex; flex-direction: column; gap: 0; }
/* Each dialog block — flex: gutter | content */
.reh-block { display: flex; align-items: stretch; padding: 8px 12px 8px 2px; border-left: 3px solid transparent; border-radius: 0 4px 4px 0; margin-bottom: 2px; transition: background .2s, border-color .2s; }
.reh-block-inner { flex: 1; min-width: 0; }
.reh-block-head { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; flex-wrap: nowrap; }
.reh-block-name { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .12em; white-space: nowrap; }
.reh-block-head-spacer { flex: 1; min-width: 8px; }
.reh-block-badge { font-size: 10px; padding: 1px 6px; border-radius: 10px; font-family: sans-serif; flex-shrink: 0; }
.reh-badge-tts { background: rgba(137,180,250,.2); color: #2563eb; }
.reh-badge-me { background: rgba(166,227,161,.25); color: #16a34a; }
.reh-block-dialog { font-size: 15px; line-height: 1.65; padding-left: 40px; color: #1a1a2e; }
.reh-direction { font-style: italic; color: #666; font-size: 13px; padding: 4px 12px; }
.reh-char-img { vertical-align: middle; }
.reh-line-play-avatar { border:0; background:transparent; padding:0; margin:0 2px 0 0; cursor:pointer; border-radius:50%; position:relative; display:inline-flex; align-items:center; justify-content:center; }
.reh-line-play-avatar:hover { box-shadow:0 0 0 3px rgba(37,99,235,.18); }
/* This badge overlay is meant to sit in the corner of the bigger avatar
circle (dialogue's own play button) — .reh-action-play-btn (the plain
narrator play button, no avatar underneath) also carries the shared
.reh-line-play-avatar class for click wiring, so it was ALSO getting
this badge layered on top of its own inline icon: two visibly different
play icons stacked on one small button. Excluded here; it's styled to
look like this same badge directly instead (one icon, not two). */
.reh-line-play-avatar:not(.reh-action-play-btn)::after { content:'\F040A'; font-family:'Material Design Icons'; position:absolute; right:-5px; bottom:-5px; width:16px; height:16px; border-radius:50%; background:var(--accent); color:#fff; font-size:11px; display:flex; align-items:center; justify-content:center; box-shadow:0 1px 4px rgba(0,0,0,.24); }
.reh-line-active .reh-line-play-avatar:not(.reh-action-play-btn)::after { content:'\F03E4'; background:var(--red); }
/* Narrator paragraph play button — no avatar image underneath, so styled
to look like the same small blue circular badge dialogue's own play
button already shows (see the ::after rule above), just as its own real
icon instead of a badge layered over something else. */
.reh-action-play-btn {
width: 16px; height: 16px; margin: 0 5px 0 0; vertical-align: middle;
border: none; color: #fff; font-size: 11px;
background: var(--accent); flex-shrink: 0;
}
.reh-action-play-btn:hover { box-shadow: 0 0 0 3px rgba(37,99,235,.18); }
.reh-line-active .reh-action-play-btn { background: var(--red); }
/* Gutter: narrow play/range column left of each dialog block */
.reh-gutter-btn { width:22px; min-width:22px; flex-shrink:0; align-self:stretch; background:none; border:none; cursor:pointer; display:flex; align-items:center; justify-content:center; color:transparent; transition:color .12s; font-size:9px; padding:0; margin-right:4px; }
.reh-block:hover .reh-gutter-btn { color:var(--accent); }
.reh-range-start .reh-gutter-btn { color:#10b981 !important; }
.reh-range-end .reh-gutter-btn { color:#ef4444 !important; }
.reh-in-range { background:rgba(245,158,11,.05) !important; }
.reh-range-start { border-left-color:#10b981 !important; }
.reh-range-end { border-left-color:#ef4444 !important; }
.reh-practice-info { display:none; align-items:center; gap:3px; font-size:10px; color:var(--subtext); white-space:nowrap; margin-left:6px; }
.reh-practice-info.visible { display:inline-flex; }
/* ── Bulk-edit (line selection) ───────────────────────────────────────────── */
.reh-bulk-bar {
display:flex; align-items:center; gap:6px; flex-wrap:wrap;
padding:6px 10px; margin:6px 0; border:1px solid var(--border); border-radius:8px;
background:var(--panel); position:sticky; top:0; z-index:6;
}
.reh-bulk-count { font-size:12px; font-weight:700; color:var(--accent); min-width:74px; }
.reh-bulk-sep { width:1px; align-self:stretch; background:var(--border); margin:2px 2px; }
.reh-bulk-spacer{ flex:1; }
/* Leading checkbox in front of each line */
.reh-bulk-check {
display:none; align-items:center; justify-content:center; flex-shrink:0;
width:26px; cursor:pointer; color:var(--subtext); font-size:20px; align-self:center;
}
.reh-bulk-mode .reh-bulk-check { display:inline-flex; }
.reh-bulk-check.checked { color:var(--accent); }
.reh-bulk-check:hover { color:var(--accent); }
/* Non-dialog blocks: keep the checkbox inline at the start */
.reh-bulk-mode .reh-act,
.reh-bulk-mode .reh-scene,
.reh-bulk-mode .reh-action-block,
.reh-bulk-mode .reh-transition,
.reh-bulk-mode .reh-direction,
.reh-bulk-mode .reh-block-pagebreak { position:relative; }
/* Ignored lines: greyed out but still visible */
.reh-line-ignored { opacity:.42; filter:grayscale(1); }
.reh-line-ignored .reh-block-dialog { text-decoration:line-through; text-decoration-color:rgba(0,0,0,.3); }
/* Hidden lines revealed in bulk mode: dashed, dimmed */
.reh-line-hidden { opacity:.5; outline:1px dashed var(--border); outline-offset:-2px; }
/* Active line */
.reh-block-active { background: rgba(37,99,235,.07); border-left-color: #2563eb; }
.reh-block-active .reh-block-dialog { font-weight: 500; }
/* Emotion picker button */
.reh-emo-btn { font-size:11px; border:1px solid rgba(0,0,0,.15); border-radius:4px; padding:2px 6px; background:rgba(0,0,0,.03); color:#555; cursor:pointer; margin-left:auto; flex-shrink:0; font-family:sans-serif; display:inline-flex; align-items:center; gap:3px; white-space:nowrap; max-width:115px; overflow:hidden; }
.reh-emo-btn:hover { border-color:var(--accent); }
.reh-emo-btn.has-emotion { background:rgba(37,99,235,.07); color:#1a1a2e; border-color:rgba(37,99,235,.3); font-weight:600; }
.reh-emo-label { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:72px; }
/* Emotion picker popover */
.reh-emo-popover { background:var(--bg); border:1px solid var(--border); border-radius:8px; box-shadow:0 8px 32px rgba(0,0,0,.18); overflow:hidden; }
.reh-emo-pop-inner { display:flex; flex-direction:column; max-height:300px; }
.reh-emo-search { padding:8px 10px; border:none; border-bottom:1px solid var(--border); background:var(--surface); font-size:12px; outline:none; color:var(--text); width:100%; box-sizing:border-box; }
.reh-emo-list { overflow-y:auto; flex:1; padding:4px; }
.reh-emo-item { display:flex; align-items:center; gap:8px; padding:5px 8px; border-radius:4px; cursor:pointer; font-size:12px; color:var(--text); }
.reh-emo-item:hover { background:var(--panel); }
.reh-emo-item.selected { background:rgba(37,99,235,.1); color:var(--accent); font-weight:600; }
.reh-emo-item-emoji { font-size:15px; flex-shrink:0; }
.reh-emo-custom-row { padding:6px; border-top:1px solid var(--border); }
/* Markdown formatting toolbar */
.reh-fmt-toolbar { display:flex; gap:3px; align-items:center; padding:4px 6px; background:var(--panel); border:1px solid var(--border); border-bottom:none; border-radius:3px 3px 0 0; flex-wrap:wrap; }
.reh-fmt-btn { padding:2px 8px; border:1px solid var(--border); border-radius:3px; background:var(--surface); cursor:pointer; font-size:12px; color:var(--text); line-height:1.4; }
.reh-fmt-btn:hover { background:var(--border); }
.reh-fmt-hint { font-size:10px; color:var(--subtext); margin-left:auto; font-style:italic; }
/* Markdown inside A4 */
.reh-a4-page strong, .reh-paper strong { font-weight:700; }
.reh-a4-page em, .reh-paper em { font-style:italic; }
.reh-a4-page u, .reh-paper u { text-decoration:underline; }
.reh-a4-page del, .reh-paper del { text-decoration:line-through; opacity:.65; }
.reh-a4-page .reh-hl, .reh-paper .reh-hl { background:#fef3c7; border-radius:2px; padding:0 1px; }
/* Word-level highlight during playback */
.reh-word { display:inline; border-radius:2px; transition:background .06s, color .06s; }
.reh-word-active { background:rgba(37,99,235,.22); color:#1a1a2e; border-radius:2px; padding:0 1px; }
/* ── Proper screenplay A4 formatting ─────────────────────────────────── */
/* Use Courier New throughout — 1 page ≈ 1 minute of screen time */
/* Base play font size. Everything below is expressed in `em` so the whole
play scales together via --reh-stage-scale (the +A / -A control). */
.reh-a4-page {
font-family: 'Courier New', Courier, monospace !important;
font-size: calc(12pt * var(--reh-stage-scale, 1));
line-height: 1.6;
}
.reh-page-title {
font-family: 'Courier New', Courier, monospace;
font-size: 1.17em;
}
/* Scene headings: all-caps, bold, with spacing */
.reh-scene {
font-size: 1em;
letter-spacing: .04em;
}
/* Narrator / action text and spoken dialog share ONE size (1em) so the play
reads evenly — no narrator-vs-dialogue size mismatch. */
.reh-action-block { font-size: 1em; }
.reh-action-text { font-size: 1em; }
/* Act headings: larger, extra top space */
.reh-act { font-size: 1.08em; }
/* Transitions: right-aligned */
.reh-transition { font-size: 1em; }
/* Dialog block — screenplay format */
.reh-block-name {
font-size: 0.92em;
letter-spacing: .1em;
}
.reh-block-dialog {
font-size: 1em;
padding-left: 32px; /* ~1.5" dialog indent */
max-width: 440px; /* ~3.5" dialog column width */
}
/* Parenthetical directions: centered-ish */
.reh-direction {
font-size: 0.92em;
padding-left: 80px;
color: #444;
}
/* Script editor modal */
.reh-modal-overlay { position:fixed; inset:0; z-index:2000; background:rgba(0,0,0,.45); display:flex; align-items:center; justify-content:center; padding:16px; }
.reh-modal-overlay[hidden] { display: none !important; }
.reh-modal-box { background:var(--bg); border-radius:10px; box-shadow:0 20px 60px rgba(0,0,0,.3); overflow:hidden; display:flex; flex-direction:column; }
.reh-modal-head { display:flex; align-items:center; justify-content:space-between; padding:12px 16px; border-bottom:1px solid var(--border); font-weight:700; }
/* TTS status bar */
.reh-tts-status-bar { display: flex; align-items: center; gap: 12px; padding: 8px 16px; background: var(--panel); border-top: 1px solid var(--border); font-size: 13px; }
.reh-tts-status-bar[hidden] { display: none; }
/* Recording overlay */
.reh-rec-overlay {
position: sticky; bottom: 0; z-index: 60;
background: var(--bg); border-top: 2px solid var(--green);
box-shadow: 0 -4px 20px rgba(0,0,0,.15);
}
.reh-rec-overlay[hidden] { display: none; }
.reh-rec-overlay-inner { padding: 14px 20px; max-width: 860px; margin: 0 auto; }
.reh-rec-cue { font-size: 14px; margin-bottom: 10px; line-height: 1.5; }
.reh-rec-cue-name { font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .1em; }
.reh-rec-cue-text { font-size: 17px; margin-top: 4px; padding: 8px 12px; background: rgba(166,227,161,.1); border-left: 3px solid var(--green); border-radius: 0 4px 4px 0; font-style: italic; }
.reh-rec-inner { padding: 14px 20px; max-width: 860px; margin: 0 auto; }
/* Summary */
.reh-summary-list { display: flex; flex-direction: column; gap: 10px; }
.reh-summary-row { display: flex; align-items: flex-start; gap: 10px; padding: 10px; background: var(--panel); border-radius: 6px; }
/* Console / sticky transport bar */
.reh-console {
position: sticky; top: 0; z-index: 50;
background: var(--bg); border-bottom: 1px solid var(--border);
display: flex; align-items: center; gap: 10px; padding: 7px 14px; flex-wrap: wrap;
}
.reh-console-transport { display: flex; gap: 4px; align-items: center; flex-shrink: 0; }
.reh-console-progress { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 80px; }
/* flex-shrink:0 with the flexbox-default min-width:auto meant this block could
never shrink below its unwrapped natural width (confirmed live: ~1560px of
buttons in a 524px-wide bar) — flex-wrap never got a chance to kick in since
the item was never considered "too wide to fit" by the wrapping algorithm,
so on any real (non-ultrawide) window the tail of the toolbar — font size,
page mode, Train, Exit — silently fell off-screen with no scrollbar to
reach it. Allowing it to shrink (and explicitly zeroing min-width, since
flex items default to min-width:auto regardless of any width you set) lets
it wrap onto additional rows within the available space instead. */
.reh-console-actions { display: flex; gap: 6px; align-items: center; flex-shrink: 1; min-width: 0; flex-wrap: wrap; }
/* Synth progress bar */
/* Tone / style backend warning bar */
.reh-tone-warn {
display: flex; align-items: flex-start; gap: 8px; padding: 7px 14px;
background: rgba(234,179,8,.1); border-bottom: 1px solid rgba(234,179,8,.35);
font-size: 12px; color: #92400e;
}
.reh-tone-warn[hidden] { display: none; }
.reh-tone-warn .mdi { color: #d97706; font-size: 14px; flex-shrink: 0; }
/* Aligns the alert icon with the table's own text baseline rather than the
whole (now taller, multi-row) bar. */
.reh-tone-warn > .mdi { margin-top: 3px; }
.reh-tone-warn-close {
margin-left: auto; background: none; border: none; cursor: pointer;
color: #92400e; font-size: 13px; line-height: 1; padding: 2px 4px; border-radius: 3px;
opacity: .7; flex-shrink: 0;
}
.reh-tone-warn-close:hover { opacity: 1; background: rgba(0,0,0,.06); }
/* Backend tone/identity comparison table — replaced a run-on sentence with a
button wedged mid-clause (confirmed live: read badly and wrapped worse).
Same two facts, laid out as two columns instead of two clauses. */
.reh-tone-cmp { border-collapse: collapse; font-size: 12px; }
.reh-tone-cmp th {
text-align: left; font-weight: 600; padding: 2px 14px 4px 0; color: #92400e;
opacity: .75; white-space: nowrap;
}
.reh-tone-cmp td { padding: 3px 14px 3px 0; white-space: nowrap; }
.reh-tone-cmp tr:first-child td { padding-top: 0; }
.reh-tone-cmp-current td:first-child { font-weight: 700; }
.reh-tone-cmp-current-tag {
font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
color: #92400e; opacity: .7;
}
.reh-tone-cmp-yes { color: #15803d; }
.reh-tone-cmp-no { color: #b91c1c; opacity: .8; }
.reh-tone-cmp-yes .mdi, .reh-tone-cmp-no .mdi { font-size: 13px; }
.reh-tone-switch-btn { padding: 2px 10px !important; font-size: 11px !important; }
.reh-tone-cmp-note { margin: 4px 0 0; font-size: 11.5px; opacity: .85; }
/* Synth progress bar — more prominent while running */
.reh-synth-bar {
display: flex; align-items: center; gap: 10px; padding: 7px 16px;
background: linear-gradient(90deg, rgba(37,99,235,.08), rgba(37,99,235,.04));
border-bottom: 2px solid rgba(37,99,235,.3); font-size: 12px;
box-shadow: 0 2px 8px rgba(37,99,235,.12);
}
.reh-synth-bar[hidden] { display: none; }
.reh-synth-bar-lbl {
font-size: 11px; font-weight: 700; color: var(--accent); white-space: nowrap;
display: flex; align-items: center; gap: 4px; letter-spacing: .04em;
}
.reh-synth-track { flex: 1; height: 6px; background: var(--border); border-radius: 3px; overflow: hidden; }
.reh-synth-fill { height: 100%; background: linear-gradient(90deg, var(--accent), #7c3aed); width: 0%; transition: width .25s ease; border-radius: 3px; }
.reh-synth-label { font-size: 12px; font-weight: 600; color: var(--accent); white-space: nowrap; min-width: 48px; text-align: right; }
/* Synthesizing dot — pulsing spinner ring */
@keyframes reh-synth-pulse { 0%,100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.5); opacity: .5; } }
.reh-synth-dot.synthesizing {
background: var(--accent);
animation: reh-synth-pulse .8s ease-in-out infinite;
box-shadow: 0 0 0 3px rgba(37,99,235,.25);
}
/* Row highlight while a line is being synthesized */
.reh-line-synthesizing {
background: rgba(37,99,235,.06) !important;
border-left-color: var(--accent) !important;
transition: background .15s;
}
/* Play font-size stepper (+A / -A) */
.reh-fontsize-ctl { display: inline-flex; gap: 2px; }
/* No padding override here on purpose — confirmed live these two buttons
rendered ~18px shorter than every sibling toolbar button (2px 7px vs the
base .btn-secondary.btn-sm's 9px 18px) because this rule fought that
padding instead of inheriting it. Font weight is the only real
customization these need. */
/* Padding now matches every sibling button exactly, but a residual gap
remained — plain "A" + superscript text computes a shorter natural
line-height than an icon+text button, and guessing at a line-height
multiplier to compensate (tried 1: overshot the other way, to 35.7px
against siblings' 43px) is fragile. Match the sibling toolbar buttons'
actual height directly instead of trying to reverse-engineer it via
line-height. */
.reh-fontsize-btn { font-weight: 700; height: 43px; display: inline-flex; align-items: center; justify-content: center; }
.reh-fontsize-btn .reh-fontsize-plus, .reh-fontsize-btn .reh-fontsize-minus { font-size: 9px; vertical-align: super; margin-left: 1px; }
/* Act heading on A4 page */
.reh-act {
font-family: 'Courier New', Courier, monospace; font-size: 13px; font-weight: 700;
text-transform: uppercase; letter-spacing: .14em; color: #1a1a2e;
margin: 28px 0 8px; padding: 7px 0; text-align: center;
border-top: 2.5px solid #1a1a2e; border-bottom: 2.5px solid #1a1a2e;
cursor: pointer;
}
/* Chapter marker — a horizontal rule with the chapter's own title/number
between the two halves, so a chapter break is visible while scrolling the
script itself and not just audible as a pause in the exported audiobook. */
.reh-chapter-marker {
display: flex; align-items: center; gap: 14px;
margin: 32px 0 20px; position: relative;
}
.reh-chapter-marker-line { flex: 1; height: 1px; background: var(--border); }
.reh-chapter-marker-label {
font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
font-size: 13px; color: var(--subtext); white-space: nowrap; padding: 0 2px;
}
.reh-chapter-marker:hover .reh-edit-btn { opacity: 1; }
/* Inline edit button — shown on hover */
.reh-edit-btn {
opacity: 0; transition: opacity .12s; border: 1px solid transparent;
background: none; cursor: pointer; font-size: 10px; color: var(--subtext);
padding: 1px 5px; border-radius: 3px; line-height: 1; flex-shrink: 0;
}
.reh-block:hover .reh-edit-btn,
.reh-action-block:hover .reh-edit-btn,
.reh-scene:hover .reh-edit-btn,
.reh-act:hover .reh-edit-btn { opacity: 1; }
.reh-edit-btn:hover { background: var(--panel); border-color: var(--border); color: var(--accent); }
/* Scene heading on the A4 page */
.reh-scene {
font-family: 'Courier New', Courier, monospace; font-size: 11.5px; font-weight: 700;
text-transform: uppercase; letter-spacing: .07em; color: #1a1a2e;
margin: 22px 0 8px; padding: 5px 0;
border-top: 1.5px solid #333; border-bottom: 1.5px solid #333;
cursor: pointer; display: flex; align-items: center; gap: 6px;
}
.reh-scene .mdi { font-size: 11px; opacity: .5; flex-shrink: 0; }
/* Action / description block — 1em so narrator matches spoken dialog and
scales with the +A / -A control. */
.reh-action-block {
font-family: 'Courier New', Courier, monospace; font-size: 1em; line-height: 1.75;
color: #2c2c3e; padding: 2px 0 10px; cursor: pointer;
}
/* Transition line */
.reh-transition {
font-family: 'Courier New', Courier, monospace; font-size: 0.75em; font-weight: 700;
text-align: right; text-transform: uppercase; letter-spacing: .1em;
color: #555; padding: 8px 0;
}
/* Active line highlight (works on any block type) */
.reh-line-active.reh-block { background: rgba(37,99,235,.08) !important; border-left-color: var(--accent) !important; }
.reh-line-active.reh-scene { background: rgba(37,99,235,.06) !important; outline: 2px solid var(--accent); outline-offset: 1px; border-radius: 3px; }
.reh-line-active.reh-action-block { background: rgba(37,99,235,.05) !important; padding-left: 6px; border-left: 2px solid var(--accent); }
.reh-line-active.reh-direction { background: rgba(37,99,235,.04) !important; }
/* Emotion selector on TTS dialog blocks */
.reh-emotion-sel {
font-size: 10px; border: 1px solid rgba(0,0,0,.18); border-radius: 3px;
padding: 1px 4px; background: rgba(0,0,0,.04); color: #555;
cursor: pointer; margin-left: auto; flex-shrink: 0; font-family: sans-serif;
max-width: 90px;
}
.reh-emotion-sel:hover, .reh-emotion-sel:focus { border-color: var(--accent); outline: none; }
.reh-emotion-sel.has-emotion { background: rgba(37,99,235,.08); color: var(--accent); border-color: var(--accent); font-weight: 600; }
/* Pre-synthesized dot */
.reh-synth-dot {
width: 7px; height: 7px; border-radius: 50%; background: var(--green);
flex-shrink: 0; display: inline-block; margin-left: 3px;
}
.reh-synth-dot.stale {
background: var(--red, #ef4444);
box-shadow: 0 0 0 2px rgba(239,68,68,.2);
}
/* Per-line re-synth button */
.reh-resynth-btn {
background: none; border: none; cursor: pointer; padding: 2px 4px;
color: var(--red, #ef4444); font-size: 12px; border-radius: 4px;
opacity: .85; transition: opacity .15s, background .15s;
display: inline-flex; align-items: center;
}
.reh-resynth-btn:hover { opacity: 1; background: rgba(239,68,68,.1); }
/* Note area — right gutter of dialog block (holds edit btn + note btn) */
.reh-block { position: relative; }
.reh-note-area {
display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
min-width: 28px; flex-shrink: 0; padding-top: 2px;
}
/* Edit button inside note-area gutter */
.reh-note-area .reh-edit-btn {
opacity: 0; transition: opacity .12s; border: 1px solid transparent;
background: none; cursor: pointer; font-size: 13px; color: var(--subtext);
padding: 3px 5px; border-radius: 4px; line-height: 1; flex-shrink: 0;
}
.reh-block:hover .reh-note-area .reh-edit-btn { opacity: 1; }
.reh-note-area .reh-edit-btn:hover { background: var(--panel); border-color: var(--border); color: var(--accent); }
.reh-note-btn {
background: none; border: none; cursor: pointer; padding: 3px;
font-size: 14px; color: var(--subtext); opacity: .45; border-radius: 4px;
transition: opacity .15s, color .15s; line-height: 1; flex-shrink: 0;
}
.reh-note-btn:hover, .reh-note-btn.has-note { opacity: 1; color: #f59e0b; }
.reh-note-ta {
display: none; width: 160px; min-height: 60px; resize: vertical;
font-size: 11px; font-family: inherit; line-height: 1.45;
padding: 6px 8px; border: 1px solid #f59e0b55; border-radius: 6px;
background: rgba(245,158,11,.06); color: var(--text); outline: none;
}
.reh-note-ta.open { display: block; }
.reh-note-ta:focus { border-color: #f59e0b; background: rgba(245,158,11,.1); }
@media (max-width: 700px) {
.reh-input-row { grid-template-columns: 1fr; }
.reh-a4-page { padding: 28px 20px; }
.reh-console { gap: 8px; }
.reh-cc-grid { grid-template-columns: 1fr; }
}
/* ── Phase sub-tabs ─────────────────────────────────────────────────────── */
.reh-subtabs {
display: flex; gap: 4px; padding: 4px; margin: 0 0 14px;
background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
flex-wrap: wrap;
}
.reh-subtab {
display: inline-flex; align-items: center; gap: 6px;
padding: 7px 14px; border: none; border-radius: 7px; cursor: pointer;
background: transparent; color: var(--subtext); font-size: 13px; font-weight: 600;
transition: background .15s, color .15s;
}
.reh-subtab .mdi { font-size: 16px; }
.reh-subtab:hover:not(:disabled):not(.active) { background: var(--border); color: var(--text); }
.reh-subtab.active { background: var(--surface); color: var(--accent); box-shadow: 0 1px 3px rgba(0,0,0,.08); }
.reh-subtab:disabled { opacity: .4; cursor: not-allowed; }
@media (max-width: 600px) {
.reh-subtab span:not(.mdi) { display: none; }
.reh-subtab { padding: 8px 12px; }
}
/* ── Studio phase tabs (deliberately separate classes from .reh-subtab —
rehearser.js wires its OWN click listeners onto every .reh-subtab in the
document via querySelectorAll, and every section's HTML is present in the
DOM at once regardless of which is visible, so reusing that class name
here would silently attach Rehearser's phase-switching logic to Studio's
own tab buttons too) ───────────────────────────────────────────────── */
.stu-subtabs {
display: flex; gap: 4px; padding: 4px; margin: 0 0 14px;
background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
flex-wrap: wrap;
}
.stu-subtab {
display: inline-flex; align-items: center; gap: 6px;
padding: 7px 14px; border: none; border-radius: 7px; cursor: pointer;
background: transparent; color: var(--subtext); font-size: 13px; font-weight: 600;
transition: background .15s, color .15s;
}
.stu-subtab .mdi { font-size: 16px; }
.stu-subtab:hover:not(:disabled):not(.active) { background: var(--border); color: var(--text); }
.stu-subtab.active { background: var(--surface); color: var(--accent); box-shadow: 0 1px 3px rgba(0,0,0,.08); }
.stu-subtab:disabled { opacity: .4; cursor: not-allowed; }
.stu-subtab-num {
display: inline-flex; align-items: center; justify-content: center;
width: 16px; height: 16px; border-radius: 50%; font-size: 10px; font-weight: 700;
background: var(--border); color: var(--subtext); flex-shrink: 0;
}
.stu-subtab.active .stu-subtab-num { background: var(--accent); color: #fff; }
@media (max-width: 600px) {
.stu-subtab span:not(.mdi):not(.stu-subtab-num) { display: none; }
.stu-subtab { padding: 8px 12px; }
}
/* Nested sub-tabs inside Studio's Characters/Perform phases (smaller, inline) */
.stu-inner-tabs { display: flex; gap: 4px; margin: 0 0 12px; }
.stu-inner-tab {
padding: 6px 12px; border: 1px solid var(--border); border-radius: 6px; cursor: pointer;
background: var(--panel); color: var(--subtext); font-size: 12.5px; font-weight: 600;
}
.stu-inner-tab.active { background: var(--surface); color: var(--accent); border-color: var(--accent); }
.stu-mode-toggle {
display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px;
border: 1px solid var(--border); border-radius: 8px; background: var(--panel);
font-size: 13px; font-weight: 600; margin: 0 0 14px; cursor: pointer;
}
/* ── Auto-design voices (Phase 2) ───────────────────────────────────────── */
.reh-autodesign {
border: 1px solid var(--border); border-radius: 10px;
padding: 12px 14px; margin: 4px 0 14px;
background: linear-gradient(180deg, rgba(37,99,235,.04), transparent);
}
.reh-autodesign-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; font-size: 13px; }
.reh-autodesign-head .note { font-weight: 400; }
.reh-autodesign-row { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
.reh-autodesign-row input, .reh-autodesign-row select {
width: 100%; padding: 6px 8px; border: 1px solid var(--border);
border-radius: 5px; background: var(--surface); color: var(--text); font-size: 12px;
}
.reh-llm-refresh { border: none; background: none; cursor: pointer; color: var(--accent); font-size: 13px; padding: 0 2px; }
.reh-autodesign-progress { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
/* Three casting options (local match / online match / design) */
.reh-cast-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 10px; margin-top: 12px; }
.reh-cast-opt { display: flex; gap: 10px; padding: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; }
.reh-co-num { flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%; background: var(--accent); color: #fff; font-size: 12px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; }
.reh-co-body { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.reh-co-body > strong { font-size: 13px; display: flex; align-items: center; gap: 6px; }
.reh-co-body > strong .mdi { color: var(--accent); }
.reh-co-body > p { font-size: 11.5px; color: var(--subtext); line-height: 1.45; margin: 0; }
.reh-co-body > p em { font-style: normal; color: var(--text); font-weight: 600; }
.reh-co-body > button { align-self: flex-start; margin-top: 2px; white-space: nowrap; }
/* Per-character status pill while designing */
.reh-cast-designing { opacity: .75; }
.reh-cast-design-badge {
font-size: 10px; padding: 1px 7px; border-radius: 10px; margin-left: 6px;
background: rgba(37,99,235,.12); color: var(--accent); font-weight: 600;
}
.reh-cast-design-badge.done { background: rgba(22,163,74,.15); color: var(--green); }
.reh-cast-design-badge.err { background: rgba(220,38,38,.15); color: var(--red); }
/* ── Per-character auto-design detail panel ─────────────────────────────── */
.reh-cast-design-panel {
margin: -4px 12px 8px 12px; padding: 10px 12px;
border: 1px solid rgba(37,99,235,.25); border-radius: 8px;
background: rgba(37,99,235,.05); display: flex; flex-direction: column; gap: 7px;
animation: reh-cdp-in .15s ease-out;
}
@keyframes reh-cdp-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.reh-cast-design-panel.done {
border-color: rgba(22,163,74,.25); background: rgba(22,163,74,.04);
}
.reh-cdp-meta { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.reh-cdp-chip {
font-size: 10px; font-weight: 600; padding: 2px 8px; border-radius: 10px;
background: var(--panel); border: 1px solid var(--border); color: var(--subtext);
display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
}
.reh-cdp-gender { color: #8b5cf6; border-color: rgba(139,92,246,.3); background: rgba(139,92,246,.07); }
.reh-cdp-lang { color: #0ea5e9; border-color: rgba(14,165,233,.3); background: rgba(14,165,233,.07); }
.reh-cdp-name { color: var(--accent); border-color: rgba(37,99,235,.3); background: rgba(37,99,235,.07); font-family: monospace; font-size: 10px; }
.reh-cdp-desc {
font-size: 11px; line-height: 1.5; color: var(--text); font-style: italic;
border-left: 2px solid var(--accent); padding-left: 8px; opacity: .85;
}
.reh-cdp-step {
display: flex; align-items: center; gap: 7px; font-size: 11px; color: var(--subtext);
}
.reh-cdp-step .reh-imsdb-spinner { border-top-color: var(--accent); }
/* ── Drag & drop importer ───────────────────────────────────────────────── */
.reh-dropzone {
margin-top: 14px; padding: 26px 16px; border: 2px dashed var(--border);
border-radius: 12px; text-align: center; color: var(--subtext);
display: flex; flex-direction: column; align-items: center; gap: 5px;
transition: border-color .15s, background .15s; cursor: default;
}
.reh-dropzone-icon { font-size: 34px; opacity: .5; }
.reh-dropzone.dragover {
border-color: var(--accent); background: rgba(37,99,235,.06); color: var(--accent);
}
.reh-dropzone.dragover .reh-dropzone-icon { opacity: 1; }
/* ── Bookshelf library ──────────────────────────────────────────────────── */
.reh-bookshelf {
display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 18px 16px; padding: 6px 4px 4px;
}
.sk { background: linear-gradient(90deg, var(--panel), rgba(37,99,235,.08), var(--panel)); background-size: 220% 100%; animation: skeletonSweep 1.15s ease-in-out infinite; }
.lib-book-sk { background: linear-gradient(135deg, var(--panel), var(--border)) !important; opacity: .7; animation: none; cursor: default; }
.lib-book-sk .sk { border-radius: 4px; }
.reh-book {
position: relative; cursor: pointer; border-radius: 4px 7px 7px 4px;
aspect-ratio: 2 / 3; padding: 14px 12px 12px 18px; color: #fff; overflow: hidden;
box-shadow: 0 5px 14px rgba(0,0,0,.22), inset 3px 0 0 rgba(0,0,0,.18);
display: flex; flex-direction: column;
transition: transform .16s ease, box-shadow .16s ease;
background: linear-gradient(135deg, var(--bk1, #4f46e5), var(--bk2, #7c3aed));
}
.reh-book::before { /* spine highlight */
content: ''; position: absolute; left: 6px; top: 0; bottom: 0; width: 2px;
background: rgba(255,255,255,.25);
}
.reh-book:hover { transform: translateY(-5px) rotate(-.6deg); box-shadow: 0 12px 26px rgba(0,0,0,.3), inset 3px 0 0 rgba(0,0,0,.18); }
.reh-book-title {
font-size: 14px; font-weight: 800; line-height: 1.25; letter-spacing: .01em;
text-shadow: 0 1px 3px rgba(0,0,0,.35); display: -webkit-box;
-webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
}
.reh-book-meta { margin-top: auto; font-size: 10.5px; opacity: .9; line-height: 1.5; }
.reh-book-avatars { display: flex; gap: 3px; margin-bottom: 6px; flex-wrap: wrap; }
.reh-book-avatars span {
width: 19px; height: 19px; border-radius: 50%; font-size: 9px; font-weight: 700;
display: inline-flex; align-items: center; justify-content: center;
border: 1.5px solid rgba(255,255,255,.7); color: #fff;
}
.reh-book-progress { height: 3px; border-radius: 2px; background: rgba(255,255,255,.28); margin-top: 5px; overflow: hidden; }
.reh-book-progress > div { height: 100%; background: rgba(255,255,255,.9); }
.reh-book-actions {
position: absolute; top: 6px; right: 6px; display: flex; gap: 3px; opacity: 0;
transition: opacity .14s;
}
.reh-book:hover .reh-book-actions { opacity: 1; }
.reh-book-act {
width: 22px; height: 22px; border-radius: 5px; border: none; cursor: pointer;
background: rgba(0,0,0,.32); color: #fff; font-size: 12px;
display: inline-flex; align-items: center; justify-content: center;
}
.reh-book-act:hover { background: rgba(0,0,0,.55); }
.reh-book-active-tag {
position: absolute; top: 8px; left: 14px; font-size: 8.5px; font-weight: 700;
text-transform: uppercase; letter-spacing: .08em; background: rgba(255,255,255,.92);
color: #1a1a2e; padding: 1px 6px; border-radius: 8px;
}
/* List-view fallback reuses old rows */
.reh-bookshelf.list-view { display: flex; flex-direction: column; gap: 8px; }
.reh-bookshelf.list-view .reh-book {
aspect-ratio: auto; flex-direction: row; align-items: center; gap: 12px;
padding: 10px 14px; color: var(--text); background: var(--panel) !important;
box-shadow: none; border: 1px solid var(--border); border-radius: 8px;
}
.reh-bookshelf.list-view .reh-book:hover { transform: none; }
.reh-bookshelf.list-view .reh-book::before { display: none; }
.reh-bookshelf.list-view .reh-book-title { -webkit-line-clamp: 1; text-shadow: none; font-size: 14px; }
.reh-bookshelf.list-view .reh-book-meta { margin: 0 0 0 auto; }
.reh-bookshelf.list-view .reh-book-actions { position: static; opacity: 1; }
.reh-bookshelf.list-view .reh-book-act { background: var(--surface); color: var(--text); border: 1px solid var(--border); }
/* ── Multi-page (paginated) script view ─────────────────────────────────── */
.reh-page-wrap.paginated { display: flex; flex-direction: column; align-items: center; gap: 22px; }
.reh-paper {
width: min(1180px, 96%); background: #fff; color: #1a1a2e;
padding: 56px 72px 40px; box-shadow: 0 4px 24px rgba(0,0,0,.18);
font-family: 'Courier New', Courier, monospace; font-size: calc(12pt * var(--reh-stage-scale, 1)); line-height: 1.6;
border-radius: 2px; position: relative; box-sizing: border-box;
min-height: min(1123px, calc((100vw - 32px) * 1.414));
}
.reh-paper-num {
position: absolute; top: 20px; right: 32px; font-size: 10pt; color: #888;
font-family: 'Courier New', monospace;
}
[data-theme="dark"] .reh-paper { background: #f8f8f2; }
/* Keep script-browser list rows readable even when old cached list styles collapse. */
.reh-imsdb-grid.list-view > .reh-imsdb-card {
height: 48px !important;
min-height: 48px !important;
max-height: 48px;
overflow: hidden;
}
.reh-imsdb-grid.list-view > .reh-imsdb-card .reh-imsdb-meta {
height: 48px;
min-height: 48px;
}
.reh-bulk-hint { font-size:11px; color:var(--subtext); margin-right:4px; }
.reh-bulk-mode .reh-selected {
background: rgba(37,99,235,.11) !important;
outline: 2px solid rgba(37,99,235,.35);
outline-offset: -2px;
}
.reh-bulk-mode .reh-selected .reh-block-dialog { font-weight:600; }
/* Keep script-browser thumbnail cards tall enough to click/download in cover view. */
.reh-imsdb-grid:not(.list-view) > .reh-imsdb-card {
display: flex !important;
flex-direction: column !important;
min-height: 230px !important;
height: auto !important;
overflow: hidden;
}
.reh-imsdb-grid:not(.list-view) > .reh-imsdb-card .reh-imsdb-poster-wrap {
display: block !important;
position: relative !important;
width: 100% !important;
aspect-ratio: 2 / 3 !important;
min-height: 178px !important;
height: auto !important;
padding-bottom: 0 !important;
flex: 0 0 auto !important;
}
.reh-imsdb-grid:not(.list-view) > .reh-imsdb-card .reh-imsdb-poster,
.reh-imsdb-grid:not(.list-view) > .reh-imsdb-card .reh-imsdb-fallback {
position: absolute !important;
inset: 0 !important;
width: 100% !important;
height: 100% !important;
}
.reh-imsdb-grid:not(.list-view) > .reh-imsdb-card .reh-imsdb-meta {
min-height: 46px;
flex: 0 0 auto;
}
/* ── Read Aloud reader ─────────────────────────────────────────────────── */
.reader-controls {
display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
}
.reader-ctl { margin: 0; min-width: 150px; }
.reader-ctl-grow { flex: 1 1 200px; }
.reader-ctl-sm { min-width: 96px; max-width: 130px; }
.reader-ctl-sm input { width: 100%; }
.reader-norm-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--subtext); white-space: nowrap; align-self: center; cursor: pointer; }
.reader-backend-hint { margin-top: 10px; font-size: 12px; color: var(--subtext); display: flex; align-items: flex-start; gap: 6px; }
.reader-backend-hint .mdi { color: var(--accent); flex-shrink: 0; }
.reader-backend-hint b { color: var(--text); }
.reader-backend-hint.reader-hint-warn { color: var(--text); }
.reader-backend-hint:empty { display: none; }
.reader-voice-pick { display: flex; gap: 6px; }
.reader-voice-pick select { flex: 1; min-width: 0; }
.reader-speed-label { color: var(--accent); font-weight: 700; }
.reader-ctl input[type=range] { width: 100%; accent-color: var(--accent); }
.reader-import-btn { cursor: pointer; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
#s-reader .reader-tuning-panel {
margin-top: 12px;
display: grid;
grid-template-columns: 1fr;
gap: 8px;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--bg);
}
#s-caststudio .reader-tuning-panel {
margin-top: 12px;
display: grid;
grid-template-columns: 1fr;
gap: 8px;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--bg);
}
#s-reader .reader-tuning-row {
grid-column: 1;
display: grid;
grid-template-columns: 136px minmax(130px, 220px) minmax(220px, 1fr);
gap: 12px;
align-items: center;
}
#s-caststudio .reader-tuning-row {
grid-column: 1;
display: grid;
grid-template-columns: 136px minmax(130px, 220px) minmax(220px, 1fr);
gap: 12px;
align-items: center;
}
#s-reader .reader-tuning-row label {
margin: 0;
color: var(--subtext);
font-size: 12px;
font-weight: 800;
text-transform: uppercase;
letter-spacing: .02em;
}
#s-caststudio .reader-tuning-row label {
margin: 0;
color: var(--subtext);
font-size: 12px;
font-weight: 800;
text-transform: uppercase;
letter-spacing: .02em;
}
#s-reader .reader-tuning-row input[type="number"],
#s-caststudio .reader-tuning-row input[type="number"],
#s-reader .reader-tuning-row input[type="range"],
#s-caststudio .reader-tuning-row input[type="range"] {
width: 100%;
min-width: 0;
}
#s-reader .reader-tuning-row input[type="range"] { accent-color: var(--accent); }
#s-caststudio .reader-tuning-row input[type="range"] { accent-color: var(--accent); }
#s-reader .reader-tuning-help {
color: var(--subtext);
font-size: 12px;
line-height: 1.35;
}
#s-caststudio .reader-tuning-help {
color: var(--subtext);
font-size: 12px;
line-height: 1.35;
}
#s-reader .reader-tuning-panel .reader-backend-hint {
/* Used to sit beside the 4 tuning rows, forced to stretch to their
combined height (grid-row: 1 / span 4) regardless of how short its own
text was — most of the time that left a large empty gap below a
1-3 line hint. Full-width below the rows instead, sized to its own
content, so there's no reserved space to be empty in the first place. */
margin: 4px 0 0;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface);
min-width: 0;
}
#s-caststudio .reader-tuning-panel .reader-backend-hint {
/* Used to sit beside the 4 tuning rows, forced to stretch to their
combined height (grid-row: 1 / span 4) regardless of how short its own
text was — most of the time that left a large empty gap below a
1-3 line hint. Full-width below the rows instead, sized to its own
content, so there's no reserved space to be empty in the first place. */
margin: 4px 0 0;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface);
min-width: 0;
}
#s-reader .reader-tuning-panel .reader-backend-hint:empty { display: none; margin: 0; }
#s-caststudio .reader-tuning-panel .reader-backend-hint:empty { display: none; margin: 0; }
#s-reader .reader-source-panel {
margin-top: 12px;
padding: 12px;
border: 1px solid var(--border);
border-radius: 10px;
background: linear-gradient(180deg, var(--surface), var(--bg));
}
#s-caststudio .reader-source-panel {
margin-top: 12px;
padding: 12px;
border: 1px solid var(--border);
border-radius: 10px;
background: linear-gradient(180deg, var(--surface), var(--bg));
}
#s-reader .reader-source-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 10px;
}
#s-caststudio .reader-source-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 10px;
}
#s-reader .reader-source-head div {
min-width: 0;
display: flex;
align-items: baseline;
gap: 10px;
flex-wrap: wrap;
}
#s-caststudio .reader-source-head div {
min-width: 0;
display: flex;
align-items: baseline;
gap: 10px;
flex-wrap: wrap;
}
#s-reader .reader-source-head strong {
display: inline-flex;
align-items: center;
gap: 6px;
color: var(--text);
font-size: 13px;
}
#s-caststudio .reader-source-head strong {
display: inline-flex;
align-items: center;
gap: 6px;
color: var(--text);
font-size: 13px;
}
#s-reader .reader-source-head span {
color: var(--subtext);
font-size: 12px;
}
#s-caststudio .reader-source-head span {
color: var(--subtext);
font-size: 12px;
}
#s-reader .reader-source-grid {
display: grid;
grid-template-columns: minmax(0, 1.4fr) minmax(260px, .8fr);
gap: 12px;
align-items: stretch;
}
#s-caststudio .reader-source-grid {
display: grid;
grid-template-columns: minmax(0, 1.4fr) minmax(260px, .8fr);
gap: 12px;
align-items: stretch;
}
#s-reader .reader-paste-panel {
min-width: 0;
display: flex;
flex-direction: column;
gap: 8px;
padding: 12px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface);
}
#s-caststudio .reader-paste-panel {
min-width: 0;
display: flex;
flex-direction: column;
gap: 8px;
padding: 12px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface);
}
#s-reader .reader-source-method {
display: flex;
align-items: flex-start;
gap: 8px;
color: var(--subtext);
}
#s-caststudio .reader-source-method {
display: flex;
align-items: flex-start;
gap: 8px;
color: var(--subtext);
}
#s-reader .reader-source-method > .mdi {
color: var(--accent);
font-size: 20px;
line-height: 1;
}
#s-caststudio .reader-source-method > .mdi {
color: var(--accent);
font-size: 20px;
line-height: 1;
}
#s-reader .reader-source-method div {
min-width: 0;
display: flex;
flex-direction: column;
gap: 1px;
}
#s-caststudio .reader-source-method div {
min-width: 0;
display: flex;
flex-direction: column;
gap: 1px;
}
#s-reader .reader-source-method strong {
color: var(--text);
font-size: 13px;
}
#s-caststudio .reader-source-method strong {
color: var(--text);
font-size: 13px;
}
#s-reader .reader-source-method span {
color: var(--subtext);
font-size: 12px;
line-height: 1.35;
}
#s-caststudio .reader-source-method span {
color: var(--subtext);
font-size: 12px;
line-height: 1.35;
}
#s-reader .reader-paste-text {
width: 100%;
min-height: 138px;
resize: vertical;
box-sizing: border-box;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--bg);
color: var(--text);
padding: 11px 12px;
font: inherit;
line-height: 1.45;
}
#s-caststudio .reader-paste-text {
width: 100%;
min-height: 138px;
resize: vertical;
box-sizing: border-box;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--bg);
color: var(--text);
padding: 11px 12px;
font: inherit;
line-height: 1.45;
}
#s-reader .reader-paste-text:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 3px rgba(37,99,235,.12);
}
#s-caststudio .reader-paste-text:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 3px rgba(37,99,235,.12);
}
#s-reader .reader-paste-actions {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 10px;
flex-wrap: wrap;
}
#s-caststudio .reader-paste-actions {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 10px;
flex-wrap: wrap;
}
.reader-dropzone {
margin-top: 14px; padding: 30px 16px; border: 2px dashed var(--border);
border-radius: 12px; text-align: center; color: var(--subtext);
display: flex; flex-direction: column; align-items: center; gap: 5px;
transition: border-color .15s, background .15s;
}
#s-reader .reader-source-panel .reader-dropzone {
margin-top: 0;
min-height: 100%;
padding: 18px;
border-radius: 8px;
background: var(--surface);
justify-content: center;
gap: 8px;
}
#s-caststudio .reader-source-panel .reader-dropzone {
margin-top: 0;
min-height: 100%;
padding: 18px;
border-radius: 8px;
background: var(--surface);
justify-content: center;
gap: 8px;
}
.reader-dropzone-icon { font-size: 34px; opacity: .5; }
/* "Extract Text" prompt — PDF pages are already visible, but text/OCR extraction
is a separate explicit action (pipeline stage 2) rather than automatic. */
.reader-extract-banner {
display: flex; align-items: center; gap: 14px; margin: 12px 0; padding: 14px 16px;
border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel);
}
.reader-extract-icon { font-size: 30px; color: var(--accent); flex-shrink: 0; }
.reader-extract-info { flex: 1; min-width: 160px; }
.reader-extract-info strong { display: block; color: var(--text); font-size: 14px; }
.reader-extract-info p { margin: 2px 0 0; color: var(--subtext); font-size: 12.5px; }
.reader-dropzone.dragover { border-color: var(--accent); background: rgba(37,99,235,.06); color: var(--accent); }
.reader-dropzone.dragover .reader-dropzone-icon { opacity: 1; }
#s-reader .reader-file-pick {
margin-top: 4px;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 6px;
}
#s-caststudio .reader-file-pick {
margin-top: 4px;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 6px;
}
@media (max-width: 860px) {
#s-reader .reader-source-grid { grid-template-columns: 1fr; }
#s-caststudio .reader-source-grid { grid-template-columns: 1fr; }
#s-reader .reader-tuning-row { grid-template-columns: 1fr; gap: 5px; }
#s-caststudio .reader-tuning-row { grid-template-columns: 1fr; gap: 5px; }
}
.reader-transport {
display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
margin-top: 14px; padding: 10px 14px; background: var(--surface);
border: 1px solid var(--border); border-radius: var(--radius);
}
.reader-tb-group { display: flex; gap: 4px; }
.reader-progress-wrap { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 160px; }
.reader-progress-track { flex: 1; height: 6px; border-radius: 4px; background: var(--panel); overflow: hidden; }
.reader-progress-fill { height: 100%; width: 0; background: var(--accent); transition: width .25s; }
.reader-progress-label { font-size: 12px; color: var(--subtext); white-space: nowrap; min-width: 56px; text-align: right; }
.reader-doc-title { font-size: 13px; font-weight: 700; color: var(--text); max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Saved-books library */
.reader-lib-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.reader-lib-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px; }
.reader-book {
position: relative; padding: 18px 16px 16px 24px; border: 1px solid var(--border);
border-radius: 4px 14px 14px 4px; background: var(--surface); cursor: pointer;
transition: border-color .15s, transform .1s, box-shadow .15s;
display: flex; flex-direction: column; aspect-ratio: 1 / 1.35;
box-shadow: inset 5px 0 10px rgba(0,0,0,.03), -1px 0 0 rgba(0,0,0,.06), 0 3px 8px rgba(0,0,0,.05);
}
.reader-book::before {
content: ''; position: absolute; top: 0; bottom: 0; left: 14px; width: 2px;
background: rgba(0,0,0,.04); border-left: 1px solid rgba(255,255,255,.5);
}
.reader-book:hover {
border-color: var(--accent);
box-shadow: inset 5px 0 10px rgba(0,0,0,.03), -1px 0 0 var(--accent), 0 8px 20px rgba(0,0,0,.08);
transform: translateY(-2px);
}
.reader-book-icon { font-size: 28px; color: var(--accent); line-height: 1; z-index: 1; }
.reader-book-title { font-weight: 800; font-size: 15px; margin-top: 10px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; line-height: 1.3; z-index: 1; }
.reader-book-meta { font-size: 11px; color: var(--subtext); margin-top: 6px; z-index: 1; }
.reader-book-bar { position: relative; height: 6px; border-radius: 4px; background: var(--panel); margin-top: auto; margin-bottom: 5px; overflow: hidden; border: 1px solid var(--border); z-index: 1; }
.reader-book-bar-synth { position: absolute; inset: 0 auto 0 0; background: rgba(34,197,94,.45); }
.reader-book-bar-read { position: absolute; inset: 0 auto 0 0; background: var(--accent); }
.reader-book-stats { display: flex; justify-content: space-between; gap: 6px; font-size: 10.5px; color: var(--subtext); z-index: 1; }
.reader-book-del {
position: absolute; top: 8px; right: 8px; border: none; background: rgba(0,0,0,.06);
color: var(--subtext); border-radius: 6px; width: 28px; height: 28px; cursor: pointer; opacity: 0; transition: opacity .15s;
display: flex; align-items: center; justify-content: center; z-index: 5;
}
.reader-book-del .mdi { font-size: 15px; }
.reader-book:hover .reader-book-del { opacity: 1; }
.reader-book-del:hover { color: var(--red, #ef4444); background: rgba(239,68,68,.1); }
/* Synthesise-ahead bar + range selection */
.reader-synthbar {
display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
margin-top: 10px; padding: 8px 12px; background: var(--surface);
border: 1px solid var(--border); border-radius: var(--radius);
justify-content: space-between;
}
.reader-page-range { display: inline-flex; align-items: center; gap: 6px; }
.reader-page-inp {
width: 56px; padding: 4px 6px; border: 1px solid var(--border);
border-radius: 6px; background: var(--panel); color: var(--text); font-family: var(--font);
}
#reader-select-toggle.active { background: var(--accent); color: #fff; border-color: var(--accent); }
.reader-sel-info { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--accent); font-weight: 600; }
.reader-sel-clear { border: none; background: none; color: var(--subtext); cursor: pointer; font-size: 13px; padding: 0 2px; }
.reader-sel-clear:hover { color: var(--red, #ef4444); }
.reader-sel-hint { font-size: 12px; color: var(--subtext); }
.reader-sel-hint b { color: var(--accent); }
.reader-export { display: inline-flex; align-items: center; gap: 6px; }
/* Audiobook live casting — floating, non-blocking, minimisable panel */
.ab-castpanel {
position: fixed; right: 18px; bottom: 18px; z-index: 1000;
width: min(880px, 96vw); height: 50vh; max-height: 82vh; display: flex; flex-direction: column;
background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
box-shadow: 0 16px 48px rgba(0,0,0,.28); overflow: hidden; resize: both; min-height: 300px; min-width: 400px;
}
.ab-castpanel-head { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--border); background: var(--bg); cursor: move; flex-shrink: 0; }
.ab-castpanel-head > .mdi { color: var(--accent); font-size: 18px; }
.ab-castpanel-title { font-weight: 800; font-size: 14px; }
.ab-castpanel-count { font-size: 12px; color: var(--subtext); }
.ab-castpanel-btn { border: none; background: none; color: var(--subtext); cursor: pointer; padding: 2px 5px; border-radius: 6px; line-height: 1; }
.ab-castpanel-btn:hover { background: var(--panel); color: var(--text); }
.ab-castpanel-bar {
position: relative; flex: 0 1 760px; min-width: 180px; height: 30px; min-height: 30px; max-height: 30px;
align-self: center; margin: 0 12px 0 0; border-radius: 6px;
background: var(--surface); border: 1px solid var(--border); overflow: hidden;
}
.ab-castpanel-bar .reader-synth-fill {
height: 100%;
}
#ab-cv-fill-text {
position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
font-size:12px; font-weight:800; color:var(--text);
text-shadow:0 1px 2px var(--bg), 0 -1px 2px var(--bg);
pointer-events:none; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; padding:0 8px;
}
.ab-castpanel-foot { display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 10px 12px; border-top: 1px solid var(--border); background: var(--bg); flex-shrink: 0; z-index: 10; position: relative; }
.ab-castpanel-foot #ab-cv-cancel { flex: 0 0 auto; margin-right: 0 !important; }
.ab-cv-done { font-size: 13px; font-weight: 700; display: inline-flex; align-items: center; gap: 6px; }
.ab-cv-done .mdi { color: #10b981; }
/* minimised → just the header chip in the corner */
.ab-castpanel.minimized { width: auto; max-width: 320px; height: auto; min-height: auto; resize: none; }
.ab-castpanel.minimized .ab-castpanel-bar,
.ab-castpanel.minimized .ab-cv-body,
.ab-castpanel.minimized .ab-castpanel-foot { display: none; }
.ab-castpanel.minimized .ab-castpanel-head { cursor: pointer; border-bottom: none; }
.ab-castpanel-inline {
display: flex;
flex-direction: column;
background: var(--panel);
/* Bound to the viewport so the feed scrolls internally instead of pushing
the action bar (Continue casting / Edit in Rehearser / ...) down the page
— without this, .ab-cv-body's flex:1 has no height to divide up against. */
height: calc(100vh - 230px);
min-height: 420px;
overflow: hidden;
}
.ab-cv-body { display: grid; grid-template-columns: minmax(0, 1fr) 220px; gap: 12px; padding: 12px; flex: 1; min-height: 0; min-width: 0; transition: grid-template-columns .15s; }
.ab-cv-body.side-collapsed { grid-template-columns: minmax(0, 1fr) 44px; }
.ab-cv-feed-wrap { position: relative; min-height: 0; min-width: 0; display: flex; flex-direction: column; background: var(--panel); }
.ab-cv-topbar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
padding: 0 6px 8px;
flex: 0 0 auto;
min-width: 0;
}
.ab-edit-toolbar {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 4px;
flex: 0 0 auto;
margin-left: auto;
}
.ab-edit-btn {
width: 28px;
height: 28px;
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--surface);
color: var(--subtext);
cursor: pointer;
}
.ab-edit-btn:hover:not(:disabled) { color: var(--accent); border-color: var(--accent); background: var(--panel); }
.ab-edit-btn:disabled { opacity: .42; cursor: default; }
.ab-page-nav {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 4px;
flex: 0 0 auto;
}
.ab-page-select {
min-width: 112px;
height: 28px;
padding: 3px 8px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--surface);
color: var(--text);
font-size: 12px;
}
.ab-page-nav-btn {
width: 28px;
height: 28px;
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--surface);
color: var(--subtext);
cursor: pointer;
}
.ab-page-nav-btn:hover { color: var(--accent); border-color: var(--accent); background: var(--panel); }
.ab-cv-feed { flex: 1; min-height: 0; min-width: 0; overflow-y: auto; overflow-x: hidden; border: 0px solid var(--border); border-radius: 0px; padding: 0px 10px 10px 0px; background: none; display: flex; flex-direction: column; gap: 18px; }
/* Each source page renders as its own "paper" card — white surface, thin
border, soft shadow — sitting on the feed's canvas background, so a long
book reads like a paginated document instead of one unbroken stream. */
.ab-cv-page {
/* Merged "paper" look: Casting's stacked-card border/shadow + Rehearser's
off-white paper background/font/colour (kept a fixed light paper even in
dark mode, same as .reh-a4-page, since it's meant to read as a printed page). */
background: #fff;
color: #1a1a2e;
font-family: 'Courier New', Courier, monospace;
font-size: calc(12pt * var(--reh-stage-scale, 1));
border-top: 1px solid var(--border);
border-left: 1px solid var(--border);
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
border-radius: 0px;
box-shadow: 5px 5px 10px rgba(0, 0, 0, .08);
padding: 14px 16px;
display: flex; flex-direction: column; gap: 3px;
}
[data-theme="dark"] .ab-cv-page { background: #f8f8f2; color: #1a1a2e; }
/* A fully-cast long book keeps EVERY page's full DOM forever (deliberate —
"keep the full completed cast available for review"), which measured at
~40,000 live nodes for a real 235-page book — confirmed live as a serious
memory/layout cost, and a real contributor to tab instability on top of
whatever else is running in the same tab (PDF canvases, an OCR worker...).
`content-visibility: auto` lets the browser skip layout/paint/style work
for whichever page groups are off-screen without touching a single line
of the scroll/search/click-handler JS that assumes every row still
physically exists in the DOM — the nodes stay, the browser just stops
doing expensive work on the ones nobody can see. `contain-intrinsic-size`
gives it a rough placeholder height before a page's real size is ever
measured, so scrolling doesn't jump around before that happens. */
.ab-cv-page { content-visibility: auto; contain-intrinsic-size: auto 500px; }
/* Long unbroken passage strings must wrap, never widen the layout (it was
pushing the sidebar out of frame). */
.ab-cv-row { min-width: 0; overflow-wrap: anywhere; word-break: break-word; }
.ab-cv-llm-preview { overflow-wrap: anywhere; word-break: break-word; }
.ab-cv-llm-pre { white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word; max-width: 100%; margin: 0; }
.ab-cv-jump-btn {
position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%);
display: flex; align-items: center; gap: 4px;
padding: 5px 14px; font-size: 12px; font-weight: 700;
background: var(--accent); color: #fff; border: none; border-radius: 20px;
cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,.25); z-index: 5;
white-space: nowrap;
}
.ab-cv-jump-btn:hover { filter: brightness(1.1); }
.ab-cv-row {
display: block;
font-family: 'Courier New', Courier, monospace;
/* Fixed px here silently defeated the A-/A+ controls (which set
--reh-stage-scale on an ancestor) — this hardcoded size always won over
the inherited calc() on .ab-cv-page, so the buttons visibly changed
nothing. Scale it the same way. */
font-size: calc(13.5px * var(--reh-stage-scale, 1));
line-height: 1.5;
padding: 20px 50px;
margin-bottom: 4px;
position: relative;
}
.ab-cv-row-tools {
position: absolute;
top: 4px;
right: 4px;
display: inline-flex;
gap: 2px;
opacity: 0;
pointer-events: none;
transition: opacity .12s;
}
.ab-cv-row:hover .ab-cv-row-tools,
.ab-cv-row:focus-within .ab-cv-row-tools {
opacity: 1;
pointer-events: auto;
}
.ab-cv-row-tool {
width: 24px;
height: 24px;
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--surface);
color: var(--subtext);
cursor: pointer;
font-size: 15px;
box-shadow: 0 2px 6px rgba(0,0,0,.12);
}
.ab-cv-row-tool:hover { color: var(--accent); border-color: var(--accent); background: var(--panel); }
.ab-cv-row.is-narr { opacity: .85; }
.ab-cv-edit-ta {
width: 100%; min-height: 60px; resize: vertical; font: inherit; color: inherit;
background: rgba(37,99,235,.06); border: 1px solid var(--accent); border-radius: 4px;
padding: 4px 6px; outline: none;
}
.ab-cv-spk {
display: block;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
margin-bottom: 2px;
}
.ab-cv-row:not(.is-narr):not(.is-processing) .ab-cv-spk {
padding-left: 120px;
cursor: pointer;
border-radius: 4px;
transition: background 0.15s;
}
.ab-cv-row:not(.is-narr):not(.is-processing) .ab-cv-spk:hover {
background: rgba(37,99,235,0.08);
}
.ab-cv-row.is-assigning {
background: rgba(245,158,11,0.1) !important;
outline: 2px dashed rgba(245,158,11,0.5);
outline-offset: -2px;
border-radius: 6px;
}
.ab-cv-row.is-assigning .ab-cv-spk {
background: rgba(245,158,11,0.2);
color: #d97706 !important;
}
.ab-cv-row:not(.is-narr):not(.is-processing) .ab-cv-txt {
display: block;
padding-left: 60px;
/*max-width: 500px;*/
}
.ab-cv-row.is-narr .ab-cv-spk {
display: block;
font-weight: 600;
padding-left: 0;
font-size: 11px;
}
.ab-cv-row.is-processing {
font-family: inherit;
display: block;
padding: 4px 8px;
}
.ab-cv-llm-head { display: flex; align-items: center; gap: 6px; }
.ab-cv-row.is-processing .ab-cv-spk {
display: inline-block;
padding-left: 0;
letter-spacing: normal;
text-transform: none;
font-size: 12px;
margin: 0;
}
.ab-cv-expand-btn {
border: none; background: none; cursor: pointer;
color: var(--subtext); padding: 0 2px; line-height: 1;
font-size: 15px; border-radius: 4px;
}
.ab-cv-expand-btn:hover { color: var(--text); background: var(--panel); }
.ab-cv-llm-preview {
font-size: 12px; color: var(--subtext); font-style: italic;
padding: 2px 0 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ab-cv-llm-pre {
font-family: inherit; font-size: 12px; color: var(--text);
white-space: pre-wrap; word-break: break-word;
background: var(--bg); border: 1px solid var(--border);
border-radius: 6px; padding: 8px 10px; margin: 0;
max-height: 260px; overflow-y: auto;
}
.ab-cv-page-label {
width: calc(100% + 4px);
border: 0;
background: transparent;
display: flex; align-items: center; gap: 6px;
font-size: 11px; font-weight: 700; letter-spacing: .06em;
color: var(--subtext); text-transform: uppercase;
padding: 0 0 8px;
border-bottom: 1px dashed var(--border);
margin: -2px -2px 10px;
text-align: left;
cursor: pointer;
}
.ab-cv-page-label .mdi { font-size: 13px; opacity: .7; }
.ab-cv-page-label:hover { color: var(--accent); }
.ab-cv-page-back { margin-left: auto; }
.ab-cv-txt { color: var(--text); white-space: pre-wrap; word-wrap: break-word; }
/* Every word in the narration/dialogue text is individually clickable — the
basis for "click a name in the text to assign", including names the app
doesn't already know (drag across a multi-word one to select it all). */
/* Live LLM view while a passage is processing: passage left, the LLM's live
thinking/raw-output stream right. Collapsed by default; toggled by the
chevron button in .ab-cv-llm-head. */
.ab-cv-llm-split { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 6px; }
.ab-cv-llm-col { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.ab-cv-llm-col-label { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--subtext); display: flex; align-items: center; gap: 5px; }
.ab-cv-think {
margin: 0; height: 240px; min-height: 80px; max-height: 80vh; resize: vertical; overflow-y: auto; white-space: pre-wrap;
overflow-wrap: anywhere; font-size: 11.5px; line-height: 1.5; color: var(--text);
background: rgba(37,99,235,.05); border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px;
}
.ab-cv-llm-split .ab-cv-llm-pre { height: 240px; min-height: 80px; max-height: 80vh; resize: vertical; overflow-y: auto; font-size: 11.5px; border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px; background: var(--panel); }
@media (max-width: 900px) { .ab-cv-llm-split { grid-template-columns: 1fr; } }
/* Heading-like narration (recovered chapter titles, OCR headline bands):
bold, larger, centered so titles read as titles inside the paper page. */
.ab-cv-row.is-heading .ab-cv-txt {
display: block; text-align: center; font-weight: 700;
font-size: 1.25em; letter-spacing: .02em; padding: 6px 0;
}
.ab-font-ctl { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
.ab-font-ctl .ab-page-nav-btn { width: auto; padding: 0 8px; font-size: 12px; font-weight: 700; }
.ab-name-hit { cursor: pointer; border-radius: 2px; }
.ab-name-hit:hover { background: rgba(37,99,235,.14); text-decoration: underline; text-decoration-style: dotted; }
.ab-cv-txt { cursor: pointer; }
/* Single reused overlay marking the word under the cursor (positioned in JS
from the caret range) — replaces per-word spans, which at book scale meant
~100k extra DOM nodes and froze the page. */
.ab-word-hover {
position: fixed; z-index: 5; pointer-events: none;
background: rgba(37,99,235,.16); border-radius: 3px;
outline: 1px dotted rgba(37,99,235,.55);
}
.ab-word-hover[hidden] { display: none; }
.ab-cv-note { font-size: 11.5px; color: var(--subtext); font-style: italic; padding: 3px 0 3px 4px; border-left: 2px solid var(--border); font-family: sans-serif; }
.ab-cv-side {
border: 1px solid var(--border); border-radius: 8px; padding: 8px; background: var(--panel);
min-height: 0; display: flex; flex-direction: column; overflow: hidden;
}
.ab-cv-side-head { display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--subtext); margin-bottom: 6px; }
.ab-cv-side-title { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ab-cv-side-collapse { border: none; background: none; color: var(--subtext); cursor: pointer; padding: 2px; border-radius: 4px; line-height: 1; flex-shrink: 0; }
.ab-cv-side-collapse:hover { background: var(--surface); color: var(--text); }
.ab-cv-side-done { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--border); flex: 0 0 auto; }
.ab-cv-side-tools { display: flex; gap: 4px; margin-bottom: 6px; flex: 0 0 auto; }
.ab-cv-side-search {
flex: 1; min-width: 0; padding: 4px 7px; font-size: 11.5px; border: 1px solid var(--border);
border-radius: 5px; background: var(--surface); color: var(--text); outline: none;
}
.ab-cv-side-search:focus { border-color: var(--accent); }
.ab-cv-side-sort {
padding: 4px 5px; font-size: 11px; border: 1px solid var(--border); border-radius: 5px;
background: var(--surface); color: var(--text); cursor: pointer; flex-shrink: 0;
}
.ab-cv-side.is-collapsed .ab-cv-side-tools { display: none; }
/* flex:1 is the actual fix here — without it this just sizes to its own
content like any other block element, ignoring .ab-cv-side's bounded
height entirely, so its own overflow-y:auto never has anything to
constrain against: the list silently grows past the panel (clipped only
by the parent's overflow:hidden, with no scrollbar at all) instead of
scrolling internally. Confirmed live as the reported "Characters found"
sidebar having no scrollbar and leaving a mismatched empty gap in the
feed column next to it (the grid row stretches to fit the taller,
unbounded sidebar content). */
.ab-cv-chars { flex: 1; display: block; min-height: 0; overflow-y: auto; padding-right: 2px; }
.ab-cv-empty { font-size: 12px; color: var(--subtext); font-style: italic; }
/* Collapsed sidebar: shrink to just the avatar dots, hide name/count/labels.
The grid column itself is narrowed via .ab-cv-body.side-collapsed. */
.ab-cv-side.is-collapsed { padding: 8px 4px; }
.ab-cv-side.is-collapsed .ab-cv-side-title,
.ab-cv-side.is-collapsed .ab-char-name,
.ab-cv-side.is-collapsed .ab-char-count { display: none; }
.ab-cv-side.is-collapsed .ab-char-item { justify-content: center; padding: 4px 0; }
.ab-cv-side.is-collapsed .ab-char-dot { margin: 0; }
/* Skeleton loading placeholders */
.ab-skel-feed { padding:8px 0; }
.ab-skel-chars { padding:4px 0; }
.ab-skel-row, .ab-skel-char-row {
display:flex; align-items:center; gap:8px;
padding:6px 10px; border-radius:4px;
opacity:.55;
}
.ab-skel-row { flex-direction:column; align-items:flex-start; gap:5px; margin-bottom:2px; }
.ab-skel-row.ab-skel-dlg { flex-direction:row; flex-wrap:wrap; align-items:center; }
.ab-skel-line {
height:10px; border-radius:4px;
background:linear-gradient(90deg, var(--border) 25%, var(--surface) 50%, var(--border) 75%);
background-size:200% 100%;
animation:skeletonSweep 1.4s ease-in-out infinite;
}
.ab-skel-narr .ab-skel-line { height:9px; }
.ab-skel-dlg .ab-skel-line { height:11px; }
.ab-skel-spk {
width:52px; height:11px; border-radius:4px; flex-shrink:0;
background:linear-gradient(90deg, var(--border) 25%, var(--surface) 50%, var(--border) 75%);
background-size:200% 100%;
animation:skeletonSweep 1.4s ease-in-out infinite;
opacity:.9;
}
.ab-skel-dot {
width:26px; height:26px; border-radius:50%; flex-shrink:0;
background:linear-gradient(90deg, var(--border) 25%, var(--surface) 50%, var(--border) 75%);
background-size:200% 100%;
animation:skeletonSweep 1.4s ease-in-out infinite;
}
.ab-skel-num {
width:18px; height:10px; border-radius:4px; margin-left:auto;
background:linear-gradient(90deg, var(--border) 25%, var(--surface) 50%, var(--border) 75%);
background-size:200% 100%;
animation:skeletonSweep 1.4s ease-in-out infinite;
}
.ab-skel-char-row .ab-skel-line { height:10px; flex:1; }
/* stagger animation delays for a wave effect */
.ab-skel-row:nth-child(2) .ab-skel-line,
.ab-skel-row:nth-child(2) .ab-skel-spk { animation-delay:.15s; }
.ab-skel-row:nth-child(3) .ab-skel-line,
.ab-skel-row:nth-child(3) .ab-skel-spk { animation-delay:.3s; }
.ab-skel-row:nth-child(4) .ab-skel-line,
.ab-skel-row:nth-child(4) .ab-skel-spk { animation-delay:.45s; }
.ab-skel-row:nth-child(5) .ab-skel-line { animation-delay:.6s; }
.ab-skel-row:nth-child(6) .ab-skel-line { animation-delay:.75s; }
.ab-skel-char-row:nth-child(2) * { animation-delay:.1s; }
.ab-skel-char-row:nth-child(3) * { animation-delay:.2s; }
.ab-skel-char-row:nth-child(4) * { animation-delay:.3s; }
.ab-skel-char-row:nth-child(5) * { animation-delay:.4s; }
/* Character list rows in the casting side panel */
.ab-char-item {
position: relative;
display:flex; align-items:center; gap:8px; padding:7px 10px;
border-radius:8px; cursor:pointer; transition:background .12s, border-color .12s;
overflow: hidden;
min-height: 44px;
}
.ab-char-item:hover, .ab-char-item.is-active { background:var(--surface); }
.ab-char-item.is-active { border-left:2px solid var(--accent); padding-left:6px; }
.ab-char-item > :not(.cs-progress-fillmeta) { position: relative; z-index: 1; }
.ab-char-dot {
width:30px; height:30px; border-radius:50%; flex-shrink:0;
display:flex; align-items:center; justify-content:center;
font-size:13px; font-weight:800; color:#fff;
box-shadow: 0 2px 6px rgba(0,0,0,.14), inset 0 0 0 1px rgba(255,255,255,.28);
border: 1px solid rgba(255,255,255,.28);
}
/* border-color is set inline per-row to the character's own cast color, so a
real portrait still reads as "this character" at a glance in a long list,
the same way the plain colored-letter dot already does via its background. */
.ab-char-dot-img { overflow: hidden; background: var(--panel); border-width: 2px; }
.ab-char-dot-img img { width: 100%; height: 100%; object-fit: cover; }
.ab-char-name { flex:1; font-size:14px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width: 0; }
.ab-char-count {
margin-left: auto;
flex-shrink: 0;
min-width: 24px;
display: inline-flex;
align-items: center;
justify-content: flex-end;
color: var(--subtext);
font-weight: 700;
line-height: 1;
font-size: 14px;
}
.ab-char-count-divider {
width: 16px;
height: 1px;
background: color-mix(in srgb, var(--subtext) 55%, transparent);
border-radius: 999px;
}
.ab-char-alias-btn {
flex-shrink: 0; width: 20px; height: 20px; border-radius: 4px; border: none;
background: none; color: var(--subtext); cursor: pointer; display: none;
align-items: center; justify-content: center; font-size: 13px;
}
.ab-char-item:hover .ab-char-alias-btn { display: inline-flex; }
.ab-char-alias-btn:hover { background: var(--panel); color: var(--accent); }
/* Sidebar's own collapse state hides the count/name anyway; keep the alias
button out of the way rather than fighting for the 44px column. */
.ab-cv-side.is-collapsed .ab-char-alias-btn { display: none !important; }
.ab-cv-chars .ab-char-item + .ab-char-item { margin-top: 4px; }
.ab-alias-popup {
position: fixed; z-index: 2002; width: 260px;
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
box-shadow: 0 10px 25px rgba(0,0,0,.35); padding: 10px; display: flex; flex-direction: column; gap: 8px;
}
.ab-alias-popup-title { font-size: 12px; color: var(--subtext); }
.ab-alias-popup-title b { color: var(--text); }
.ab-alias-popup-inp {
width: 100%; padding: 6px 8px; font-size: 12.5px; border: 1px solid var(--border);
border-radius: 6px; background: var(--bg, var(--surface)); color: var(--text); outline: none;
}
.ab-alias-popup-inp:focus { border-color: var(--accent); }
.ab-alias-popup-hint { font-size: 10.5px; color: var(--subtext); text-transform: uppercase; letter-spacing: .03em; font-weight: 700; margin-top: -2px; }
.ab-alias-popup-list { display: flex; flex-direction: column; gap: 2px; max-height: 180px; overflow-y: auto; }
.ab-alias-merge-opt {
display: flex; justify-content: space-between; align-items: center; gap: 8px;
padding: 5px 7px; font-size: 12px; border: 1px solid transparent; border-radius: 5px;
background: none; color: var(--text); cursor: pointer; text-align: left;
}
.ab-alias-merge-opt:hover { background: var(--panel); border-color: var(--border); }
.ab-alias-merge-name { display: flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ab-alias-merge-name .ab-char-dot { width: 18px; height: 18px; font-size: 9px; }
.ab-alias-merge-count { font-size: 10.5px; color: var(--subtext); font-weight: 700; flex-shrink: 0; }
.ab-alias-popup-actions { display: flex; justify-content: flex-end; gap: 6px; }
/* Grouped footer flyout menus (Identify / Cast / View & Export Characters) —
opens upward from a bottom toolbar, fixed-position + body-appended so it's
never clipped by the scrolling panel it lives in. */
.ab-foot-trigger.is-menu-open { border-color: var(--accent); color: var(--accent); }
.ab-foot-menu {
position: fixed; z-index: 2002; min-width: 240px; max-width: 320px;
max-height: calc(100vh - 24px); overflow-y: auto;
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
box-shadow: 0 10px 25px rgba(0,0,0,.35); padding: 6px; display: flex; flex-direction: column; gap: 2px;
}
.ab-foot-menu-item {
display: flex; align-items: center; gap: 10px;
padding: 8px 10px; font-size: 13px; font-weight: 600; text-align: left;
border: none; border-radius: 7px; background: none; color: var(--text); cursor: pointer;
}
.ab-foot-menu-item:hover:not(:disabled) { background: var(--panel); }
.ab-foot-menu-item:disabled { opacity: .4; cursor: not-allowed; }
.ab-foot-menu-item .mdi { font-size: 16px; color: var(--subtext); flex-shrink: 0; }
.ab-foot-menu-item.is-danger { color: var(--error); }
.ab-foot-menu-item.is-danger .mdi { color: var(--error); }
.ab-foot-menu-item-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ab-foot-menu-sep { height: 1px; margin: 4px 6px; background: var(--border); }
/* Character detail panel inside the casting feed area */
.ab-char-detail-panel {
display:flex; flex-direction:column; overflow-y:auto;
height:100%; border:1px solid var(--border); border-radius:8px;
background:var(--panel);
}
.ab-char-detail-back {
display:inline-flex; align-items:center; gap:6px;
background:none; border:none; cursor:pointer; color:var(--accent);
font-size:13px; padding:10px 14px 6px; opacity:.85; flex-shrink:0;
}
.ab-char-detail-back:hover { opacity:1; }
.ab-char-detail-panel .lcd-header { border-radius:0; flex-shrink:0; }
.ab-cd-body { padding:0; }
.ab-cd-body .lcd-voice-top button {
padding:3px 8px; font-size:11px; border:1px solid var(--border);
border-radius:4px; background:none; cursor:pointer; color:var(--text);
}
.ab-cd-edit-btn {
background:rgba(255,255,255,.15); border:1px solid rgba(255,255,255,.3);
border-radius:6px; cursor:pointer; color:#fff; padding:5px 8px;
font-size:14px; display:flex; align-items:center; line-height:1;
transition:background .15s;
}
.ab-cd-edit-btn:hover { background:rgba(255,255,255,.28); }
.ab-cd-header-actions { position:absolute; top:10px; right:10px; display:flex; align-items:center; gap:8px; z-index:3; }
.ab-cd-refine-btn {
background:rgba(255,255,255,.15); border:1px solid rgba(255,255,255,.3);
border-radius:6px; cursor:pointer; color:#fff; padding:5px 10px;
font-size:12px; font-weight:700; display:flex; align-items:center; gap:6px; line-height:1;
transition:background .15s;
}
.ab-cd-refine-btn:hover { background:rgba(255,255,255,.28); }
/* editable fields: show hint border in edit mode */
.ab-cd-editing .ab-editable {
border-bottom:1px dashed var(--accent);
outline:none; cursor:text; min-height:1.3em;
border-radius:2px; padding:1px 2px;
}
.ab-cd-editing .ab-editable:focus { background:rgba(124,106,247,.07); }
.ab-cd-body .lcd-voice-top .ab-cd-pick:hover { border-color:var(--accent); color:var(--accent); }
.ab-cd-body .lcd-voice-top .ab-cd-auto:hover { border-color:var(--green,#22c55e); color:var(--green,#22c55e); }
.ab-cd-body .lcd-voice-top .ab-cd-online:hover { border-color:#0ea5e9; color:#0ea5e9; }
.ab-cd-color {
display:inline-flex; align-items:center; gap:5px;
padding:3px 7px; border:1px solid var(--border); border-radius:4px;
color:var(--subtext); cursor:pointer; line-height:1;
}
.ab-cd-color:hover { border-color:var(--accent); color:var(--accent); }
.ab-cd-color input {
width:22px; height:18px; padding:0; border:0; background:transparent; cursor:pointer;
}
.cl-edit-color input[type="color"] {
width:48px; height:30px; padding:2px; cursor:pointer;
}
/* Character selection bar (compact bar above the casting feed) */
.ab-char-bar[hidden] { display: none; }
.ab-char-bar {
display:flex; align-items:center; gap:8px;
flex:1 1 430px; min-width:280px; max-width:100%;
padding:6px 10px; margin:0;
background:var(--panel); border:1px solid var(--border); border-radius:8px;
}
.ab-char-bar-dot {
width:32px; height:32px; border-radius:50%; flex-shrink:0;
display:flex; align-items:center; justify-content:center;
font-size:13px; font-weight:700; color:#fff;
}
.ab-char-bar-info { display:flex; flex-direction:column; min-width:0; flex-shrink:0; }
.ab-char-bar-name { font-size:13px; font-weight:700; white-space:nowrap; }
.ab-char-bar-cnt { font-size:11px; opacity:.5; }
.ab-char-bar-nav { display:flex; align-items:center; gap:4px; flex-shrink:0; }
.ab-char-bar-nav button {
width:26px; height:26px; border-radius:50%;
border:1px solid var(--border); background:none; cursor:pointer; color:var(--text);
display:flex; align-items:center; justify-content:center; font-size:15px;
}
.ab-char-bar-nav button:hover { background:var(--panel); border-color:var(--accent); }
.ab-char-bar-pos { font-size:11px; opacity:.6; min-width:44px; text-align:center; }
.ab-char-bar-search {
flex:1; min-width:140px; max-width:none;
padding:4px 8px; font-size:12px;
border:1px solid var(--border); border-radius:6px;
background:var(--bg,var(--surface)); color:var(--text); outline:none;
}
.ab-char-bar-search:focus { border-color:var(--accent); }
.ab-char-bar-profile, .ab-char-bar-close {
padding:4px 8px; font-size:12px; flex-shrink:0;
border:1px solid var(--border); border-radius:6px;
background:none; cursor:pointer; color:var(--text);
display:inline-flex; align-items:center; gap:4px;
}
.ab-char-bar-profile:hover { border-color:var(--accent); color:var(--accent); }
.ab-char-bar-close { padding:4px 6px; }
.ab-char-bar-close:hover { border-color:#f87171; color:#f87171; }
/* Feed row highlights for selected character */
.ab-cv-row.ab-char-hl { background:rgba(124,106,247,.08); }
.ab-cv-row.ab-char-focus { background:rgba(124,106,247,.20); border-left:3px solid var(--accent); padding-left:5px; }
/* Keep old ab-chip for any legacy use */
.ab-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; padding: 3px 8px; border: 1px solid var(--border); border-radius: 20px; cursor: pointer; transition: background 0.1s; }
.ab-chip:hover { background: var(--panel); border-color: var(--accent); }
.ab-chip-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--c); flex-shrink: 0; }
.ab-chip b { margin-left: auto; color: var(--subtext); font-weight: 700; }
.audiobook-narr-note { color: var(--subtext); }
@media (max-width: 900px) {
.ab-cv-topbar { flex-wrap: wrap; }
.ab-char-bar { flex-basis: 100%; }
.ab-edit-toolbar { margin-left: 0; }
}
@media (max-width: 560px) { .ab-cv-body { grid-template-columns: 1fr; } .ab-cv-side { height: auto; max-height: 22vh; } }
/* Audiobook casting overlay */
.audiobook-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.45); display: flex; align-items: center; justify-content: center; z-index: 1000; }
.audiobook-box { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 22px 24px; width: min(420px, 90vw); box-shadow: 0 12px 40px rgba(0,0,0,.25); }
.audiobook-title { font-weight: 800; font-size: 15px; display: flex; align-items: center; gap: 8px; }
.audiobook-title .mdi { color: var(--accent); font-size: 20px; }
.audiobook-msg { color: var(--subtext); font-size: 13px; margin: 10px 0 12px; }
.audiobook-box .reader-synth-track { width: 100%; }
.audiobook-box label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; font-weight: 600; color: var(--subtext); }
.audiobook-box label input[type="text"] { font: inherit; font-weight: 400; color: var(--text); padding: 7px 9px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); }
.audiobook-actions { margin-top: 14px; text-align: right; display: flex; gap: 8px; justify-content: flex-end; }
/* Avatar lightbox — click any character avatar to open */
.avatar-lightbox-box { width: min(1180px, 96vw); max-height: 92vh; overflow-y: auto; }
.alb-body { display: flex; gap: 32px; margin-top: 20px; flex-wrap: wrap; }
.alb-preview { flex: 0 0 440px; }
.alb-preview img { width: 440px; height: 440px; object-fit: cover; border-radius: 14px; border: 1px solid var(--border); }
.alb-preview-empty {
width: 440px; height: 440px; border-radius: 14px; border: 1px dashed var(--border);
display: flex; align-items: center; justify-content: center; font-size: 120px; color: var(--subtext); opacity: .5;
}
.alb-actions { flex: 1; min-width: 340px; display: flex; flex-direction: column; gap: 22px; }
.alb-section-label { font-size: 14px; font-weight: 700; color: var(--subtext); display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.alb-section input[type="file"] { font-size: 13.5px; width: 100%; }
.alb-url-row { display: flex; gap: 8px; }
.alb-url-row input { flex: 1; min-width: 0; font-size: 13.5px; padding: 8px 10px; }
#alb-prompt { width: 100%; font-size: 13.5px; font-family: inherit; resize: vertical; padding: 10px; min-height: 140px; }
.alb-gen-row { display: flex; gap: 8px; align-items: center; margin-top: 8px; }
.alb-gen-row select { flex: 1; min-width: 0; font-size: 13.5px; padding: 8px 10px; }
.alb-gen-row .btn-primary { font-size: 13.5px; padding: 9px 16px; }
@media (max-width: 820px) {
.alb-preview, .alb-preview img, .alb-preview-empty { flex-basis: auto; width: min(440px, 80vw); height: min(440px, 80vw); }
.alb-actions { min-width: 0; width: 100%; }
}
#alb-status { margin-top: 10px; }
.ab-recast-select-list { max-height: 320px; overflow-y: auto; margin: 10px 0; text-align: left; border: 1px solid var(--border); border-radius: 6px; padding: 4px; }
.ab-recast-select-list .ab-char-item + .ab-char-item { margin-top: 2px; }
.ab-recast-select-list .ab-recast-cb { flex-shrink: 0; width: 16px; height: 16px; cursor: pointer; }
.ab-recast-select-list .ab-cv-empty { padding: 16px; text-align: center; color: var(--subtext); font-size: 13px; }
.audiobook-count { font-weight: 500; font-size: 12px; color: var(--subtext); margin-left: auto; }
.audiobook-preview-box { width: min(760px, 94vw); }
.audiobook-preview-box .audiobook-title { flex-wrap: wrap; }
.audiobook-seglist { max-height: 56vh; overflow-y: auto; border: 1px solid var(--border); border-radius: 8px; padding: 6px; margin-top: 6px; }
.audiobook-seg { display: grid; grid-template-columns: 130px 96px 1fr; gap: 8px; align-items: center; padding: 4px 6px; border-radius: 6px; }
.audiobook-seg:nth-child(odd) { background: var(--panel); }
.audiobook-seg.is-dialog { box-shadow: inset 3px 0 0 var(--accent); }
.audiobook-seg input { padding: 3px 6px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface); color: var(--text); font-size: 12px; font-family: var(--font); min-width: 0; }
.audiobook-seg input:disabled { opacity: .4; }
.audiobook-seg-text { font-size: 12px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#reh-tb-audiobook .mdi { color: var(--accent); }
#reader-charsheets-btn .mdi, #reh-charsheets-btn .mdi { color: var(--accent); }
/* Character sheets overlay */
.cs-box { width: min(1120px, 96vw); max-height: 90vh; display: flex; flex-direction: column; }
.cs-page-shell { width: 100%; max-width: none; }
#s-reader #reader-charsheets-panel { display: flex; flex-direction: column; flex: 1; min-height: 0; }
#s-caststudio #reader-charsheets-panel { display: flex; flex-direction: column; flex: 1; min-height: 0; }
#s-reader #reader-charsheets-panel .cs-progress-box-big,
#s-caststudio #reader-charsheets-panel .cs-progress-box-big,
#s-reader #reader-charsheets-panel .cs-page-shell,
#s-caststudio #reader-charsheets-panel .cs-page-shell {
width: 100%;
max-width: none;
}
/* Embedded inline, this has been through three wrong attempts:
(1) a fixed/viewport-relative height left a gap below the box whenever
the section (a fixed, full-height flex column needed for other
content like the PDF reader) was taller than the box needed to be;
(2) flex:1 (forcing the box to fill that whole section) fixed that gap,
but then forced .cs-progress-preview (flex:1 itself, scrolling a
single character's card) to stretch to match — so a SHORT card left
the SAME empty gap one level down, inside the preview panel instead
of below the box;
(3) making the BOX ALSO shrink-to-content (flex:0 1 auto) to fix that,
intending "short content -> short box" — but .cs-progress-layout
(the box's own direct child) is itself `flex:1` (meant to fill
whatever height the box has), which made the box's "content size"
circular: the box has no real min-content height to shrink to as
long as its child is a flex:1 filler, so it silently kept resolving
to the max-height CEILING regardless of how little was actually
generated yet — confirmed live: an 8-character result still filled
the box to the exact 90vh cap, even though almost nothing had been
generated, leaving a huge empty gap below the small amount of real
content.
Back to flex:1 (the box fills the section, no gap below it — that part
of (2) was never actually wrong) and rely ENTIRELY on the preview/output
split below (.cs-progress-preview shrink + .cs-progress-output absorbing
the rest) to keep short content from looking stretched-empty, since that
fix (unlike this one) doesn't fight a flex:1 child. */
#s-reader #reader-charsheets-panel .cs-progress-box-big,
#s-caststudio #reader-charsheets-panel .cs-progress-box-big {
height: auto;
flex: 1;
min-height: 0;
max-height: min(880px, 90vh);
box-shadow: none;
}
.cs-progress-box-big {
box-shadow: none;
}
.cs-progress-layout {
flex: 1;
min-height: 0;
display: grid;
grid-template-columns: minmax(0, 1fr) 300px;
gap: 14px;
margin-top: 12px;
align-items: stretch;
}
.cs-progress-layout.side-collapsed {
grid-template-columns: minmax(0, 1fr) 44px;
}
.cs-progress-left {
min-width: 0;
min-height: 0;
display: flex;
flex-direction: column;
gap: 12px;
min-height: 0;
}
.cs-titlebar { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.cs-list { overflow-y: auto; padding-right: 4px; display: grid; grid-template-columns: repeat(auto-fill, minmax(430px, 1fr)); gap: 14px; align-content: start; }
/* Compact cards (_charCardHtml, same as the Library's own character grid)
need a much narrower column than the old full-detail cards this grid
used to render. */
.cs-list.cs-list-compact { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
.cs-group-label { grid-column: 1 / -1; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--subtext); margin-top: 4px; }
.cs-card { border: 1px solid var(--border); border-radius: 8px; padding: 14px; background: color-mix(in srgb, var(--panel) 88%, var(--surface)); box-shadow: 0 8px 22px rgba(0,0,0,.08); }
.cs-card.cs-main { box-shadow: inset 4px 0 0 var(--accent), 0 8px 22px rgba(0,0,0,.08); }
.cs-card.cs-supp { box-shadow: inset 4px 0 0 var(--border), 0 8px 22px rgba(0,0,0,.08); }
.cs-header-pills {
display: flex;
flex-wrap: wrap;
gap: 7px;
margin-top: 10px;
}
.cs-header-pill {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 5px 10px;
border-radius: 999px;
border: 1px solid rgba(255,255,255,.24);
background: rgba(255,255,255,.14);
color: #fff;
box-shadow: 0 2px 6px rgba(0,0,0,.08);
}
.cs-header-pill .mdi { font-size: 14px; }
.cs-header-pill-label {
text-transform: uppercase;
letter-spacing: .05em;
font-size: 9px;
font-weight: 800;
opacity: .82;
}
.cs-header-pill-value {
font-size: 12px;
font-weight: 700;
white-space: nowrap;
}
.cs-header-pills-primary { margin-bottom: 2px; }
.cs-header-pills-primary + .lcd-tier-gender { margin-top: 8px; }
.lcd-header .cs-header-color {
flex-shrink: 0; align-self: flex-start;
background: rgba(255,255,255,.18); border: 1px solid rgba(255,255,255,.32); color: #fff;
}
.lcd-header .cs-header-color:hover { background: rgba(255,255,255,.32); border-color: rgba(255,255,255,.5); color: #fff; }
/* A too-narrow native color swatch can paint as garbled "###" text in some
Chromium builds before it settles — give it a bit more room than the
generic .ab-cd-color input default to avoid that. */
.lcd-header .cs-header-color input { width: 30px; height: 20px; min-width: 30px; }
.cs-header-actions {
display: flex;
gap: 8px;
flex-shrink: 0;
align-self: flex-start;
flex-wrap: wrap;
}
.cs-detail-hero-note {
padding: 12px 18px;
background: color-mix(in srgb, var(--panel) 82%, var(--surface));
border-bottom: 1px solid var(--border);
}
.cs-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cs-name { font-weight: 900; font-size: 17px; letter-spacing: .01em; }
.cs-archetype { font-size: 12px; font-weight: 700; color: var(--accent); }
.cs-tier { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--subtext); border: 1px solid var(--border); border-radius: 20px; padding: 1px 8px; }
.cs-head-btns { margin-left: auto; display: flex; gap: 4px; flex-shrink: 0; }
.cs-head-btns .btn-secondary { font-size: 10px; padding: 2px 7px; }
.cs-img-btn:hover { border-color: #a78bfa; color: #a78bfa; }
.cs-voice-btn:hover { border-color: var(--accent); color: var(--accent); }
.cs-meta-tags {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin: 4px 0 6px;
}
.cs-meta-tag {
display: inline-flex;
align-items: center;
gap: 6px;
border: 1px solid color-mix(in srgb, var(--border) 90%, transparent);
border-radius: 999px;
padding: 3px 8px;
background: color-mix(in srgb, var(--panel) 78%, transparent);
color: var(--subtext);
font-size: 11px;
line-height: 1;
}
.cs-meta-tag-label {
text-transform: uppercase;
letter-spacing: .04em;
font-size: 9px;
font-weight: 800;
color: var(--accent);
}
.cs-meta-tag-value {
font-style: italic;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 220px;
}
/* Character sheet card layout with avatar */
.cs-card-top { display: flex; gap: 14px; margin-bottom: 10px; }
.cs-card-top-body { flex: 1; min-width: 0; }
.cs-avatar {
width: 80px; height: 80px; border-radius: 10px; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
font-size: 28px; font-weight: 800; color: #fff;
cursor: pointer; position: relative; overflow: hidden;
border: 2px solid rgba(255,255,255,.1);
}
.cs-avatar img { width: 100%; height: 100%; object-fit: cover; }
.cs-avatar-overlay {
position: absolute; inset: 0; background: rgba(0,0,0,.5);
display: flex; align-items: center; justify-content: center;
opacity: 0; transition: opacity .15s; font-size: 20px; color: #fff;
}
.cs-avatar:hover .cs-avatar-overlay { opacity: 1; }
/* Library card avatar with image */
.lib-char-avatar { position: relative; overflow: hidden; cursor: pointer; }
.lib-char-avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.lib-char-avatar-cam {
position: absolute; inset: 0; background: rgba(0,0,0,.5);
display: flex; align-items: center; justify-content: center;
opacity: 0; transition: opacity .15s; font-size: 14px; color: #fff; border-radius: inherit;
}
.lib-char-avatar:hover .lib-char-avatar-cam { opacity: 1; }
/* Alignment gradient bar */
.cs-alignment-wrap { margin: 8px 0 6px; }
.cs-alignment-labels { display: flex; justify-content: space-between; font-size: 10px; color: var(--subtext); margin-bottom: 4px; text-transform: uppercase; letter-spacing: .04em; }
.cs-alignment-gradient {
position: relative; height: 20px; border-radius: 4px;
background: linear-gradient(to right, #111 0%, #444 25%, #888 50%, #ccc 75%, #f5f5f5 100%);
box-shadow: inset 0 1px 3px rgba(0,0,0,.5);
}
.cs-alignment-dot {
position: absolute; top: 50%; transform: translate(-50%, -50%);
width: 18px; height: 18px; border-radius: 50%;
background: #fff; border: 2px solid rgba(0,0,0,.7);
box-shadow: 0 0 0 2px rgba(255,255,255,.5), 0 2px 6px rgba(0,0,0,.6);
display: flex; align-items: center; justify-content: center;
}
.cs-alignment-arc-arrow {
font-size: 13px; line-height: 1; font-style: normal; margin-top: -1px;
text-shadow: 0 1px 3px rgba(0,0,0,.8);
}
.cs-arc-note { font-size: 11px; color: var(--subtext); margin-top: 3px; font-style: italic; }
.cs-progress-box { width: min(520px, 92vw); }
/* Big layout: passage | live output side by side, character sidebar on the
right (current/just-updated characters highlighted) — same shape as the
audiobook casting live view, so you can watch each sheet being built. */
.cs-progress-box-big { width: min(1400px, 96vw); height: min(880px, 90vh); display: flex; flex-direction: column; padding: 20px 22px; }
.cs-progress-head { flex-shrink: 0; }
.cs-progress-head .audiobook-msg { margin: 8px 0 10px; }
.cs-progress-prompt { padding: 10px 12px; margin: 0 0 10px; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; }
.cs-progress-prompt textarea {
width: 100%; font-family: monospace; font-size: 12.5px; font-weight: 500; padding: 10px;
line-height: 1.5; border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
color: var(--text); resize: vertical;
}
.cs-progress-prompt-actions { display: flex; justify-content: flex-end; margin-top: 8px; gap: 8px; align-items: center; }
.cs-progress-prompt-actions select { max-width: 200px; outline: none; border: 1px solid var(--border); border-radius: 4px; padding: 4px 8px; font-size: 12px; background: var(--surface); color: var(--text); }
.cs-progress-prompt-actions input { width: 140px; padding: 4px 8px; font-size: 12px; border: 1px solid var(--border); border-radius: 4px; background: var(--surface); color: var(--text); outline: none; }
.cs-progress-output {
display: flex;
flex-direction: column;
flex: 1 1 auto;
gap: 8px;
min-height: 120px;
max-height: 42vh;
overflow: auto;
resize: none;
position: relative;
padding: 10px 12px 12px;
border: 1px solid color-mix(in srgb, var(--border) 90%, transparent);
border-radius: 12px;
background: color-mix(in srgb, var(--panel) 72%, var(--surface));
box-shadow: 0 1px 0 rgba(255,255,255,.7) inset;
}
.cs-progress-footer {
margin-top: auto;
padding-top: 12px;
display: flex;
align-items: center;
gap: 12px;
}
.cs-progress-footer-track {
flex: 1 1 auto;
min-width: 0;
margin: 0;
height: 12px;
border-radius: 999px;
overflow: hidden;
}
.cs-progress-footer .reader-synth-fill { border-radius: inherit; }
.cs-progress-footer-actions {
margin: 0;
flex: none;
display: flex;
justify-content: flex-end;
}
.cs-progress-output-head {
display: flex; align-items: center; justify-content: space-between; gap: 8px;
font-size: 12.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--subtext);
margin-top: 6px;
}
.cs-progress-output-title { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.cs-progress-output .cs-progress-live-status { margin-left: 4px; }
.cs-progress-output.is-collapsed {
min-height: 140px;
max-height: 140px;
resize: none;
overflow: hidden;
padding-bottom: 10px;
}
.cs-progress-output.is-collapsed .cs-progress-body { display: flex; }
.cs-progress-output.is-collapsed .cs-progress-output-head { margin-top: 6px; }
/* A small centered grip bar on the panel's top edge, like a sheet handle,
instead of a boxed icon button floating over the bottom-right content. */
.cs-progress-resize-handle {
position: absolute; top: 5px; left: 50%; transform: translateX(-50%);
width: 44px; height: 5px; border-radius: 999px; padding: 0;
border: none;
background: color-mix(in srgb, var(--subtext) 35%, transparent);
cursor: ns-resize;
z-index: 3;
transition: background .15s, width .15s;
}
.cs-progress-resize-handle:hover,
.cs-progress-resize-handle:active { background: var(--accent); width: 56px; }
.cs-output-resizing, .cs-output-resizing * { cursor: ns-resize !important; }
.cs-progress-body { flex: 1; min-height: 0; display: flex; gap: 14px; margin-top: 0; }
.cs-progress-main { flex: 1; min-width: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.cs-progress-col { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 6px; }
.cs-progress-col-label {
display: flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 800;
text-transform: uppercase; letter-spacing: .04em; color: var(--subtext); flex-shrink: 0;
}
.cs-progress-passage-pre, .cs-progress-live-pre {
flex: 1; min-height: 0; margin: 0; padding: 10px 12px; overflow-y: auto; white-space: pre-wrap;
overflow-wrap: anywhere; font-size: 14px; line-height: 1.6; color: var(--text);
background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
}
.cs-progress-live-pre { background: rgba(37,99,235,.045); }
.cs-progress-output.is-collapsed .cs-progress-passage-pre,
.cs-progress-output.is-collapsed .cs-progress-live-pre {
font-size: 12.5px;
line-height: 1.45;
padding: 8px 10px;
min-height: 58px;
}
.cs-progress-side {
width: 100%;
flex-shrink: 0;
display: flex;
flex-direction: column;
gap: 8px;
min-height: 0;
/* NOT height:100% — the grid row's own height is itself content-derived
(no explicit row height on .cs-progress-layout), so a child asking for
"100% of the row" creates a circular reference that resolves back to
the child's own content size instead of actually matching the taller
sibling column. align-items:stretch on the grid already gives this a
real, definite computed height with no percentage involved — confirmed
live: removing this let the two columns match (was 180px vs the other
column's 371px; matched afterward). */
padding: 10px 8px 8px;
}
.cs-progress-side.is-collapsed {
padding: 8px 4px;
}
.cs-progress-layout.side-collapsed .cs-progress-side {
width: 44px;
}
.cs-progress-side.is-collapsed .ab-cv-side-title,
.cs-progress-side.is-collapsed .ab-cv-side-tools,
.cs-progress-side.is-collapsed .ab-cv-side-done {
display: none;
}
.cs-progress-side.is-collapsed .cs-progress-chars {
padding-right: 0;
}
.cs-progress-side .ab-char-item {
min-height: 48px;
padding: 8px 12px;
border-radius: 10px;
}
.cs-progress-side .ab-char-item.is-active {
padding-left: 10px;
}
.cs-progress-side .ab-char-dot {
width: 32px;
height: 32px;
font-size: 13px;
}
.cs-progress-side .ab-char-name {
font-size: 16px;
font-weight: 600;
}
.cs-progress-side .ab-char-count {
font-size: 14px;
}
.cs-progress-side-title { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--subtext); flex-shrink: 0; }
.cs-progress-preview {
/* Not flex:1 — when the sidebar has many characters (and so needs a tall
column to give the list room to scroll, per align-items:stretch on
.cs-progress-layout), flex:1 here forced THIS panel to stretch to
match, leaving a large empty gap below a short/not-yet-filled sheet
(confirmed live with a short card next to a 72-character sidebar).
Shrink-to-content instead; .cs-progress-output below absorbs any
leftover column height since it's the piece meant to grow (it already
scrolls its own passage/live-output text, unlike this preview which
shows one bounded character sheet). */
margin: 10px 0 0;
padding: 0;
min-height: 220px;
flex: 0 1 auto;
overflow: auto;
}
.cs-progress-left.is-output-collapsed .cs-progress-preview { min-height: 520px; }
.cs-progress-output.is-collapsed .cs-progress-output-title { opacity: .85; }
.cs-progress-output.is-working .cs-progress-output-title { color: var(--text); }
.cs-progress-preview .cs-card {
box-shadow: none;
border-radius: 12px;
margin: 0;
background: color-mix(in srgb, var(--panel) 92%, var(--surface));
}
.cs-progress-preview .cs-head-btns,
.cs-progress-preview .cs-sources {
display: none;
}
.cs-progress-preview .cs-avatar {
pointer-events: none;
cursor: default;
}
.cs-progress-preview-empty {
font-size: 13px;
color: var(--subtext);
font-style: italic;
border: 1px dashed var(--border);
border-radius: 10px;
padding: 12px;
background: color-mix(in srgb, var(--panel) 80%, transparent);
}
.cs-progress-chars { flex: 1; min-height: 0; overflow-y: auto; display: block; padding: 2px 2px 4px; }
.cs-progress-chars .ab-char-item + .ab-char-item { margin-top: 6px; }
/* Two-row roster card: a bigger avatar spanning both rows, name on top,
line count + profile completeness together underneath — instead of
cramming avatar/name/count into one flex row like the casting sidebar. */
.cs-progress-chars .ab-char-item {
display: grid;
grid-template-columns: 38px 1fr;
grid-template-rows: auto auto;
column-gap: 10px;
row-gap: 2px;
align-items: center;
min-height: 0;
padding: 8px 10px;
}
.cs-progress-chars .ab-char-dot {
grid-row: 1 / 3;
width: 38px; height: 38px; font-size: 15px;
}
.cs-progress-chars .ab-char-name { grid-column: 2; grid-row: 1; font-weight: 700; }
.cs-progress-chars .ab-char-meta {
grid-column: 2; grid-row: 2;
display: flex; align-items: center; gap: 6px;
font-size: 11.5px; color: var(--subtext); font-weight: 600;
}
.cs-progress-chars .ab-char-meta-sep { opacity: .45; }
.cs-progress-chars .ab-char-count { margin-left: 0; font-size: 11.5px; font-weight: 600; color: var(--subtext); }
.cs-progress-empty { font-size: 12px; color: var(--subtext); font-style: italic; text-align: center; padding: 20px 0; }
.cs-progress-chip {
display: grid; grid-template-columns: 26px minmax(0, 1fr) 44px auto; align-items: center; gap: 8px;
min-height: 38px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 8px;
background: var(--surface); color: var(--text); flex-shrink: 0;
}
.cs-progress-chip.is-new { border-color: rgba(34,197,94,.45); background: rgba(34,197,94,.08); }
.cs-progress-chip.is-updated { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); box-shadow: 0 0 0 1px var(--accent); }
@media (max-width: 900px) {
.cs-progress-box-big { width: 96vw; height: 92vh; }
.cs-progress-body { flex-direction: column; }
.cs-progress-main { grid-template-columns: 1fr; }
.cs-progress-side { width: 100%; max-height: 180px; }
}
.cs-progress-dot {
width: 22px; height: 22px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
background: var(--accent); color: #fff; font-size: 10px; font-weight: 800;
}
.cs-progress-meta { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.cs-progress-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; }
.cs-progress-alias { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--subtext); font-size: 10px; }
.cs-progress-fillmeta {
position: absolute;
inset: 0;
border-radius: inherit;
background: color-mix(in srgb, var(--panel) 90%, transparent);
overflow: hidden;
border: 1px solid color-mix(in srgb, var(--border) 85%, transparent);
pointer-events: none;
}
.cs-progress-fillmeta span {
display: block;
height: 100%;
background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 16%, transparent), color-mix(in srgb, var(--accent) 46%, transparent));
border-radius: inherit;
min-width: 2px;
}
.cs-progress-badge { font-size: 9px; text-transform: uppercase; color: var(--subtext); font-weight: 800; }
.cs-fields { margin: 0; display: grid; grid-template-columns: 1fr; gap: 6px; }
.cs-identity-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
gap: 6px;
margin-bottom: 4px;
}
.cs-id-cell {
display: flex;
flex-direction: column;
gap: 3px;
padding: 9px 11px;
font-size: 13.5px;
border: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
border-radius: 10px;
background: color-mix(in srgb, var(--surface) 78%, transparent);
}
.cs-id-cell dt {
font-weight: 800;
color: var(--subtext);
text-transform: uppercase;
font-size: 10.5px;
letter-spacing: .04em;
display: flex;
align-items: center;
gap: 5px;
}
.cs-id-cell dd {
margin: 0;
color: var(--text);
line-height: 1.35;
}
.cs-row { display: grid; grid-template-columns: 150px 1fr; gap: 12px; font-size: 15.5px; padding: 8px 10px; border: 1px solid color-mix(in srgb, var(--border) 55%, transparent); border-radius: 8px; background: color-mix(in srgb, var(--surface) 72%, transparent); }
.cs-row dt { font-weight: 800; color: var(--subtext); text-transform: uppercase; font-size: 10.5px; letter-spacing: .04em; display:flex; align-items:center; gap:5px; }
.cs-row dd { margin: 0; color: var(--text); line-height: 1.5; }
.cs-row ul { margin: 0; padding-left: 16px; }
.cs-source-mark {
width: 17px; height: 17px; border-radius: 50%; border: 1px solid var(--accent);
background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent);
font-size: 9px; font-weight: 900; cursor: pointer; line-height: 1; padding: 0;
}
.cs-row dd .cs-source-mark,
.lcd-field-value .cs-source-mark { margin-left: 6px; vertical-align: middle; }
.cs-source-mark:hover, .cs-source-mark.is-active { background: var(--accent); color: #fff; }
.cs-source-mark-sample { cursor: default; pointer-events: none; }
.cs-source-preview {
margin: 16px 28px 20px; padding: 14px 16px; border-radius: 10px;
background: color-mix(in srgb, var(--accent) 6%, var(--panel)); border: 1px solid color-mix(in srgb, var(--accent) 25%, var(--border));
}
.cs-source-preview-empty { font-size: 12.5px; color: var(--subtext); }
.cs-source-preview-head { display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--accent); margin-bottom: 6px; }
.cs-source-preview-head em { font-style: normal; opacity: .75; text-transform: none; letter-spacing: 0; }
.cs-source-preview-quote { font-size: 14px; line-height: 1.6; color: var(--text); font-style: italic; }
.cs-sources { margin-top: 10px; padding-top: 9px; border-top: 1px dashed var(--border); font-size: 11px; color: var(--subtext); }
.cs-sources-title { display:flex; align-items:center; gap:5px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; margin-bottom:6px; }
.cs-sources b { color: var(--text); }
.cs-sources .mdi { color: var(--accent); }
.cs-source-list { display:flex; flex-wrap:wrap; gap:5px; }
.cs-source-link {
display:inline-flex; align-items:center; gap:5px; max-width:100%;
border:1px solid var(--border); border-radius:999px; background:var(--surface); color:var(--subtext);
padding:3px 8px; font-size:10.5px; cursor:pointer;
}
.cs-source-link:hover { border-color:var(--accent); color:var(--accent); }
.cs-source-link span { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:150px; }
.cs-source-link .cs-source-quote { max-width: 260px; color: var(--text); }
.cs-source-link .cs-source-hint { color: var(--subtext); }
.cs-source-link em { font-style:normal; opacity:.8; }
.cs-row-voice dt .mdi { color: var(--accent); }
.cs-row-voice dd { font-style: italic; }
.cs-prompts { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.cs-prompts .lcd-prompt-box summary { border-radius: 8px; }
.cs-prompts .lcd-prompt-empty { opacity: .6; font-size: 11px; }
.cs-overview {
padding: 0;
overflow: hidden;
display: flex;
flex-direction: column;
min-height: 560px;
border-radius: 24px;
border: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
background:
radial-gradient(circle at 100% 0%, rgba(255,255,255,.18), transparent 32%),
linear-gradient(180deg, color-mix(in srgb, var(--panel) 74%, var(--surface)) 0%, color-mix(in srgb, var(--surface) 88%, var(--panel)) 100%);
box-shadow: 0 20px 50px rgba(0,0,0,.14);
}
.cs-overview .cs-header {
border-radius: 0;
padding: 24px 24px 20px;
}
.cs-overview .cs-avatar {
width: 96px;
height: 96px;
font-size: 40px;
border-width: 4px;
box-shadow: 0 14px 28px rgba(0,0,0,.24);
}
.cs-overview .lcd-name { font-size: 30px; }
.cs-overview .lcd-aliases { font-size: 15px; opacity: .76; }
.cs-overview .lcd-archetype { font-size: 18px; margin-bottom: 14px; }
.cs-overview .lcd-tier { font-size: 11px; padding: 4px 11px; }
.cs-overview .cs-header-pills { margin-top: 12px; }
.cs-overview .cs-header-pill {
background: rgba(255,255,255,.12);
border-color: rgba(255,255,255,.22);
}
.cs-overview-meta {
display: flex;
flex-direction: column;
gap: 16px;
padding: 18px 20px 20px;
flex: 1;
}
.cs-overview-alignment { margin: 0; }
.cs-overview-facts {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
}
.cs-overview-fact {
min-height: 66px;
padding: 10px 12px;
border-radius: 14px;
border: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
background: color-mix(in srgb, var(--surface) 82%, var(--panel));
display: flex;
flex-direction: column;
justify-content: center;
gap: 2px;
}
.cs-overview-fact span {
font-size: 10px;
font-weight: 800;
text-transform: uppercase;
letter-spacing: .05em;
color: var(--subtext);
}
.cs-overview-fact b {
font-size: 14px;
line-height: 1.35;
color: var(--text);
}
.cs-overview-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.cs-overview .cl-tag-chip {
font-size: 12px;
padding: 4px 10px;
}
/* ── Character library section ─────────────────────────────────────────── */
.cl-toolbar { margin-bottom: 14px; }
.cl-tool-field { display: flex; flex-direction: column; gap: 4px; }
.cl-tool-label { font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--subtext); }
.cl-tool-field select, .cl-tool-field input { padding: 7px 10px; border: 1px solid var(--border); border-radius: 7px; background: var(--surface); color: var(--text); font-size: 13px; }
.cl-grid { display: flex; flex-direction: column; gap: 20px; }
.cl-book-group { }
.cl-book-head { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 14px; padding: 4px 0 10px; border-bottom: 2px solid var(--border); margin-bottom: 12px; }
.cl-book-head .mdi { color: var(--accent); }
.cl-book-count { margin-left: 6px; font-size: 11px; font-weight: 700; color: var(--subtext); border: 1px solid var(--border); border-radius: 20px; padding: 1px 8px; }
.cl-book-cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(430px, 1fr));
gap: 18px;
align-items: start;
}
.cl-card-wrap { position: relative; min-width: 0; }
.cl-card-tools { position: absolute; top: 8px; right: 8px; display: flex; gap: 4px; z-index: 2; opacity: 0; transition: opacity .15s; }
.cl-card-wrap:hover .cl-card-tools { opacity: 1; }
.cl-card-tools .btn-sm { font-size: 11px; padding: 2px 7px; }
.cl-empty { text-align: center; padding: 60px 20px; color: var(--subtext); }
.cl-empty p { margin: 8px 0 0; }
.cl-empty-hint { font-size: 12.5px; }
.cl-edit-box { max-width: 620px; width: 92vw; }
.cl-edit-body { display: flex; flex-direction: column; gap: 10px; max-height: 70vh; overflow-y: auto; padding: 4px 2px; }
.cl-edit-row { display: flex; flex-direction: column; gap: 3px; }
.cl-edit-row > span { font-size: 11px; font-weight: 700; color: var(--subtext); }
.cl-edit-row input, .cl-edit-row textarea, .cl-edit-row select { padding: 7px 9px; border: 1px solid var(--border); border-radius: 7px; background: var(--surface); color: var(--text); font-size: 13px; font-family: inherit; resize: vertical; }
/* ── Recast unknown: gap between non-contiguous passages ───────────────── */
.ab-cv-divider { text-align: center; color: var(--subtext); font-size: 20px; letter-spacing: .35em; line-height: 1; padding: 10px 0 6px; opacity: .55; user-select: none; }
.ab-cv-divider-expand { cursor: pointer; font-size: 14px; letter-spacing: normal; transition: opacity .15s; }
.ab-cv-divider-expand:hover { opacity: .9; color: var(--accent); }
.ab-cv-divider-hint { font-size: 11px; font-weight: 500; text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 2px; vertical-align: middle; }
.ab-cv-ctx-row { opacity: .7; background: color-mix(in srgb, var(--panel) 60%, transparent); border-left: 2px solid var(--border); }
.reader-synth-prog { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }
.reader-synth-track { width: 130px; height: 38px; border-radius: 4px; background: var(--panel); overflow: hidden; }
.reader-synth-fill { height: 100%; width: 0; background: rgba(234,179,8,.9); transition: width .15s; }
.reader-synth-label { font-size: 12px; color: var(--subtext); min-width: 52px; }
/* Select mode: clickable sentences (pointer, not crosshair — it's click-to-pick) */
.reader-doc.reader-selecting { box-shadow: inset 0 0 0 2px var(--accent); }
.reader-doc.reader-selecting .reader-stat { pointer-events: auto; cursor: pointer; }
.reader-doc.reader-selecting .reader-stat:hover { background: rgba(37,99,235,.16); outline: 1px dashed rgba(37,99,235,.5); }
.reader-doc.reader-selecting .reader-word { cursor: pointer; }
.reader-doc.reader-selecting .reader-word:hover { background: rgba(37,99,235,.18); }
/* committed range */
.reader-stat.sel { outline: 2px solid var(--accent); outline-offset: 0; background: rgba(37,99,235,.10); }
.reader-word.in-sel { box-shadow: inset 0 -2px 0 var(--accent); }
/* the start "anchor" pulses while waiting for the end click */
.reader-stat.sel-anchor { outline: 2px solid var(--accent); background: rgba(37,99,235,.20); animation: readerAnchorPulse 1s ease-in-out infinite; }
.reader-word.sel-anchor { box-shadow: inset 0 -2px 0 var(--accent); background: rgba(37,99,235,.22); animation: readerAnchorPulse 1s ease-in-out infinite; }
@keyframes readerAnchorPulse { 0%,100% { opacity: 1; } 50% { opacity: .45; } }
/* Zoom toolbar + status legend */
.reader-toolbar {
display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px;
margin-top: 10px; padding: 8px 12px; background: var(--surface);
border: 1px solid var(--border); border-radius: var(--radius);
}
.reader-zoom { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.reader-zoom-sep { width: 1px; height: 20px; background: var(--border); margin: 0 4px; }
.reader-zoom-pct { font-size: 12px; font-weight: 700; min-width: 44px; text-align: center; color: var(--subtext); }
/* PDF Search */
.reader-search-wrap { display: flex; align-items: center; gap: 5px; }
.reader-search-icon { font-size: 14px; color: var(--subtext); }
.reader-search-inp {
width: 160px; padding: 4px 10px; border: 1px solid var(--border); border-radius: 20px;
background: var(--panel); color: var(--text); font-size: 13px; outline: none;
transition: border-color .15s, width .2s;
}
.reader-search-inp:focus { border-color: var(--accent); width: 220px; }
.reader-search-status { font-size: 11px; color: var(--subtext); white-space: nowrap; min-width: 32px; }
.reader-search-btn {
width: 24px;
height: 24px;
display: inline-flex;
align-items: center;
justify-content: center;
border: 0;
border-radius: 5px;
background: transparent;
color: var(--subtext);
cursor: pointer;
padding: 0;
}
.reader-search-btn:hover { background: var(--panel); color: var(--accent); }
.reader-search-btn .mdi { font-size: 17px; }
.reader-legend { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font-size: 11px; color: var(--subtext); }
.reader-leg { display: inline-flex; align-items: center; gap: 5px; }
.reader-leg::before { content: ''; width: 11px; height: 11px; border-radius: 3px; }
.reader-leg-pending::before { background: rgba(239,68,68,.45); }
.reader-leg-synth::before { background: rgba(234,179,8,.65); }
.reader-leg-ready::before { background: rgba(34,197,94,.55); }
.reader-leg-reading::before { background: rgba(37,99,235,.6); }
.reader-doc {
margin-top: 14px; max-height: 72vh; overflow-y: auto; overflow-x: auto;
background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
padding: 16px; display: flex; flex-direction: column; gap: 16px;
}
.reader-doc:empty { display: none; }
.reader-parsing { display: flex; align-items: center; gap: 10px; padding: 24px; color: var(--subtext); font-size: 13px; margin: 0 auto; }
.reader-doc.two-page { flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.reader-page {
position: relative; flex: 0 0 auto; margin: 0 auto;
box-shadow: 0 2px 10px rgba(0,0,0,.12); background: #fff;
contain: layout paint style;
content-visibility: auto;
contain-intrinsic-size: auto 1100px;
}
.reader-canvas { display: block; }
.reader-overlay { position: absolute; inset: 0; pointer-events: none; }
.reader-hl-word {
position: absolute; border-radius: 3px; background: rgba(37,99,235,.30); z-index: 3;
box-shadow: 0 0 0 1.5px rgba(37,99,235,.75); transition: left .12s, top .12s, width .12s, height .12s;
}
.reader-search-hit {
position: absolute;
z-index: 2;
border-radius: 2px;
background: rgba(250, 204, 21, .35);
box-shadow: 0 0 0 1px rgba(202, 138, 4, .25);
pointer-events: none;
}
.reader-search-hit.search-current {
z-index: 4;
background: rgba(250, 204, 21, .72);
box-shadow: 0 0 0 2px rgba(202, 138, 4, .85);
}
.reader-word.search-hit { background: rgba(250, 204, 21, .35); border-radius: 3px; }
.reader-word.search-current {
background: rgba(250, 204, 21, .75);
box-shadow: 0 0 0 2px rgba(202, 138, 4, .8);
}
/* Per-sentence synthesis-state overlay (PDF) — the "not synthesised" tint stays
invisible until synthesis actually starts (button, play, or a restored doc
with saved audio); otherwise a freshly-imported book reads as wall-to-wall red. */
.reader-stat { position: absolute; border-radius: 3px; z-index: 1; transition: background .2s; }
.reader-stat-pending { background: transparent; }
.reader-doc.reader-synth-started .reader-stat-pending { background: rgba(239,68,68,.12); }
.reader-stat-synth { background: rgba(234,179,8,.30); }
.reader-stat-ready { background: rgba(34,197,94,.18); }
.reader-stat-reading { background: rgba(37,99,235,.20); z-index: 2; }
.reader-text {
max-width: 760px; background: var(--surface); color: var(--text);
border: 1px solid var(--border); border-radius: var(--radius);
padding: 28px 34px; line-height: 1.85; font-size: 17px;
}
.reader-text-para { margin: 0 0 1em; }
.reader-word { border-radius: 3px; padding: 0 1px; cursor: pointer; transition: background .12s; }
/* Per-sentence synthesis-state tint (text) */
.reader-word.stat-pending { background: transparent; }
.reader-doc.reader-synth-started .reader-word.stat-pending { background: rgba(239,68,68,.09); }
.reader-word.stat-synth { background: rgba(234,179,8,.22); }
.reader-word.stat-ready { background: rgba(34,197,94,.14); }
.reader-word.stat-reading { background: rgba(37,99,235,.15); }
.reader-word.is-word { background: rgba(37,99,235,.42) !important; box-shadow: 0 0 0 1px rgba(37,99,235,.6); }
/* ── Fish Audio inline emotion-tag reference (Try It Out) ─────────────────── */
/* Uses the app's real theme tokens (--surface/--panel/--border/--text), not
hardcoded colours, so the panel follows both the light and dark themes. */
.fish-tags-panel {
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 10px 12px;
background: var(--panel);
}
.fish-tags-head { display: flex; align-items: center; gap: 8px; font-weight: 600; color: var(--text); }
.fish-tags-group { margin-top: 10px; }
.fish-tags-group-title { font-size: 12px; font-weight: 600; color: var(--subtext); margin-bottom: 6px; }
.fish-tags-grid { display: flex; flex-wrap: wrap; gap: 6px; }
.fish-tag {
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 12px;
padding: 3px 8px;
border-radius: 5px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
cursor: pointer;
transition: background .12s, border-color .12s, color .12s;
}
.fish-tag:hover { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.fish-tag:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Quotation-mark visibility toggle in the casting view */
.ab-cv-quote-toggle.is-on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }