Files
DemonGatanjieu-Anomalous_Mo…/web/styles/12-tts-setup.css
T
DemonGatanjieuandClaude Opus 5.5 db045b8f57 Voice pages: tabs instead of folds
GPT-SoVITS Settings gets a status chip by the title and tabs (tones, other
languages, base files with a dot when they need the user, where things are,
version); the tones have a Simple / Numbers switch. Voice-over's side panel
gets How it reads / Numbers / Settings tabs for a character or picked lines.
The More fold is gone; ui_tab_strip.js replaces ui_tts_fold.js.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 02:39:53 +08:00

1730 lines
39 KiB
CSS

/* GPT-SoVITS settings dialog, import workbench and studio file drop.
Modal shell, fields, chips and buttons come from 11-audio-studio.css. */
/* ---------- Settings dialog (opened from the audio sidebar) ---------- */
.anomalous-voice-modal.anomalous-tts-setup-modal {
width: 760px;
}
.anomalous-tts-setup {
display: flex;
flex-direction: column;
gap: 16px;
margin-top: 12px;
color: var(--amb-text-soft);
font-size: 12px;
}
.anomalous-tts-reminder {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 12px;
padding: 8px 10px;
border-radius: 8px;
background: rgba(245, 158, 11, 0.07);
}
.anomalous-tts-reminder-text {
flex: 1 1 260px;
min-width: 0;
color: var(--amb-text-main);
line-height: 1.5;
}
/* Empty GPT-SoVITS studio: the whole area takes dropped files. */
.anomalous-audio-empty.is-drop {
margin-top: 4px;
border: 1.5px dashed rgba(148, 163, 184, 0.25);
border-radius: 14px;
}
.anomalous-audio-empty-action {
margin-top: 18px;
padding: 7px 18px;
font-size: 13px;
}
.anomalous-tts-setup-group {
display: flex;
flex-direction: column;
gap: 6px;
}
.anomalous-tts-setup-row {
display: flex;
align-items: center;
gap: 8px;
min-height: 26px;
}
.anomalous-tts-setup-row.is-package {
flex-wrap: wrap;
}
.anomalous-tts-setup-path {
flex: 1;
min-width: 0;
overflow: hidden;
color: var(--amb-text-main);
text-overflow: ellipsis;
white-space: nowrap;
}
.anomalous-tts-setup-meta {
flex-shrink: 0;
color: var(--amb-text-muted);
}
/* Generation presets (ui_tts_presets.js) and a character's generation settings (ui_tts_tuning.js) */
.anomalous-tts-preset-rules {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
align-items: center;
gap: 6px 12px;
}
.anomalous-tts-preset-grid {
display: grid;
grid-template-columns: auto repeat(4, minmax(0, 1fr));
align-items: center;
gap: 6px 8px;
margin: 6px 0;
}
.anomalous-tts-tuning-numbers .anomalous-tts-preset-grid {
grid-template-columns: auto minmax(0, 1fr) auto minmax(0, 1fr);
}
.anomalous-tts-number {
width: 100%;
min-width: 56px;
box-sizing: border-box;
}
.anomalous-tts-presets-body {
display: flex;
flex-direction: column;
gap: 8px;
}
/* Modes as choices and the picked one's numbers as bars (ui_tts_preset_switch.js);
the bars are the Current node card's (20-current-node.css). */
.anomalous-tts-switch {
display: flex;
flex-direction: column;
gap: 8px;
}
.anomalous-tts-switch-choices {
display: flex;
flex-wrap: wrap;
gap: 2px;
padding: 2px;
border: 1px solid var(--amb-border);
border-radius: 8px;
background: rgba(var(--amb-ink-rgb), 0.03);
}
.anomalous-tts-switch-badge {
margin-left: 4px;
color: var(--amb-text-dim);
font-size: 10px;
font-weight: 400;
}
.anomalous-tts-switch-new {
color: var(--amb-link);
}
.anomalous-tts-switch-rows {
display: grid;
grid-template-columns: auto minmax(40px, 1fr) auto;
align-items: center;
gap: 6px 10px;
}
.anomalous-tts-switch-row {
display: contents;
}
.anomalous-tts-switch-label {
display: flex;
flex-direction: column;
color: var(--amb-text-soft);
font-size: 12px;
line-height: 1.3;
}
.anomalous-tts-switch-label code {
color: var(--amb-text-dim);
font-family: ui-monospace, monospace;
font-size: 10px;
}
.anomalous-tts-switch-row.is-same .anomalous-node-param-bars {
opacity: 0.55;
}
.anomalous-tts-switch-nums {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: flex-end;
gap: 0 2px;
font-size: 12px;
}
.anomalous-tts-switch-nums > .is-now {
color: var(--amb-text-soft);
}
/* An editable number reads as the value itself: a dashed underline says it can be changed,
the box appears only on hover or while typing, so "15 → 10" stays one line to read.
No spin arrows (they covered the digits); typing and the arrow keys change it. */
.anomalous-tts-switch-nums .anomalous-tts-number {
width: 52px;
min-width: 0;
padding: 1px 4px;
border: 1px solid transparent;
border-bottom: 1px dashed var(--amb-border-strong);
border-radius: 4px;
background: transparent;
color: var(--amb-text-main);
font: inherit;
font-weight: 600;
text-align: right;
-moz-appearance: textfield;
}
.anomalous-tts-switch-nums .anomalous-tts-number::-webkit-inner-spin-button,
.anomalous-tts-switch-nums .anomalous-tts-number::-webkit-outer-spin-button {
margin: 0;
-webkit-appearance: none;
}
.anomalous-tts-switch-nums .anomalous-tts-number:hover,
.anomalous-tts-switch-nums .anomalous-tts-number:focus {
border-color: var(--amb-border-strong);
background: var(--amb-bg-input);
outline: none;
}
/* Under the number, so a narrow column (the Script Director's side) keeps it whole. */
.anomalous-tts-switch-was {
flex-basis: 100%;
color: var(--amb-warn-text);
font-size: 11px;
text-align: right;
}
/* Steady to lively: a ring for the base, a dot for the mode picked. */
.anomalous-tts-feel-track {
position: relative;
height: 4px;
margin: 10px 8px 6px;
border-radius: 2px;
background: linear-gradient(90deg, color-mix(in srgb, var(--amb-link) 25%, transparent), color-mix(in srgb, var(--amb-warn) 45%, transparent));
}
.anomalous-tts-feel-mark {
position: absolute;
top: 50%;
width: 14px;
height: 14px;
border-radius: 50%;
transform: translate(-50%, -50%);
box-sizing: border-box;
}
.anomalous-tts-feel-mark.is-base {
border: 2px solid var(--amb-text-soft);
background: var(--amb-bg-dialog);
}
.anomalous-tts-feel-mark.is-now {
width: 10px;
height: 10px;
background: var(--amb-link);
}
.anomalous-tts-feel-ends {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 0 8px;
color: var(--amb-text-muted);
font-size: 11px;
}
/* Its own line under the two ends. */
.anomalous-tts-feel-legend {
order: 3;
flex-basis: 100%;
color: var(--amb-text-dim);
text-align: center;
}
.anomalous-tts-feel-say {
color: var(--amb-text-soft);
font-size: 12.5px;
line-height: 1.5;
}
.anomalous-tts-feel-say strong {
color: var(--amb-text-main);
font-weight: 600;
}
/* Listening (ui_tts_mode_preview.js): who reads which line, then the takes heard. */
.anomalous-tts-listen-setup,
.anomalous-tts-takes {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 6px 8px; font-size: 12px;
}
.anomalous-tts-listen-text {
flex: 1;
min-width: 160px;
padding: 4px 6px;
border: 1px solid var(--amb-border-strong);
border-radius: 6px;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.3));
color: var(--amb-text-main);
font-size: 12px;
}
.anomalous-tts-listen-take {
padding: 2px 8px;
border: 1px solid var(--amb-border);
border-radius: 999px;
background: none;
color: var(--amb-text-soft);
font: inherit;
font-size: 12px;
cursor: pointer;
}
.anomalous-tts-listen-take.is-current {
border-color: var(--amb-link);
color: var(--amb-text-main);
}
.anomalous-tts-switch-about {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 4px 12px;
}
.anomalous-tts-link.is-danger {
color: var(--amb-danger);
}
/* A dialog row's numbers in effect; blue = not what the general presets give. */
.anomalous-tts-tuning-effect {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 4px;
grid-column: 1 / -1;
font-size: 12px;
}
.anomalous-tts-tuning-value {
padding: 1px 6px;
border-radius: 4px;
color: var(--amb-text-muted);
}
.anomalous-tts-tuning-value.is-diff {
background: color-mix(in srgb, var(--amb-link) 16%, transparent);
color: var(--amb-text-main);
}
.anomalous-tts-tuning-numbers summary {
cursor: pointer;
color: var(--amb-link);
}
.anomalous-tts-tuning-rows {
display: flex;
flex-direction: column;
gap: 10px;
}
.anomalous-tts-tuning-row {
display: grid;
grid-template-columns: 90px minmax(0, 1fr) auto;
align-items: center;
gap: 8px 12px;
padding-bottom: 10px;
border-bottom: 1px solid var(--amb-border);
}
.anomalous-tts-tuning-row .anomalous-tts-tuning-numbers {
grid-column: 1 / -1;
}
.anomalous-tts-tuning-label {
color: var(--amb-text-main);
}
.anomalous-tts-tuning-speed {
display: flex;
align-items: center;
gap: 6px;
}
.anomalous-tts-tuning-speed .anomalous-tts-number {
width: 72px;
}
.anomalous-tts-version-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 10px;
margin-left: auto;
}
.anomalous-tts-setup-command {
flex: 1 1 320px;
min-width: 0;
padding: 4px 8px;
border-radius: 6px;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.3));
color: var(--amb-text-main);
font: 11px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
overflow-wrap: anywhere;
}
.anomalous-tts-setup-actions {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.anomalous-tts-setup-notice {
padding: 8px 10px;
border-radius: 8px;
background: rgba(248, 113, 113, 0.08);
color: var(--amb-danger-text);
}
.anomalous-tts-kind {
flex-shrink: 0;
padding: 1px 6px;
border-radius: 4px;
background: color-mix(in srgb, var(--amb-link) 12%, transparent);
color: var(--amb-link);
font-size: 10.5px;
white-space: nowrap;
}
.anomalous-tts-state {
flex-shrink: 0;
font-size: 11px;
white-space: nowrap;
}
.anomalous-tts-state.is-ok { color: var(--amb-ok); }
.anomalous-tts-state.is-busy { color: var(--amb-link); }
.anomalous-tts-state.is-missing { color: #f59e0b; }
.anomalous-tts-state.is-error { color: var(--amb-danger); cursor: help; }
.anomalous-tts-add:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.anomalous-tts-link {
padding: 0;
border: none;
background: none;
color: var(--amb-link);
font: inherit;
font-size: 12px;
text-decoration: underline;
text-underline-offset: 2px;
cursor: pointer;
}
/* ---------- Import window ----------
Empty: one drop area saying what to bring. With files: one card per character,
one unfolded at a time. Tones: ready green, needed amber, error red, busy blue. */
.anomalous-voice-modal.anomalous-tts-import {
position: relative;
width: 880px;
height: min(84vh, 800px);
max-width: 94vw;
overflow: hidden;
gap: 14px;
}
.anomalous-tts-import > .anomalous-voice-modal-header,
.anomalous-tts-import > .anomalous-tts-steps,
.anomalous-tts-import > .anomalous-voice-modal-footer {
flex-shrink: 0;
}
/* Three steps, so a first-time user knows where they are. */
.anomalous-tts-steps {
display: flex;
gap: 8px;
margin: 0;
padding: 0;
list-style: none;
}
.anomalous-tts-step {
display: flex;
flex: 1;
align-items: center;
gap: 8px;
min-width: 0;
color: var(--amb-text-dim);
font-size: 12px;
}
.anomalous-tts-step:not(:last-child)::after {
content: "";
flex: 1;
height: 1px;
margin-left: 4px;
background: rgba(var(--amb-ink-rgb), 0.08);
}
.anomalous-tts-step-no {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
border: 1px solid var(--amb-border-strong);
border-radius: 50%;
font-size: 11px;
font-weight: 700;
}
.anomalous-tts-step-label {
white-space: nowrap;
}
.anomalous-tts-step.is-current {
color: var(--amb-text-main);
font-weight: 600;
}
.anomalous-tts-step.is-current .anomalous-tts-step-no {
border-color: transparent;
background: linear-gradient(135deg, var(--amb-link), var(--amb-link));
color: var(--amb-text-main);
box-shadow: 0 0 0 4px color-mix(in srgb, var(--amb-link) 18%, transparent);
}
.anomalous-tts-step.is-done {
color: var(--amb-text-muted);
}
.anomalous-tts-step.is-done .anomalous-tts-step-no {
border-color: rgba(52, 211, 153, 0.5);
color: var(--amb-ok);
}
.anomalous-tts-step.is-done::after {
background: rgba(52, 211, 153, 0.35);
}
.anomalous-tts-content {
display: flex;
flex: 1 1 auto;
flex-direction: column;
gap: 10px;
min-height: 0;
margin: 0 -6px;
padding: 0 6px 2px;
overflow-y: auto;
}
/* ---- the first question: what do you have? ---- */
.anomalous-tts-header-buttons {
display: flex;
align-items: center;
gap: 6px;
}
.anomalous-tts-help {
width: 26px;
height: 26px;
padding: 0;
border: 1px solid var(--amb-border-strong);
border-radius: 50%;
background: transparent;
color: var(--amb-text-muted);
font: inherit;
font-size: 13px;
font-weight: 700;
cursor: pointer;
}
.anomalous-tts-help:hover {
border-color: var(--amb-link);
color: var(--amb-text-main);
}
.anomalous-tts-choose {
display: flex;
flex-direction: column;
gap: 10px;
width: min(560px, 100%);
margin: auto;
padding: 12px 0;
}
.anomalous-tts-choose-title {
margin-bottom: 6px;
color: var(--amb-text-main);
font-size: 19px;
font-weight: 700;
text-align: center;
}
.anomalous-tts-mode {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 18px;
border: 1px solid var(--amb-border);
border-radius: 14px;
background: rgba(var(--amb-ink-rgb), 0.03);
color: var(--amb-text-main);
font: inherit;
text-align: left;
cursor: pointer;
transition: border-color 0.15s ease, background 0.15s ease, transform 0.15s ease;
}
.anomalous-tts-mode:hover:not(:disabled) {
border-color: color-mix(in srgb, var(--amb-link) 55%, transparent);
background: color-mix(in srgb, var(--amb-link) 10%, transparent);
transform: translateY(-1px);
}
.anomalous-tts-mode:disabled {
opacity: 0.45;
cursor: not-allowed;
}
.anomalous-tts-mode-icon {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
border-radius: 12px;
background: color-mix(in srgb, var(--amb-link) 16%, transparent);
color: var(--amb-link);
}
.anomalous-tts-mode-words {
display: flex;
flex: 1;
flex-direction: column;
gap: 3px;
min-width: 0;
}
.anomalous-tts-mode-title {
font-size: 14.5px;
font-weight: 700;
}
.anomalous-tts-mode-desc {
color: var(--amb-text-muted);
font-size: 12px;
line-height: 1.5;
}
.anomalous-tts-mode-go {
color: var(--amb-text-dim);
font-size: 22px;
}
.anomalous-tts-pick-character {
display: flex;
flex-direction: column;
gap: 8px;
padding: 12px 14px;
border: 1px dashed color-mix(in srgb, var(--amb-link) 35%, transparent);
border-radius: 12px;
}
.anomalous-tts-pick-character[hidden] {
display: none;
}
.anomalous-tts-pick-character-title {
color: var(--amb-text-soft);
font-size: 12px;
font-weight: 600;
}
.anomalous-tts-pick-character-list {
display: flex;
flex-wrap: wrap;
gap: 6px;
max-height: 160px;
overflow-y: auto;
}
.anomalous-tts-pick-character-item {
padding: 5px 12px;
border: 1px solid var(--amb-border-strong);
border-radius: 999px;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.2));
color: var(--amb-text-main);
font: inherit;
font-size: 12px;
cursor: pointer;
}
.anomalous-tts-pick-character-item:hover {
border-color: var(--amb-link);
background: color-mix(in srgb, var(--amb-link) 16%, transparent);
}
.anomalous-tts-toolbar-hint {
color: var(--amb-text-dim);
font-size: 11.5px;
}
.anomalous-tts-toolbar [hidden] {
display: none;
}
/* ---- empty: the drop area ---- */
.anomalous-tts-hero {
display: flex;
flex: 1;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 14px;
padding: 32px 24px;
border: 2px dashed color-mix(in srgb, var(--amb-link) 35%, transparent);
border-radius: 18px;
background:
radial-gradient(circle at 50% 30%, color-mix(in srgb, var(--amb-link) 12%, transparent), transparent 60%),
rgba(var(--amb-ink-rgb), 0.015);
text-align: center;
transition: border-color 0.15s ease, background 0.15s ease;
}
.anomalous-tts-hero-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 72px;
height: 72px;
border-radius: 50%;
background: color-mix(in srgb, var(--amb-link) 16%, transparent);
color: var(--amb-link);
}
.anomalous-tts-hero-title {
color: var(--amb-text-main);
font-size: 19px;
font-weight: 700;
}
.anomalous-tts-hero-needs {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 8px;
}
.anomalous-tts-hero-need {
display: inline-flex;
align-items: baseline;
gap: 6px;
padding: 5px 12px;
border: 1px solid var(--amb-border);
border-radius: 999px;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.25));
color: var(--amb-text-dim);
font-size: 11.5px;
}
.anomalous-tts-hero-need b {
color: var(--amb-text-main);
font-weight: 600;
}
.anomalous-tts-hero-desc {
max-width: 540px;
color: var(--amb-text-muted);
font-size: 12.5px;
line-height: 1.7;
}
.anomalous-tts-hero-buttons {
display: flex;
gap: 10px;
margin-top: 4px;
}
.anomalous-tts-hero-buttons .anomalous-voice-modal-submit {
padding: 10px 26px;
font-size: 13.5px;
}
/* Suggested folder layout under the batch drop area. */
.anomalous-tts-layout {
width: 100%;
max-width: 540px;
color: var(--amb-text-muted);
font-size: 12px;
text-align: left;
}
.anomalous-tts-layout summary {
width: fit-content;
margin: 0 auto;
color: var(--amb-link);
cursor: pointer;
}
.anomalous-tts-layout-tree {
display: grid;
grid-template-columns: max-content 1fr;
gap: 4px 18px;
margin-top: 10px;
padding: 10px 14px;
border: 1px solid var(--amb-border);
border-radius: 10px;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.25));
}
.anomalous-tts-layout-name {
color: var(--amb-text-main);
font-family: ui-monospace, Consolas, monospace;
white-space: nowrap;
}
.anomalous-tts-layout-note {
color: var(--amb-text-dim);
}
.anomalous-tts-layout-foot {
margin: 8px 2px 0;
line-height: 1.6;
}
/* Dragging files over the window. */
.anomalous-tts-drop-cover {
position: absolute;
inset: 10px;
z-index: 5;
display: none;
align-items: center;
justify-content: center;
border: 2px dashed var(--amb-link);
border-radius: 14px;
background: var(--amb-lt-surface, rgba(20, 23, 34, 0.88));
color: var(--amb-text-main);
font-size: 18px;
font-weight: 700;
pointer-events: none;
}
.anomalous-tts-import.is-dragover .anomalous-tts-drop-cover {
display: flex;
}
/* ---- with files: toolbar and "add more" menu ---- */
.anomalous-tts-toolbar {
display: flex;
align-items: center;
gap: 8px;
}
.anomalous-tts-toolbar-title {
margin-right: auto;
color: var(--amb-text-main);
font-size: 13px;
font-weight: 700;
}
.anomalous-tts-ghost {
padding: 6px 12px;
border: 1px solid var(--amb-border-strong);
border-radius: 8px;
background: rgba(var(--amb-ink-rgb), 0.04);
color: var(--amb-text-soft);
font: inherit;
font-size: 12px;
cursor: pointer;
transition: background 0.15s ease, border-color 0.15s ease;
}
.anomalous-tts-ghost:hover {
border-color: color-mix(in srgb, var(--amb-link) 45%, transparent);
background: color-mix(in srgb, var(--amb-link) 12%, transparent);
color: var(--amb-text-main);
}
.anomalous-tts-ghost.is-large {
padding: 10px 22px;
font-size: 13.5px;
}
.anomalous-tts-menu-wrap {
position: relative;
}
.anomalous-tts-menu {
position: absolute;
top: calc(100% + 6px);
right: 0;
z-index: 4;
display: none;
flex-direction: column;
min-width: 240px;
padding: 6px;
border: 1px solid var(--amb-border-strong);
border-radius: 12px;
background: var(--amb-bg-card);
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.55);
}
.anomalous-tts-menu.is-open {
display: flex;
}
.anomalous-tts-menu-item {
display: flex;
flex-direction: column;
gap: 2px;
padding: 8px 10px;
border: none;
border-radius: 8px;
background: none;
color: var(--amb-text-main);
font: inherit;
font-size: 12.5px;
text-align: left;
cursor: pointer;
}
.anomalous-tts-menu-item:hover {
background: color-mix(in srgb, var(--amb-link) 16%, transparent);
}
.anomalous-tts-menu-hint {
color: var(--amb-text-dim);
font-size: 11px;
}
.anomalous-tts-note {
color: var(--amb-text-muted);
font-size: 11.5px;
}
.anomalous-tts-note:empty {
display: none;
}
/* ---- character cards ---- */
.anomalous-tts-cards {
display: flex;
flex-direction: column;
gap: 8px;
}
.anomalous-tts-card {
flex-shrink: 0;
border: 1px solid var(--amb-border);
border-radius: 12px;
background: rgba(var(--amb-ink-rgb), 0.025);
transition: border-color 0.15s ease, background 0.15s ease;
}
.anomalous-tts-card.is-open {
border-color: color-mix(in srgb, var(--amb-link) 35%, transparent);
background: color-mix(in srgb, var(--amb-link) 4%, transparent);
}
.anomalous-tts-card.is-drop-target {
border-color: var(--amb-link);
box-shadow: 0 0 0 2px color-mix(in srgb, var(--amb-link) 35%, transparent);
}
.anomalous-tts-card[data-tone="done"] {
opacity: 0.55;
}
.anomalous-tts-card-head {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
padding: 9px 12px;
cursor: pointer;
}
.anomalous-tts-card.is-tray .anomalous-tts-card-head {
cursor: default;
}
.anomalous-tts-card-chevron {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
padding: 0;
border: none;
background: none;
color: var(--amb-text-dim);
cursor: pointer;
}
.anomalous-tts-card-chevron::before {
content: "";
width: 7px;
height: 7px;
border-right: 2px solid currentColor;
border-bottom: 2px solid currentColor;
transform: rotate(-45deg);
transition: transform 0.15s ease;
}
.anomalous-tts-card.is-open .anomalous-tts-card-chevron::before {
transform: rotate(45deg);
}
.anomalous-tts-card-avatar {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, var(--amb-link), var(--amb-link));
color: var(--amb-text-main);
font-size: 14px;
font-weight: 700;
}
.anomalous-tts-card.is-tray .anomalous-tts-card-avatar {
background: rgba(251, 191, 36, 0.2);
color: var(--amb-warn);
}
.anomalous-tts-card-title {
display: inline-flex;
flex: 1 1 auto;
align-items: baseline;
gap: 8px;
min-width: 0;
overflow: hidden;
color: var(--amb-text-main);
font-size: 14px;
font-weight: 700;
text-overflow: ellipsis;
white-space: nowrap;
}
.anomalous-tts-card-addto {
color: var(--amb-text-dim);
font-size: 12px;
font-weight: 500;
}
.anomalous-tts-card-name-input {
flex: 1 1 auto;
min-width: 60px;
padding: 4px 8px;
margin-left: -8px;
border: 1px solid transparent;
border-radius: 7px;
background: transparent;
color: var(--amb-text-main);
font: inherit;
font-size: 14px;
font-weight: 700;
}
.anomalous-tts-card-name-input:hover {
border-color: var(--amb-border);
}
.anomalous-tts-card-name-input:focus {
border-color: color-mix(in srgb, var(--amb-link) 60%, transparent);
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.25));
outline: none;
}
.anomalous-tts-card-name-input::placeholder {
color: var(--amb-warn);
font-weight: 500;
}
.anomalous-tts-card-pill {
flex-shrink: 0;
padding: 2px 9px;
border-radius: 999px;
background: rgba(148, 163, 184, 0.12);
color: var(--amb-text-muted);
font-size: 11px;
font-weight: 600;
white-space: nowrap;
}
.anomalous-tts-card[data-tone="ready"] .anomalous-tts-card-pill { background: rgba(52, 211, 153, 0.14); color: var(--amb-ok); }
.anomalous-tts-card[data-tone="needed"] .anomalous-tts-card-pill { background: rgba(251, 191, 36, 0.14); color: var(--amb-warn); }
.anomalous-tts-card[data-tone="error"] .anomalous-tts-card-pill { background: rgba(248, 113, 113, 0.14); color: var(--amb-danger); }
.anomalous-tts-card[data-tone="busy"] .anomalous-tts-card-pill { background: color-mix(in srgb, var(--amb-link) 24%, transparent); color: var(--amb-link); }
.anomalous-tts-card-meta {
flex-shrink: 0;
color: var(--amb-text-dim);
font-size: 11px;
white-space: nowrap;
}
.anomalous-tts-card-remove,
.anomalous-tts-file-remove {
flex-shrink: 0;
width: 24px;
height: 24px;
padding: 0;
border: none;
border-radius: 6px;
background: none;
color: var(--amb-text-dim);
font-size: 15px;
line-height: 1;
cursor: pointer;
}
.anomalous-tts-card-remove:hover,
.anomalous-tts-file-remove:hover {
background: rgba(248, 113, 113, 0.12);
color: var(--amb-danger);
}
.anomalous-tts-card-body {
display: flex;
flex-direction: column;
gap: 12px;
padding: 2px 14px 14px;
}
.anomalous-tts-card.is-tray {
border-style: dashed;
border-color: rgba(251, 191, 36, 0.4);
background: rgba(251, 191, 36, 0.035);
}
.anomalous-tts-pick {
padding: 6px 14px;
border: 1px solid color-mix(in srgb, var(--amb-link) 40%, transparent);
border-radius: 8px;
background: color-mix(in srgb, var(--amb-link) 24%, transparent);
color: var(--amb-text-main);
font: inherit;
font-size: 12px;
font-weight: 600;
cursor: pointer;
}
.anomalous-tts-pick:hover {
background: color-mix(in srgb, var(--amb-link) 26%, transparent);
}
.anomalous-tts-card-section {
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: 4px 10px;
}
.anomalous-tts-card-section-title {
color: var(--amb-text-soft);
font-size: 12px;
font-weight: 700;
}
.anomalous-tts-card-section-hint {
color: var(--amb-text-dim);
font-size: 11px;
}
.anomalous-tts-card-files {
display: flex;
flex-direction: column;
gap: 6px;
}
.anomalous-tts-card-more {
align-self: flex-start;
}
/* ---- folded rows: files left out, and the unassigned files of one folder ---- */
.anomalous-tts-card-fold {
border: 1px dashed var(--amb-border);
border-radius: 10px;
}
.anomalous-tts-card-fold-summary {
display: flex;
align-items: center;
gap: 10px;
padding: 7px 10px;
color: var(--amb-text-muted);
font-size: 12px;
cursor: pointer;
}
.anomalous-tts-card-fold-label {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.anomalous-tts-card-fold[open] > .anomalous-tts-card-files {
padding: 0 8px 8px;
}
/* ---- the checklist: done items ticked and quiet, the next one lit with its button ---- */
.anomalous-tts-check {
display: flex;
flex-direction: column;
gap: 4px;
padding: 6px;
border-radius: 10px;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.16));
}
.anomalous-tts-check-item {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
min-height: 36px;
padding: 5px 8px;
border: 1px solid transparent;
border-radius: 8px;
color: var(--amb-text-dim);
font-size: 12.5px;
}
.anomalous-tts-check-mark {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
border: 1px solid var(--amb-border-strong);
border-radius: 50%;
font-size: 11px;
font-weight: 700;
}
.anomalous-tts-check-text {
flex: 0 1 auto;
min-width: 0;
}
.anomalous-tts-check-actions {
display: inline-flex;
flex-shrink: 0;
align-items: center;
gap: 10px;
margin-left: auto;
}
.anomalous-tts-check-item > .anomalous-tts-file {
flex: 1 1 auto;
justify-content: flex-end;
margin-left: auto;
}
.anomalous-tts-check-item > .anomalous-tts-file .anomalous-tts-file-label {
flex: 0 1 auto;
}
.anomalous-tts-check-item.is-done {
color: var(--amb-text-muted);
}
.anomalous-tts-check-item.is-done .anomalous-tts-check-mark {
border-color: rgba(52, 211, 153, 0.5);
background: rgba(52, 211, 153, 0.12);
color: var(--amb-ok);
}
.anomalous-tts-check-item.is-next {
border-color: color-mix(in srgb, var(--amb-link) 50%, transparent);
background: color-mix(in srgb, var(--amb-link) 12%, transparent);
color: var(--amb-text-main);
font-weight: 600;
}
.anomalous-tts-check-item.is-next .anomalous-tts-check-mark {
border-color: transparent;
background: linear-gradient(135deg, var(--amb-link), var(--amb-link));
color: var(--amb-text-main);
box-shadow: 0 0 0 4px color-mix(in srgb, var(--amb-link) 18%, transparent);
}
.anomalous-tts-card[data-tone="error"] .anomalous-tts-check-item.is-next {
border-color: rgba(248, 113, 113, 0.45);
background: rgba(248, 113, 113, 0.08);
}
.anomalous-tts-card-clips {
display: flex;
flex-direction: column;
gap: 8px;
}
/* ---- one file ---- */
.anomalous-tts-file {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.anomalous-tts-file.is-audio {
flex-direction: column;
align-items: stretch;
gap: 6px;
padding: 8px 10px;
border: 1px solid var(--amb-border);
border-left: 3px solid rgba(52, 211, 153, 0.7);
border-radius: 9px;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.18));
}
.anomalous-tts-card-files > .anomalous-tts-file:not(.is-audio) {
padding: 6px 10px;
border: 1px solid var(--amb-border);
border-radius: 9px;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.18));
}
.anomalous-tts-file[data-tone="busy"] { border-left-color: var(--amb-link); }
.anomalous-tts-file[data-tone="skip"] { border-left-color: #64748b; opacity: 0.7; }
.anomalous-tts-file[data-tone="idle"] { border-left-color: #475569; }
.anomalous-tts-file[data-tone="error"] {
border-color: rgba(248, 113, 113, 0.4);
border-left-color: var(--amb-danger);
background: rgba(248, 113, 113, 0.05);
}
.anomalous-tts-file-top,
.anomalous-tts-file-bottom {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.anomalous-tts-file-bottom {
padding-left: 34px;
}
.anomalous-tts-file [hidden] {
display: none;
}
.anomalous-tts-file-play {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
padding: 0 0 0 2px;
border: 1px solid var(--amb-border-strong);
border-radius: 50%;
background: rgba(var(--amb-ink-rgb), 0.04);
color: var(--amb-text-soft);
font-size: 9px;
cursor: pointer;
}
.anomalous-tts-file-play:hover {
border-color: var(--amb-link);
color: var(--amb-text-main);
}
/* The clip being listened to: its button is "stop". */
.anomalous-tts-file.is-playing {
border-color: color-mix(in srgb, var(--amb-link) 45%, transparent);
background: color-mix(in srgb, var(--amb-link) 8%, transparent);
}
.anomalous-tts-file.is-playing .anomalous-tts-file-play {
padding: 0;
border-color: var(--amb-link);
background: var(--amb-btn-primary-bg);
color: var(--amb-btn-primary-text);
}
.anomalous-tts-file-play.is-failed {
border-color: rgba(248, 113, 113, 0.6);
color: var(--amb-danger);
}
.anomalous-tts-file-label {
display: flex;
flex: 1 1 auto;
align-items: baseline;
gap: 8px;
min-width: 0;
}
.anomalous-tts-file-name {
overflow: hidden;
color: var(--amb-text-main);
font-size: 12.5px;
font-weight: 600;
text-overflow: ellipsis;
white-space: nowrap;
}
.anomalous-tts-file-meta {
flex-shrink: 0;
color: var(--amb-text-dim);
font-size: 11px;
}
.anomalous-tts-file.is-out-of-range {
opacity: 0.6;
}
.anomalous-tts-file.is-out-of-range .anomalous-tts-file-meta {
color: var(--amb-warn);
}
.anomalous-tts-file-state {
flex-shrink: 1;
max-width: 180px;
overflow: hidden;
color: var(--amb-text-muted);
font-size: 11px;
font-weight: 600;
text-overflow: ellipsis;
white-space: nowrap;
}
.anomalous-tts-file-state:empty {
display: none;
}
.anomalous-tts-file[data-tone="busy"] .anomalous-tts-file-state { color: var(--amb-link); }
.anomalous-tts-file[data-tone="merge"] .anomalous-tts-file-state { color: var(--amb-ok); }
.anomalous-tts-file[data-tone="error"] .anomalous-tts-file-state { color: var(--amb-danger); }
.anomalous-tts-file-main {
flex-shrink: 0;
padding: 3px 10px;
border: 1px solid var(--amb-border-strong);
border-radius: 999px;
background: transparent;
color: var(--amb-text-dim);
font: inherit;
font-size: 11px;
cursor: pointer;
}
.anomalous-tts-file-main::before {
content: "☆ ";
}
.anomalous-tts-file-main:hover:not(:disabled) {
border-color: rgba(251, 191, 36, 0.5);
color: var(--amb-warn-soft);
}
.anomalous-tts-file-main.active {
border-color: rgba(251, 191, 36, 0.6);
background: rgba(251, 191, 36, 0.14);
color: var(--amb-warn);
font-weight: 700;
}
.anomalous-tts-file-main.active::before {
content: "★ ";
}
.anomalous-tts-file-main:disabled {
opacity: 0.35;
cursor: not-allowed;
}
.anomalous-tts-file input,
.anomalous-tts-file-move,
.anomalous-tts-card-language {
min-width: 0;
padding: 5px 8px;
border: 1px solid var(--amb-border);
border-radius: 7px;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.25));
color: var(--amb-text-main);
font: inherit;
font-size: 12px;
}
.anomalous-tts-file input:focus,
.anomalous-tts-card-language:focus {
border-color: color-mix(in srgb, var(--amb-link) 60%, transparent);
outline: none;
}
.anomalous-tts-file-emotion {
flex: 0 0 132px;
}
.anomalous-tts-file-emotion:disabled {
opacity: 0.5;
}
.anomalous-tts-file-text {
flex: 1 1 auto;
}
/* Where the line came from: amber = a guess from the file name, red dashes = none found. */
.anomalous-tts-file-text[data-source="filename"] {
border-color: rgba(251, 191, 36, 0.5);
}
.anomalous-tts-file-text[data-source="none"],
.anomalous-tts-file-text[data-source="missing"] {
border-style: dashed;
border-color: rgba(248, 113, 113, 0.45);
}
.anomalous-tts-file-text.dragover {
border-color: var(--amb-link);
background: color-mix(in srgb, var(--amb-link) 12%, transparent);
}
.anomalous-tts-file-move {
flex: 0 1 auto;
max-width: 150px;
padding: 3px 6px;
border-color: transparent;
background: transparent;
color: var(--amb-text-dim);
font-size: 11px;
cursor: pointer;
}
/* Where a file belongs stays quiet until the row is pointed at, except where it is the question. */
.anomalous-tts-file:hover .anomalous-tts-file-move,
.anomalous-tts-file-move:focus,
.anomalous-tts-card.is-tray .anomalous-tts-file-move {
border-color: var(--amb-border-strong);
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.25));
color: var(--amb-text-soft);
}
.anomalous-tts-card.is-tray .anomalous-tts-file-move {
border-color: rgba(251, 191, 36, 0.5);
color: var(--amb-warn-soft);
}
/* Line files and language: the quieter things at the bottom of a card. */
.anomalous-tts-card-extras {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 10px 20px;
padding-top: 10px;
border-top: 1px solid var(--amb-border);
}
.anomalous-tts-card-lines,
.anomalous-tts-card-lang {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 6px 10px;
min-width: 0;
}
.anomalous-tts-card-lines > .anomalous-tts-file {
padding: 2px 4px 2px 10px;
border: 1px solid var(--amb-border);
border-radius: 999px;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.2));
}
.anomalous-tts-card-lines .anomalous-tts-file-meta,
.anomalous-tts-card-lines .anomalous-tts-file-move {
display: none;
}
.anomalous-tts-card-extra-label {
color: var(--amb-text-muted);
font-size: 12px;
font-weight: 600;
}
.anomalous-tts-card-note {
color: var(--amb-text-muted);
font-size: 11.5px;
line-height: 1.6;
}
.anomalous-tts-card-problems {
display: flex;
flex-direction: column;
gap: 4px;
}
.anomalous-tts-card-problem {
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: 8px;
padding: 6px 10px;
border-radius: 8px;
background: rgba(245, 158, 11, 0.08);
color: var(--amb-warn);
font-size: 12px;
}
.anomalous-tts-card-problem[hidden] {
display: none;
}
.anomalous-tts-card-problem.is-blocking {
background: rgba(248, 113, 113, 0.08);
color: var(--amb-danger-text);
}
/* ---- footer ---- */
.anomalous-tts-footer {
align-items: center;
}
.anomalous-tts-footer > button {
flex-shrink: 0;
white-space: nowrap;
}
/* Nothing to import yet: the drop area is the whole window. */
.anomalous-tts-import.is-empty .anomalous-tts-footer {
display: none;
}
.anomalous-tts-footer-info {
display: flex;
flex: 1 1 auto;
flex-direction: column;
gap: 2px;
min-width: 0;
margin-right: auto;
}
.anomalous-tts-footer-summary {
color: var(--amb-warn);
font-size: 12px;
font-weight: 600;
}
.anomalous-tts-footer-summary[hidden] {
display: none;
}
.anomalous-tts-footer-path {
overflow: hidden;
color: var(--amb-text-dim);
font-size: 11px;
text-overflow: ellipsis;
white-space: nowrap;
}
@media (max-width: 700px) {
.anomalous-tts-step-label,
.anomalous-tts-card-meta,
.anomalous-tts-toolbar-hint {
display: none;
}
.anomalous-tts-check-item {
flex-wrap: wrap;
}
.anomalous-tts-file-top,
.anomalous-tts-file-bottom {
flex-wrap: wrap;
}
.anomalous-tts-file-bottom {
padding-left: 0;
}
}
.anomalous-tts-hint.is-error {
color: var(--amb-danger);
}
/* ---------- Dropping files on the studio ---------- */
.anomalous-audio-studio-wrapper.is-file-dragover {
position: relative;
outline: 2px dashed color-mix(in srgb, var(--amb-link) 60%, transparent);
outline-offset: -2px;
border-radius: 12px;
}
.anomalous-audio-studio-wrapper.is-file-dragover::after {
content: attr(data-drop-hint);
position: absolute;
top: 8px;
left: 50%;
z-index: 2;
padding: 6px 14px;
border-radius: 999px;
background: var(--amb-btn-primary-bg);
color: var(--amb-btn-primary-text);
font-size: 12px;
font-weight: 600;
white-space: nowrap;
transform: translateX(-50%);
pointer-events: none;
}
.anomalous-character-voice-card.is-just-added {
animation: ambTtsJustAdded 2.4s ease-out;
}
@keyframes ambTtsJustAdded {
0%, 40% { box-shadow: 0 0 0 2px var(--amb-ok); }
100% { box-shadow: 0 0 0 2px transparent; }
}
.anomalous-character-voice-card.is-file-target {
outline: 2px solid var(--amb-link);
outline-offset: 1px;
}