Files
DemonGatanjieuandClaude Opus 5.5 2a7cfe5075 Voice-over: three layers, whole script / character / line, and a draft
The side panel changes one layer at a time under a path (Whole script ›
character › line); each layer has the same rows (speed, tone, language),
each saying where its value comes from, with ↺ to follow the layer above.
The more particular wins: line, character, whole script, the character's
usual settings. The whole script's values go into the node's inputs and
only lines that differ get tags. Lasting settings are links at the foot.
The script is kept as a draft in this browser and comes back after a
reload; editing the text keeps unchanged lines' own settings.

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

815 lines
18 KiB
CSS
Raw Permalink 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.
/* The Voices page's Voice-over view (ui_script_page.js) and the script director it holds. */
#anomalous-script-panel {
flex: 1;
flex-direction: column;
min-height: 0;
overflow: hidden;
background: var(--amb-bg-page);
}
/* Characters | Voice-over, where the Characters view has its toolbar. */
.anomalous-script-topbar {
margin: 20px 20px 0;
}
.anomalous-script-host {
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
}
.anomalous-script-director-panel {
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
overflow: hidden;
}
.anomalous-script-director-panel [hidden] {
display: none;
}
/* Instead of the director: loading, no node pack, no characters yet. */
.anomalous-script-page-note {
display: flex;
flex: 1;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 14px;
padding: 40px 24px;
color: var(--amb-text-muted);
font-size: 13.5px;
text-align: center;
}
.anomalous-script-page-note p {
max-width: 420px;
margin: 0;
line-height: 1.6;
}
.anomalous-sd-body,
.anomalous-sd-main {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
/* Narrow: settings and the generate bar under the cards, never taking over the drawer. */
.anomalous-sd-side {
flex-shrink: 0;
max-height: 55%;
overflow-x: hidden;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 8px;
padding: 8px 16px 10px;
border-top: 1px solid var(--amb-border);
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.2));
}
/* Wide: cards take the full height, the generate side is a column beside them. */
.anomalous-script-director-panel.is-wide .anomalous-sd-body {
flex-direction: row;
}
/* About half the width by default; the divider changes it (ui_script_director.js). */
.anomalous-script-director-panel.is-wide .anomalous-sd-side {
width: var(--sd-side-width, 46%);
min-width: 320px;
max-width: calc(100% - 340px);
max-height: none;
padding: 12px 14px;
border-top: none;
}
.anomalous-sd-splitter {
display: none;
}
.anomalous-script-director-panel.is-wide .anomalous-sd-splitter {
display: block;
flex: 0 0 7px;
position: relative;
cursor: col-resize;
touch-action: none;
}
.anomalous-script-director-panel.is-wide .anomalous-sd-splitter::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 3px;
width: 1px;
background: var(--amb-border);
}
.anomalous-script-director-panel.is-wide .anomalous-sd-splitter:hover::after {
left: 2px;
width: 3px;
background: color-mix(in srgb, var(--amb-link) 60%, transparent);
}
.anomalous-sd-header {
padding: 12px 16px 2px;
}
.anomalous-sd-subtitle {
margin: 0;
color: var(--amb-text-muted);
font-size: 13px;
line-height: 1.6;
}
/* Script input */
.anomalous-sd-input-area {
padding: 12px 16px;
display: flex;
flex-direction: column;
gap: 10px;
flex: 1;
min-height: 0;
}
.anomalous-sd-textarea {
width: 100%;
flex: 1;
min-height: 160px;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.2));
border: 1px solid var(--amb-border);
border-radius: 6px;
padding: 10px;
color: var(--amb-text-soft);
font-size: 13px;
line-height: 1.6;
resize: none;
box-sizing: border-box;
}
.anomalous-sd-input-actions {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 8px;
}
.anomalous-sd-btn {
background: rgba(var(--amb-ink-rgb), 0.05);
border: 1px solid var(--amb-border);
color: var(--amb-text-main);
padding: 6px 12px;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
white-space: nowrap;
transition: background 0.2s ease, border-color 0.2s ease;
}
.anomalous-sd-btn:hover:not(:disabled) {
background: rgba(var(--amb-ink-rgb), 0.1);
}
.anomalous-sd-btn:disabled {
opacity: 0.45;
cursor: not-allowed;
}
.anomalous-sd-btn.primary {
background: color-mix(in srgb, var(--amb-link) 10%, transparent);
color: var(--amb-link);
border-color: color-mix(in srgb, var(--amb-link) 25%, transparent);
}
.anomalous-sd-btn.primary:hover:not(:disabled) {
background: color-mix(in srgb, var(--amb-link) 20%, transparent);
}
.anomalous-sd-btn.accent {
background: color-mix(in srgb, var(--amb-link) 18%, transparent);
color: var(--amb-link);
border-color: color-mix(in srgb, var(--amb-link) 35%, transparent);
font-weight: 600;
}
.anomalous-sd-btn.accent:hover:not(:disabled) {
background: color-mix(in srgb, var(--amb-link) 30%, transparent);
}
.anomalous-sd-btn.is-success {
background: rgba(16, 185, 129, 0.2);
border-color: rgba(16, 185, 129, 0.45);
color: var(--amb-ok-soft);
}
/* Lines */
.anomalous-sd-lines-bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 16px 0;
font-size: 12px;
color: var(--amb-text-muted);
}
.anomalous-sd-link-btn {
background: none;
border: none;
padding: 0;
color: var(--amb-link);
font-size: 12px;
cursor: pointer;
}
.anomalous-sd-link-btn:hover {
text-decoration: underline;
}
.anomalous-sd-scroll {
flex: 1;
min-height: 120px;
overflow-y: auto;
padding: 10px 16px;
display: flex;
flex-direction: column;
gap: 8px;
}
.anomalous-sd-lines-container {
display: flex;
flex-direction: column;
gap: 8px;
}
.anomalous-sd-line-card {
background: rgba(var(--amb-ink-rgb), 0.03);
border: 1px solid var(--amb-border);
border-radius: 8px;
padding: 8px 10px 10px;
display: flex;
flex-direction: column;
gap: 6px;
}
.anomalous-sd-line-card:focus-within {
border-color: color-mix(in srgb, var(--amb-link) 35%, transparent);
}
/* Lines picked to give to a character (ui_script_cast.js), and who reads each once several do. */
.anomalous-sd-line-card.is-picked {
border-color: color-mix(in srgb, var(--amb-link) 75%, transparent);
background: color-mix(in srgb, var(--amb-link) 13%, transparent);
}
.anomalous-sd-line-card.has-speaker {
border-left: 3px solid var(--speaker);
}
/* The text as read (ui_script_cards.js): a click picks the card, a double-click edits it. */
.anomalous-sd-line-words {
padding: 3px 5px;
border: 1px solid transparent;
color: var(--amb-text-main);
font-size: 13px;
line-height: 1.6;
overflow-wrap: anywhere;
white-space: pre-wrap;
cursor: default;
user-select: none;
}
.anomalous-sd-line-words.is-empty {
color: var(--amb-text-dim);
}
.anomalous-sd-line-card.is-editing {
border-color: color-mix(in srgb, var(--amb-link) 55%, transparent);
}
/* Right after the number (above the rule that sends the head's buttons after the text). */
.anomalous-sd-line-card > .anomalous-sd-line-head > .anomalous-sd-speaker {
order: 0;
max-width: 120px;
overflow: hidden;
padding: 1px 8px;
border-radius: 999px;
border: none;
background: color-mix(in srgb, var(--speaker) 24%, transparent);
color: var(--amb-text-main);
font: inherit;
font-size: 11px;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
.anomalous-sd-line-head > .anomalous-sd-speaker:hover {
background: color-mix(in srgb, var(--speaker) 40%, transparent);
}
/* The characters to read a line, under its name (ui_script_cards.js). */
.anomalous-sd-speaker-menu {
position: fixed;
z-index: 10050;
display: flex;
flex-direction: column;
min-width: 150px;
max-height: 320px;
overflow-y: auto;
padding: 4px;
border: 1px solid var(--amb-border-strong);
border-radius: 8px;
background: var(--amb-bg-float, var(--amb-bg-dialog));
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}
.anomalous-sd-speaker-item {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 10px;
border: none;
border-radius: 6px;
background: none;
color: var(--amb-text-soft);
font: inherit;
font-size: 12px;
text-align: left;
cursor: pointer;
}
.anomalous-sd-speaker-item:hover,
.anomalous-sd-speaker-item.is-current {
background: rgba(var(--amb-ink-rgb), 0.07);
color: var(--amb-text-main);
}
.anomalous-sd-speaker-dot {
flex-shrink: 0;
width: 9px;
height: 9px;
border-radius: 50%;
}
/* Whose lines a paste makes (the character picked in the cast). */
.anomalous-sd-paste-for {
margin-bottom: 6px;
color: var(--amb-text-soft);
font-size: 12px;
}
.anomalous-sd-cast-hint {
flex: 1;
min-width: 0;
margin: 0 10px;
color: var(--amb-text-dim);
font-size: 11px;
}
/* The line heard on the right (ui_script_run.js): marked, with a word saying so. */
.anomalous-sd-line-card.is-listen {
border-color: color-mix(in srgb, var(--amb-link) 55%, transparent);
background: color-mix(in srgb, var(--amb-link) 6%, transparent);
}
/* ▶ hears the line in the mode picked on the side: on the card you are on, and on hover. */
.anomalous-sd-line-play {
opacity: 0;
color: var(--amb-link);
transition: opacity 0.15s ease;
}
.anomalous-sd-line-card:hover .anomalous-sd-line-play,
.anomalous-sd-line-card.is-listen .anomalous-sd-line-play {
opacity: 1;
}
@media (hover: none) {
.anomalous-sd-line-play {
opacity: 1;
}
}
/* One row per line: number, text, then its buttons; the emotion chips under it when there is a choice. */
.anomalous-sd-line-card {
flex-direction: row;
flex-wrap: wrap;
align-items: center;
gap: 4px 6px;
padding: 6px 8px;
}
.anomalous-sd-line-head {
display: contents;
}
/* The text takes what is left, so the buttons never wrap to a row of their own. */
.anomalous-sd-line-card > .anomalous-sd-line-text,
.anomalous-sd-line-card > .anomalous-sd-line-words {
order: 1;
flex: 1 1 0;
width: auto;
min-width: 0;
}
.anomalous-sd-line-head > :not(.anomalous-sd-line-no) {
order: 2;
}
.anomalous-sd-line-card > .anomalous-sd-emotion-row {
order: 3;
flex-basis: 100%;
}
/* Split, merge and delete show on the card you are on; another take of a line stays in view. */
.anomalous-sd-line-head .anomalous-sd-icon-btn.is-edit {
opacity: 0;
transition: opacity 0.15s ease;
}
.anomalous-sd-line-card:hover .anomalous-sd-icon-btn.is-edit,
.anomalous-sd-line-card:focus-within .anomalous-sd-icon-btn.is-edit {
opacity: 1;
}
@media (hover: none) {
.anomalous-sd-line-head .anomalous-sd-icon-btn.is-edit {
opacity: 1;
}
}
.anomalous-sd-line-no {
flex: 0 0 auto;
min-width: 22px;
font-size: 11px;
font-family: monospace;
color: var(--amb-text-dim);
}
.anomalous-sd-icon-btn {
width: 22px;
height: 22px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 50%;
border: 1px solid var(--amb-border);
background: rgba(var(--amb-ink-rgb), 0.04);
color: var(--amb-text-muted);
font-size: 14px;
line-height: 1;
cursor: pointer;
}
.anomalous-sd-icon-btn:hover,
.anomalous-sd-icon-btn.is-playing {
color: var(--amb-link);
border-color: color-mix(in srgb, var(--amb-link) 40%, transparent);
}
.anomalous-sd-icon-btn.is-danger:hover {
color: var(--amb-danger);
border-color: rgba(248, 113, 113, 0.4);
}
.anomalous-sd-line-text {
width: 100%;
box-sizing: border-box;
field-sizing: content;
min-height: 1.6em;
background: transparent;
border: 1px solid transparent;
border-radius: 4px;
padding: 2px 4px;
color: var(--amb-text-main);
font: inherit;
font-size: 13px;
line-height: 1.6;
resize: none;
}
.anomalous-sd-line-text:hover,
.anomalous-sd-line-text:focus {
border-color: var(--amb-border);
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.2));
outline: none;
}
.anomalous-sd-emotion-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 5px;
}
/* The chosen emotion's reference clip: how the voice sounds, beside the chips it belongs to. */
.anomalous-sd-ref-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
border: none;
border-radius: 50%;
background: transparent;
color: var(--amb-text-dim);
cursor: pointer;
}
.anomalous-sd-ref-btn:hover:not(:disabled),
.anomalous-sd-ref-btn.is-playing {
color: var(--amb-link);
background: color-mix(in srgb, var(--amb-link) 12%, transparent);
}
.anomalous-sd-ref-btn:disabled {
opacity: 0.35;
cursor: default;
}
.anomalous-sd-emotion-chip {
padding: 2px 9px;
border-radius: 999px;
border: 1px solid var(--amb-border);
background: rgba(var(--amb-ink-rgb), 0.04);
color: var(--amb-text-muted);
font-size: 11px;
cursor: pointer;
transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.anomalous-sd-emotion-chip:hover {
color: var(--amb-text-main);
border-color: color-mix(in srgb, var(--amb-link) 40%, transparent);
}
.anomalous-sd-emotion-chip.active {
background: color-mix(in srgb, var(--amb-link) 30%, transparent);
border-color: var(--amb-link);
color: var(--amb-text-main);
font-weight: 600;
}
.anomalous-sd-emotion-chip.is-main.active {
background: rgba(16, 185, 129, 0.22);
border-color: rgba(52, 211, 153, 0.7);
}
/* Generating here is the main way: its button stands out. */
.anomalous-sd-run-actions > .anomalous-sd-btn.accent:first-child {
padding: 7px 18px;
font-size: 13px;
font-weight: 600;
}
/* Into your own workflow: below generating, quieter. */
.anomalous-sd-workflow {
display: flex;
flex-direction: column;
gap: 6px;
padding-top: 10px;
border-top: 1px solid var(--amb-border);
}
.anomalous-sd-workflow-title {
color: var(--amb-text-dim);
font-size: 11.5px;
cursor: pointer;
}
/* Bundle */
.anomalous-sd-footer {
display: flex;
flex-direction: column;
gap: 8px;
}
.anomalous-sd-package-summary {
font-size: 12px;
color: var(--amb-text-soft);
}
.anomalous-sd-package-summary.is-error {
color: var(--amb-warn);
}
.anomalous-sd-package-actions {
display: flex;
align-items: center;
gap: 8px;
}
/* Generating happens in the run section; the canvas buttons stay a small row. */
.anomalous-sd-package-actions .anomalous-sd-btn {
padding: 3px 8px;
font-size: 11px;
}
.anomalous-sd-drag-handle {
flex: 1;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 3px 8px;
border-radius: 6px;
border: 1px dashed color-mix(in srgb, var(--amb-link) 50%, transparent);
background: color-mix(in srgb, var(--amb-link) 8%, transparent);
color: var(--amb-link);
font-size: 11px;
cursor: grab;
user-select: none;
}
.anomalous-sd-drag-handle:active {
cursor: grabbing;
}
.anomalous-sd-drag-handle.is-disabled {
opacity: 0.4;
cursor: not-allowed;
}
.anomalous-sd-emotion-chip.is-missing {
border-style: dashed;
border-color: rgba(251, 191, 36, 0.7);
color: var(--amb-warn);
background: rgba(245, 158, 11, 0.1);
}
.anomalous-sd-split-mode {
margin-right: auto;
min-width: 0;
background: var(--amb-lt-sunken, rgba(0, 0, 0, 0.3));
border: 1px solid var(--amb-border-strong);
border-radius: 6px;
color: var(--amb-text-soft);
font-size: 12px;
padding: 5px 6px;
}
.anomalous-sd-add-line {
align-self: stretch;
padding: 7px;
border-radius: 8px;
border: 1px dashed var(--amb-border-strong);
background: transparent;
color: var(--amb-text-muted);
font-size: 12px;
cursor: pointer;
}
.anomalous-sd-add-line:hover {
color: var(--amb-text-main);
border-color: color-mix(in srgb, var(--amb-link) 45%, transparent);
}
/* Generate here (GPT-SoVITS): ui_script_run.js */
.anomalous-sd-run {
display: flex;
flex-direction: column;
gap: 6px;
}
.anomalous-sd-run-hint {
font-size: 11px;
line-height: 1.5;
}
.anomalous-sd-run-hint.is-warning {
color: var(--amb-warn);
}
.anomalous-sd-run-actions {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
/* How it is read: the side panel's layers (ui_script_tune.js; their rows in 34-voice-over-panel.css). */
.anomalous-sd-run-settings {
display: flex;
flex-direction: column;
gap: 8px;
padding-top: 10px;
border-top: 1px solid var(--amb-border);
}
.anomalous-sd-run-label {
display: flex;
flex-direction: column;
flex-shrink: 0;
width: 44px;
color: var(--amb-text-soft);
font-size: 12px;
line-height: 1.35;
}
.anomalous-sd-run-segment {
display: inline-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-sd-run-choice {
padding: 3px 10px;
border: none;
border-radius: 6px;
background: transparent;
color: var(--amb-text-muted);
font: inherit;
font-size: 12px;
cursor: pointer;
}
.anomalous-sd-run-choice:hover:not(:disabled) {
color: var(--amb-text-main);
}
.anomalous-sd-run-choice[aria-checked="true"] {
background: color-mix(in srgb, var(--amb-link) 18%, transparent);
color: var(--amb-text-main);
font-weight: 600;
}
.anomalous-sd-run-choice:disabled {
opacity: 0.6;
cursor: default;
}
.anomalous-sd-run-slider {
flex: 1;
min-width: 0;
accent-color: var(--amb-link);
}
.anomalous-sd-run-value {
width: 32px;
color: var(--amb-text-main);
font-size: 12px;
font-variant-numeric: tabular-nums;
text-align: right;
}
/* The pronunciation editor's language picker (ui_tts_pronunciation.js). */
.anomalous-sd-run-select {
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-sd-run-links {
display: flex;
flex-wrap: wrap;
gap: 4px 14px;
}
.anomalous-sd-run-note {
margin: 0;
font-size: 11px;
line-height: 1.5;
color: var(--amb-text-muted);
}
.anomalous-sd-run-status {
font-size: 12px;
color: var(--amb-text-soft);
}
/* "Saved to the audio gallery ›": the file's path is its tooltip. */
.anomalous-sd-run-saved {
align-self: flex-start;
}
.anomalous-sd-run-warnings {
max-height: 60px;
overflow-y: auto;
font-size: 11px;
color: var(--amb-warn);
white-space: pre-wrap;
}
.anomalous-sd-run-player {
width: 100%;
height: 32px;
}
.anomalous-sd-take-no {
margin-left: 2px;
font-size: 10px;
color: var(--amb-link);
}